Код термометра не работает при переносе с Mega32 на Tiny2313

Обсуждаем контроллеры компании Atmel.
Ответить
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Доброго времени суток. Решил сделать себе термометр для бойлера. Готовые прошивки не интересны, есть мысль, что удасться лучше понять азы программирования, хотя бы ковыряясь в чужом коде, а не просто заливая готовые прошивки, поэтому искал исходники. Неприменно не ассемблере, потому что потихоньку учу его. Нашел по адресу https://sites.google.com/site/skyersoft/avr-examples
Скачал оттуда пример для Меги32 и портировал его на Тини2313А. Подправил кое-что и оно завелось и засветилось, но увы работает не совсем корректно. Вобщем все примерно соответствует первому посту этой темы http://radiokot.ru/forum/viewtopic.php?f=61&t=64022 Датчик реагирует на изминения температуры, но показывает неверное значения, сейчас дома около +28, а показывает +2 градуса. При зажимании датчика между пальцами, быстро подскакивает чуть ли до +40. Но у меня датчик DS18B20, а не просто DS1820 или DS18S20. Что я сделал не так ? Или изначальный код примера с ошибкой ? К сожаления самому проверить последний вопрос не представляеться возможным, в связи с отсутствием у меня Меги 32(16).
Мой вариант под спойлером. Пишу в АВР Студио 4.19
Спойлер.include "tn2313Adef.inc" ; Use AtTiny2313A

; Macro ======
; End macro ======

; RAM ======
.DSEG

.equ XTAL = 8000000
.equ BaudRate = 9600
.equ BaudDivider = XTAL/(16*BaudRate)-1

.def Temp1=R16
.def Temp2=R17
.def Temp3=R18
.def Temp4=R19
.def Flag=R20
;R25 assigned for 1-wire

TempDigit: .byte 2

; End RAM ======

; FLASH
.CSEG

.ORG 0
RJMP Reset ; Reset Handler
.ORG 0x0E
RJMP TIM1_COMPA ; Timer1 CompareA Handler

.include "DS1820.asm" ; Unit for DS18B20


; Interrupts ======
TIM1_COMPA:
LDI R16,0
OUT TCNT1H,R16
OUT TCNT1L,R16
RCALL GetTemp
RETI
; End Interrupts ======

; Reset and Initialization ======
RESET:
; Stack Pointer Initialization

LDI R16,RAMEND
OUT SPL,R16

; Variables Init
LDI R16,0
STS TempDigit,R16
STS TempDigit+1,R16
LDI Flag,0

; Configure I/O Ports
LDI R16,0xFF
OUT DDRB,R16 ;PortB полностью на вывод, для выводов A-G 7-сегментного индикатора
LDI R16,0b0111111
OUT DDRD,R16 ;PortD тоже не вывод, для общих проводов индикатора, но оставяем вывод PD6 на вход для датчика DS18B20
OUT PortD,R16

; Configure Timer, prescaler 1/256, compare to 0x7A12
LDI R16, (1<<OCIE1A)
OUT TIMSK,R16

LDI R16, (1<<CS12)
OUT TCCR1B,R16

LDI XL,LOW(0x7A12)
LDI XH,HIGH(0x7A12)
OUT OCR1AH,XH
OUT OCR1AL,XL

LDI R16,0
OUT TCNT1H,R16
OUT TCNT1L,R16

; Enable Interrupts Globally

SEI

; End Reset and Initialization ======

; Main ======
Main:

RCALL Display
RJMP Main

; End Main ======

; Procedure ======
Decoder:
LDI ZL,Low(DcMatrix*2)
LDI ZH,High(DcMatrix*2)
ADD ZL,Temp1
LDI Temp2,0
ADC ZH,Temp2

LPM Temp1,Z
RET


DcMatrix:
; hgfedcba hgfedcba
.db 0b00111111,0b00000110 ;0,1
.db 0b01011011,0b01001111 ;2,3
.db 0b01100110,0b01101101 ;4,5
.db 0b01111101,0b00000111 ;6,7
.db 0b01111111,0b01101111 ;8,9


TempTable:

.db 0b00000000,0b00000000;0,0,0,0
.db 0b00000000,0b00000110;0,6,2,5
.db 0b00000001,0b00000010;1,2,5,0
.db 0b00000001,0b00001000;1,8,7,5
.db 0b00000010,0b00000101;2,5,0,0
.db 0b00000011,0b00000001;3,1,2,5
.db 0b00000011,0b00000111;3,7,5,0
.db 0b00000100,0b00000011;4,3,7,5
.db 0b00000101,0b00000000;5,0,0,0
.db 0b00000101,0b00000110;5,6,2,5
.db 0b00000110,0b00000010;6,2,5,0
.db 0b00000110,0b00001000;6,8,7,5
.db 0b00000111,0b00000101;7,5,0,0
.db 0b00001000,0b00000001;8,1,2,5
.db 0b00001000,0b00000111;8,7,5,0
.db 0b00001001,0b00000011;9,3,7,5

Delay:
LDI Temp1,0
LDI Temp2,4
Dll:
DEC Temp1
BRNE Dll
DEC Temp2
BRNE Dll
RET


Display:
/* LDI Temp1,0b00111110 ;Не знаю что делают это строки !!!
OUT PortD,Temp1
MOV Temp1,Flag
ANDI Temp1,0b01000000
OUT PortB,Temp1
RCALL Delay */



LDI Temp1,0b0101111 ;Выводим десятки градусов на вывод PD4
OUT PortD,Temp1
LDS Temp1,TempDigit+1
RCALL Decoder
ORI Temp1,0b10000000
OUT PortB,Temp1
RCALL Delay

LDI Temp1,0b0011111 ;Выводим еденицы градусов на вывод PD5
OUT PortD,Temp1
LDS Temp1,TempDigit
RCALL Decoder
OUT PortB,Temp1
RCALL Delay


RET

GetTemp:
; Reset 1-wire
RCALL Init_1W
; Skip address
LDI Temp1,CMD_SKIP_ROM
MOV R0, Temp1
RCALL Send_1W
; Read ScratchPad
LDI Temp1,CMD_R_SCRATCHPAD
MOV R0, Temp1
RCALL Send_1W
; Read bytes
RCALL ReadBytes_1w
; Reset 1-wire
RCALL Init_1W
; Skip address
LDI Temp1,CMD_SKIP_ROM
MOV R0, Temp1
RCALL Send_1W
; Convert temperature
LDI Temp1,CMD_CONVERT_T ; команда "измерить температуру"
MOV R0, Temp1
RCALL Send_1W


LDI Temp1,0
STS TempDigit,Temp1
STS TempDigit+1,Temp1

ANDI Flag,0b10111111

;***********************************************************
; Integer
LDS Temp2,Buffer ; Load LS
LDS Temp1,Buffer+1 ; Load MS

CPI Temp1,0x08
BRLO IsPlus
NEG Temp2
COM Temp1
STS Buffer,Temp2
STS Buffer+1,Temp1
ORI Flag,0b01000000

IsPlus:

ANDI Temp2, ~(0x0F)
OR Temp2, Temp1
SWAP Temp2

LDI Temp1, 0
IntLoop:
CPI Temp2,10
BRLO IntNext
SUBI Temp2,10
INC Temp1
RJMP IntLoop
IntNext:
STS TempDigit+1,Temp2

;***********************************************************
; Frac
LDS Temp3,Buffer ; Load LS
ANDI Temp3,0x0F ; Оставили дробную часть
; Умножая ее на 0.0625 получим табличное значение

LDI ZL,LOW(TempTable*2)
LDI ZH,HIGH(TempTable*2)

CLR R24
ADD ZL,Temp3
ADC ZH,R24

ADD ZL,Temp3
ADC ZH,R24

LPM Temp1,Z+
LPM Temp2,Z+

CPI Temp2,5
BRLO FracAdd
BREQ FracAdd

INC Temp1
FracAdd:
STS TempDigit,Temp1

GetTempExit:
ret
; End Procedure ======
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15752
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

У датчиков ( DS18S20, DS18B20) разное назначение и/или содержимое ячеек с одинаковыми адресами - нужно привести программу в соответствие с картой применяемого датчика.
8)
Реклама
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Так в том то и дело, что в примере указано, что он для датчика DS18B20, и датчик у меня DS18B20, а работает так, как будто я использую датчик DS1820. И у меня закрались сомнения, по поводу того что код работы с датчиком
Спойлер; команды для работы с датчиком DS18В20
;.equ CMD_SEARCH_ROM = 0xF0 ; поиск адресов всех устройств по спецалгоритму
.equ CMD_READ_ROM = 0x33 ; считываение адреса единственного устройства
;.equ CMD_MATCH_ROM = 0x55 ; активация конкретного устройства по его адресу
.equ CMD_SKIP_ROM = 0xCC ; обращение к единственному на шине устройству без указания его адреса
;.equ CMD_ALARM_SEARCH = 0xEC ; поиск устройств, у которых сработал ALARM (алгоритм поиска как у CMD_SERCH_ROM)
.equ CMD_CONVERT_T = 0x44 ; старт преобразования температуры
.equ CMD_W_SCRATCHPAD = 0x4E ; запись во внутренний буфер (регистры)
.equ CMD_R_SCRATCHPAD = 0xBE ; чтение внутреннего буфера (регистров)
;.equ CMD_C_SCRATCHPAD = 0x48 ; сохранение регистров в EEPROM
;.equ CMD_RECALL_EE = 0xB8 ; заносит в буфер из EEPROM значение порога ALARM
;.equ CMD_READ_POWER = 0xB4 ; определение, есть ли в шине устройства с паразитным питанием

;используемые порты и регистры
;перед началом работы необходимо настроить выбранную линию порта
;на работу в качестве входа без подтягивающего резистора, т. е. DDRx=0 PORTx=0
.equ wireport = DDRD ; порт вывода 1-Wire
.equ wirepin = PinD; ; порт сигнальных линий 1-Wire
.equ wirebit = 6 ; номер линии порта 1-Wire

.def wiretemp = R25 ; temp регистр для 1-Wire
.def wireres = R2 ; регистр из числа r0...r15

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

delay1us:
; задержка повышенной точности в 1 микросекунду c учетом длительности RCALL и RET
; rcall (им вызываем эту задержку) дает 3 + 1 nop + 4 ret = 8 - 1 микросекунда при 8МГц
; не использует никаких регистров
; для низкой тактовой частоты, возможно, придется заменить на несколько NOP-ов
nop
ret

delay10us:
; задержка повышенной точности в 10 микросекунд, основана на delay1us
; rcall (им вызываем эту задержку) дает 3 + 12 команды вне цикла +
; (5*(8+1+2)+8+1+1)=55 дает сам цикл = 80 тактов = 10 микросекунд
push wiretemp
ldi wiretemp, 6
delay10us_loop:
rcall delay1us
dec wiretemp
brne delay10us_loop
pop wiretemp
nop
nop
nop
ret

delayus:
; задержка в wiretemp десятков микросекунд, повышенной точности не требуется
; на входе - wiretemp, где записано число десятков секунд (wiretemp изменяется)
dec wiretemp
delayus_loop:
rcall delay10us
dec wiretemp
brne delayus_loop
rcall delay1us
rcall delay1us
ret

Init_1W:
; выполняет сброс линии и выдает наличие сигнала присутствия PRESENCE от датчика
; при наличии сигнала присутствия взводим Z-флаг, иначе сбрасываем его
cbi wireport, wirebit ; 0->DDR = Z-состояние
sbis wirepin, wirebit ; проверим наличие 1 в линии
rjmp presence_fault ; если нет - это ошибка
sbi wireport, wirebit ; иначе давим линию в 0
ldi wiretemp, 48 ; задержка в 480 микросекунд
rcall delayus
cbi wireport, wirebit ; давим линию в 1
ldi wiretemp, 6 ; задержка в 60 микросекунд
rcall delayus
; начинаем ждать сигнал присутствия PRESENCE
ldi wiretemp, 250 ; ждем с запасом - 240 max
presence_wait:
sbis wirepin, wirebit
rjmp presence_ok
rcall delay1us
dec wiretemp
brne presence_wait
presence_fault:
; PRESENCE не получен
clz ; сбрасываем Z-флаг

;ldi wiretemp,255
;out ddrC,wiretemp
;out portC,wiretemp

ret
presence_ok:
; PRESENCE получен, задержка в 480 микросекунд
sez ; взводим Z-флаг
ldi wiretemp, 48
rcall delayus
ret

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

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

sw1_next:
push Temp1
in Temp1, SREG
push Temp1 ; сохраним флаги, т.к. будем запрещать прерывания

cli ; запрещаем прерывания
sbi wireport, wirebit ; 1->DDR = 0 на выходе ; давим линию в 0
rcall delay1us ; 1 мкс задержки
ror r0 ; выталкиваем выводимый бит
brcc s0 ; если бит C = 0 - обход
cbi wireport, wirebit ; 0->DDR = Z-состояние ; линию в 1
s0:
push wiretemp
ldi wiretemp, 9 ; в некоторых случаях может потребоваться
; увеличить это значение, но не более 13 (и не менее 9)!
sw1_wait:
rcall delay1us
dec wiretemp
brne sw1_wait
clc
sbic wirepin, wirebit
sec
ror wireres
ldi wiretemp, 9
rcall delayus ; 90 микросекунд - длительность тайм-слота
cbi wireport, wirebit ; 0->DDR = Z-состояние
pop wiretemp

pop Temp1
out SREG, Temp1
pop Temp1

dec wiretemp
brne sw1_next
mov r0, wireres
ret


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


CRC8:
; выполняет подсчет CRC по алгоритму 1-Wire
; на входе r0 - считанный байт
; на выходе CRC - содержит подсчитанную сумму
; портит регистр Z, R0 сохраняется
; примечание: перед первым вызовом CRC необходимо обнулить
push r0
ldi wiretemp, 8
mov wireres,wiretemp
CRC8_loop:
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 CRC8_loop
pop r0
lds r0, CRC
ret
поразительно похож на аналогичный код из темы http://www.radiokot.ru/circuit/digital/home/12/
а там ведь используеться датчик DS1820...
akl
Друг Кота
Сообщения: 4468
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

.include "DS1820.asm" ; ????????????? Unit for DS18B20
Без комментов плохо, с неправильными - ещё хужее. :(
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Дело было не в бобине, д......б сидел в кабине. Невнимательность привела к тому, что я вместо десятков и целых градусов виводил на индикаторы целые граусы и десятые части (тоесть вместо 30,2 я выводил 02). Прошу извинить меня тем, кто потратил на меня свое время.
Реклама
Ответить

Вернуться в «AVR»