Термометр на контроллере

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Аватара пользователя
mollari
Родился
Сообщения: 3
Зарегистрирован: Вт июн 07, 2011 14:38:07

Термометр на контроллере

Сообщение mollari »

Доброго всем дня! Я только начинаю изучать avr asm и поэтому часто долгими вечерами исправляю свои косяки, что не всегда выходит. Вот один из таких случаев:
Решил я собрать термометр на tiny2313 на датчике DS1820, взял за основу статью http://radiokot.ru/circuit/digital/home/12/
Кварц мне нужен на 10МГц поэтому пришлось переделать процедуры задержки. Вывод температуры хочу произвести на лапках PortB (это пока, в планах дисплейчик приколхозить, но надо еще разобраться что и как с ним делать), т.е. двоичное число, соответствующее температуре. Короче говоря, я пытался немного переделать под нужды моего проекта, но Proteus был против...
Может быть кот ученый сможет мне подсказать...
Программа:
  • .include "2313def.inc"
    .include "ds1820.inc" ;команды датчика


    .def rot = r17
    .def Temp = r16
    .def Temp1 = r18
    .def Temp2 = r19
    .def Temp3 = r20
    .def Temp4 = r21

    .dseg
    buffer: .byte 9 ;9 байт буфера приема
    CRC: .byte 1 ;расчитываемая контр.сумма

    .cseg
    .org 0

    rjmp Reset ;вектора прерываний
    rjmp INT_0
    rjmp INT_1
    rjmp Timer1_capt1
    rjmp Timer1_comp1
    rjmp Timer1_OVF1
    rjmp Timer0_OVF0
    rjmp UART_RX
    rjmp UART_UDRE
    rjmp UART_TX
    rjmp ANA_COMP


    ;Reset:
    INT_0:
    INT_1:
    Timer1_capt1:
    ;Timer1_comp1:
    Timer1_OVF1:
    Timer0_OVF0:
    UART_RX:
    UART_UDRE:
    UART_TX:
    ANA_COMP:
    reti

    ;==========
    .macro Send_1w
    ;отправка в линию 1-Wire
    ldi Temp, @0 ;первый параметр
    mov r0, Temp
    rcall Send1w ; вывод
    .endmacro
    ;==========
    .macro popf ;извлечение SREG
    pop Temp
    out SREG, Temp
    pop Temp
    .endmacro

    .macro pushf ;сохранение SREG
    push Temp
    in Temp, SREG
    push Temp
    .endmacro
    ;==========

    ;*********************************************************************
    ; задержка в X мкс
    ;*********************************************************************
    .macro delayXmks ;присваиваем имя макросу - « delay »

    ldi XL,Low (@0) ;Загрузить младший байт константы времени
    ldi XH,high(@0) ;Загрузить старший байт константы времени
    delay_:
    ldi Temp1,4
    Loop: dec Temp1 ;в сумме это 10 команд, которые будут выполняться X раз, т.е. X мкс
    brne Loop
    sbiw XL,1 ;вычитаем единицу из двухбайтного слова загруженного в регистровую пару Х
    brne delay_

    .endm ;конец макроса

    ;*********************************************************************
    ; задержка в X мс
    ;*********************************************************************
    .macro delayXms ;присваиваем имя макросу - « delay »
    ldi YL,Low (@0) ;Загрузить младший байт константы времени
    ldi YH,high(@0) ;Загрузить старший байт константы времени
    delay_1:
    delayXmks 1000
    sbiw YL,1 ;вычитаем единицу из двухбайтного слова загруженного в регистровую пару Х
    brne delay_1

    .endm ;конец макроса


    ;****************************************************
    ; ИНИЦИАЛИЗАЦИЯ
    ;****************************************************
    Reset: ldi Temp,0 ;настройка портов
    out DDRD,Temp

    ldi Temp,0b11111111 ;настройка портов
    out DDRB,Temp

    ldi Temp,0b01000000 ;разрешить прерывание компаратора
    out TIMSK,Temp

    ldi Temp,0b00000100 ;тактовый сигнал = CK/256
    out TCCR1B,Temp

    ldi Temp,0x5B ;инициализация компаратора
    out OCR1AH,Temp
    ldi Temp,0x8E
    out OCR1AL,Temp

    ldi Temp,RamEnd ;установка указателя стека
    out SPL,Temp

    ldi Temp,0 ;обнуление таймера
    out TCNT1H,Temp
    out TCNT1L,Temp
    ldi temp2,5 ;это регистр, благодаря которому только 5-ое прерывание компаратора работает
    sei ;разрешить прерывания



    ;****************************************************
    ; ОСНОВНОЙ ЦИКЛ
    ;****************************************************
    Inf:

    ;Тут у меня в планах всякие примочки

    rjmp Inf




    ;****************************************************
    ; измерение температуры 1 датчика
    ;****************************************************
    termo:
    rcall reset1w ; сброс 1-Wire
    breq presented ; есть датчик ?
    error:
    ; нету датчика или сбой обмена 1-Wire
    ;------------------------------------
    ldi temp1,0b10101010
    out PortB,temp1 ;ну чтобы знать что ошибка
    ret ; повторяем сначала
    presented:
    ; есть датчик
    Send_1w CMD_SKIP_ROM ; команда "пропустить адрес"
    Send_1w CMD_CONVERT_T ; команда "измерить температуру"
    delayXms 1000 ; ждем 1 секунду, т.к. измеряется долго
    ; получение результата измерения температуры
    rcall reset1w ; сброс 1-Wire
    Send_1w CMD_SKIP_ROM ; команда "пропустить адрес"
    Send_1w CMD_R_SCRATCHPAD ; команда "считывание регистров"
    rcall readbytes1w ; получаем данные
    tst r0 ; r0 - результат обмена
    brne error ; если ошибка - перейдем к индикации ошибки
    ;выводы
    ret
    ;****************************************************
    ; ОБРАБОТЧИК ПРЕРЫВАНИЯ КОМПАРАТОРА
    ;****************************************************

    Timer1_comp1:
    cli
    dec temp2
    brne endtimer
    rcall termo
    ;полезный код. Rot*100 - обороты в минуту

    lds Temp, Buffer
    out PortB,temp


    ldi rot,0 ;обнуление числа оборотов
    ldi Temp,0 ;обнуление таймера
    out TCNT1H,Temp
    out TCNT1L,Temp
    ldi temp2,5
    sei
    reti
    endtimer:

    sei
    reti ;выход из обработчика


    ;#####################################################
    ;#################### 1-WIRE #######################
    ;#####################################################


    .equ wireport = DDRD;
    .equ wirepin = PinD; ; порт сигнальных линий
    .equ wirebit = 5 ; номер линии порта


    .def wiretemp = r22 ; регистр под нужды 1-wire
    .def wireres = r2 ; обязательно из числа r0...r15

    .macro wire1;
    cbi wireport, wirebit ; 0->DDR = Z-состояние
    .endmacro;

    .macro wire0;
    sbi wireport, wirebit ; 1->DDR = 0 на выходе
    .endmacro;

    ;*********************************************************************
    reset1w:
    ; выполняет выдачу сброса в линию 1-wire и возврат состояния PRESENCE
    ; вход: ничего
    ; выход: флаг Z установлен, если был PRESENCE
    ; так как длительность RESET может быть любой, прерывания не запрещаются,
    ; если это не необходимо
    wire1
    sbis wirepin, wirebit ; проверим наличие 1 в линии
    rjmp presence_fault ; если нет - это ошибка
    wire0 ; давим линию в 0
    delayXmks 480 ; 480 микросекунд задержка
    wire1 ; линию в 1
    delayXmks 60 ; 60 микросекунд задержка
    ; начинаем ждать PRESENCE

    ldi wiretemp, 250 ; Тут примерно 1с должно быть
    rw1_wait:
    sbis wirepin, wirebit
    rjmp presence_ok
    delayXmks 1
    dec wiretemp
    brne rw1_wait

    ldi wiretemp, 250
    rw2_wait:
    sbis wirepin, wirebit
    rjmp presence_ok
    delayXmks 1
    dec wiretemp
    brne rw2_wait

    ldi wiretemp, 125;
    rw3_wait:
    sbis wirepin, wirebit
    rjmp presence_ok
    delayXmks 1
    dec wiretemp
    brne rw3_wait


    presence_fault:
    ; сюда мы попадаем, если не дождались PRESENCE
    clz ; сбрасываем Z-флаг
    ret
    presence_ok:
    ; PRESENCE получен
    sez
    delayXmks 480 ; 480 микросекунд задержка
    ret ; Z-флаг и так стоит

    ;*********************************************************************

    resive1w:
    ; выполняет прием байта из линии
    ; вход: ничего
    ; выход: r0 - принятый байт
    ;ldi wiretemp, 0xFF
    ser wiretemp
    mov r0, wiretemp
    ;*********************************************************************


    send1w:
    ; выполняет передачу байта в линию
    ; вход: R0 - выводимый байт
    ; выход: R0 - то, что удалось ВВЕСТИ из линии
    ; портит: R0
    ; примечание: если делать ВЫВОД 0хFF, то на выходе будет ПРИНЯТЫЙ байт
    ldi wiretemp, 8 ; число битов в байте

    sw1_next:
    pushf ; сохраним флаги, т.к. будем запрещать
    cli ; запрещаем прерывания
    wire0 ; давим линию в 0
    delayXmks 1 ; 1 мкс задержки
    ror r0 ; выталкиваем выводимый бит
    brcc s0 ; если бит C = 0 - обход
    wire1 ; линию в 1
    s0:
    push wiretemp
    ldi wiretemp, 9 ; в некоторых случаях может потребоваться
    ; увеличить это значение, но не более 13!
    sw1_wait:
    delayXmks 1
    dec wiretemp
    brne sw1_wait
    clc
    sbic wirepin, wirebit
    sec
    ror wireres
    delayXmks 90 ; 90 микросекунд - длительность тайм-слота
    wire1
    pop wiretemp
    popf
    dec wiretemp
    brne sw1_next
    mov r0, wireres
    ret

    ;*********************************************************************

    readbytes1w:
    ; считывает 9 байтов в буфер, подсчитывает CRC
    ; портит r0 и SREG, регистры X и Z
    clr wiretemp
    sts CRC, wiretemp ; обнуляем CRC
    ldi XL, low(Buffer)
    ldi XH, high(Buffer)
    ldi wiretemp, 9
    r1w_next:
    push wiretemp
    rcall resive1w ; считываем 1 байт
    ; r0=считанному байту, начинаем подсчет CRC
    st X+, r0 ; сохраняем принятый байт
    rcall crc8 ; считаем контрольную сумму
    pop wiretemp
    dec wiretemp
    brne r1w_next
    ret
    ;*********************************************************************




    crc8:
    push r0
    ldi wiretemp, 8
    mov wireres,wiretemp
    r1w_loop_crc:
    lds wiretemp, CRC
    eor r0, wiretemp
    ror r0
    mov r0, wiretemp
    brcc zero
    ldi wiretemp, 0x18
    eor r0, wiretemp
    zero:
    ror r0
    sts CRC, r0
    pop r0
    ; 4 следующие команды делают циклический сдвиг r0
    push r0
    ror r0
    pop r0
    ror r0
    ; сдвиг закончен - очень удобно, не правда ли?!
    push r0
    dec wireres
    brne r1w_loop_crc
    pop r0
    lds r0, CRC
    ret
Реклама
Аватара пользователя
kvb48
Потрогал лапой паяльник
Сообщения: 321
Зарегистрирован: Пн июн 21, 2010 18:39:28

Re: Термометр на контроллере

Сообщение kvb48 »

Это надо скорее всего на тему "Микроконтроллеры и ПЛИС"
Реклама
Аватара пользователя
mollari
Родился
Сообщения: 3
Зарегистрирован: Вт июн 07, 2011 14:38:07

Re: Термометр на контроллере

Сообщение mollari »

kvb48 писал(а):Это надо скорее всего на тему "Микроконтроллеры и ПЛИС"
Ага, я первоначально туда и хотел, но потом подумал что статья из обучалки, и поместил сообщение сюда... перенести бы его... а то плодить одно и то же как то не хочется
По делу: кажется у меня не правильно подсчитывается контрольная сумма или прием результатов
PS: а Proteus нормально эмулирует ds1820? Т.е. может в реале попробовать?
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»