;ATmega853 5 кварц 4000 кГц
.include "m8535def.inc"
;==== Определения и константы ====
;Управление индикацией
.equ segG = 6 ;port С pin 28
.equ segF = 5 ;pin 27
.equ segE = 4 ;pin 26
.equ segD = 3 ;pin 25
.equ segC = 2 ;pin 24
.equ segB = 1 ;pin 23
.equ segA = 0 ;pin 22
.equ RazrTdH = 0 ;PortB,0 pin 1 десятки градуса
.equ RazrTdM = 1 ;PortB,1 pin 2 ед. градусов
.equ RazrTdL = 2 ;PortB,2 pin 3 десятые градусов
.equ RazrPdH = 3 ;PortB,3 pin 4 сотни давления
.equ RazrPdM = 4 ;PortB,4 pin 5 дес. давления
.equ RazrPdL = 5 ;PortB,5 pin 6 ед. давления
;адреса SRAM старший байт адреса SRAM=0x01
.equ Tram =: 0x0 ;0x0,0x1 — старш. и младш. байты температуры АЦП
.equ Pram =: 0x2 ;0x2,0x3 — старш. и младший, байты давления АЦП
.equ TdH = 0x04 ;температура старший дес.
.equ TdM = 0x05 ;темп. средний дес.
.equ TdL = 0x06 ;темп. младший дес.
.equ PdH = 0x07 ;давление старший дес.
.equ PdM = 0x08 ;давление средний дес.
.equ PdL = 0x09 ;давление младший дес.
.equ tZH = 0x20 ;ст. разряд коэффициента Z температуры
.equ tZL = 0x21 ;мл. разряд коэффициента Z температуры
.equ tKH = 0x22 ;ст. разряд коэффициента К температуры
.equ tKL = 0x23 ;мл. разряд коэффициента К температуры
.equ pZH = 0x24 ;ст. разряд коэффициента Z давления
.equ pZL = 0x25 ;мл. разряд коэффициента Z давления
.equ pKH = 0x26 ;ст. разряд коэффициента К давления
.equ pKL = 0x27 ;мл. разряд коэффициента К давления
.equ AtBCDO = 5 ;адрес ResL для процедуры преобразования Bin-Dee
.equ AtBCD2 = 6 ;адрес ResH
;переменные
.def AregH = r2 ;результат измерения hex, старший байт
.def AregL = r3 ;результат измерения hex, младший байт
.def KoeffH = r4 ;коэффициент, старший байт
.def KoeffL = r5 ;коэффициент, младший байт
.def ResL = r6 ;результат упакованный BCD, младший байт
.def ResH = r7 ;результат упакованный BCD, старший байт
.def temp = r16 ;рабочий регистр
.def temp1 = r17 ;вспомогательная переменная
.def temp2 = r18 ;вспомогательная переменная
.def count = r19 ;счетчик преобразований — до 64
.def countCyk = r20 ;счетчик до 32,
.def Flag = r21 ;регистр флагов, биты:
;измерение: 0 — температуры, 1 — давления,
.def cRazr = г22 ;счетчик до 6 мультиплексирования разрядов
;====== прерывания ======
rjmp RESET ;Reset Handle
reti ;IRQ0 Handler
reti ;IRQ1 Handler
reti ;Timer2 Compare Handler
reti ;Timer2 Overflow Handler
reti ;Timer1 Capture Handler
reti ;Timer1 Compare A Handler
reti ;Timer1 Compare В Handler
reti ;TIM1_OVF ;Timer1 Overflow Handler
rjmp TIM0 ;Timer0 Overflow Handler
reti ;SPI Transfer Complete Handler
reti ;USART RX Complete Handler
reti ;UDR Empty Handler
reti ;USART TX Complete Handler
rjmp readADC ;reti;ADC ;ADC Conversion Complete Handler
reti ;EEPROM Ready Handler
reti ;Analog Comparator Handler
reti ;Two-wire Serial Interface Handler
reti ;IRQ2 Handler
reti ;Timer0 Compare Handler
reti ;Store Program Memory Ready Handler
;==================
OUT_N: ;маски цифр
.db
0b00111111,0b0000110,0b01011011,0b01001111,0b01100110,0b01101101, 0b01111101,0b00000111,0b01111111,0b01101111
;seg ABCDEF(0);seg BC(1);seg ABDEG(2);seg ABCDG(3);seg BCFG(4);seg ACDFG(5)
;seg ACDEFG(6);seg ABC(7);seg ABCDEFG(8);seg ABCDFG(9)
TIM0:
;сначала индикация
inc cRazr ;счетчик разрядов
cpi cRazr,6 ;всего б разрядов
brne Set_razr
clr cRazr ;если равен 6, очищаем
Set_razr:
cpi cRazr,0 ;десятки градусов
brne Р1 ;если нет — на другие разряды
ldi r28,TdH ;установка YL — старш. темп.
ld temp,Y ;в temp — значение десятков градусов
ldi ZH,HIGH(OUT_N*2) ;адрес констант в памяти — в Z
ldi ZL,LOW(OUT_N*2)
add ZL,temp ;адрес маски цифры, равной temp
lpm ;в r0 — маска
out PortC,r0 ;установили сегменты
ldi temp,1<
out PORTB,temp ;установили разряды
rjmp rADC
P1:
cpi cRazr,1 ;единицы град
brne P2
ldi r2 8,TdM ;установка адреса — ср. темп.
ld temp,Y
ldi ZH,HIGH()UT_N*2)
ldi ZL,LOW(OUT_N* 2)
add ZL,temp
lpm
out PortC,r0 ;установили сегменты
ldi temp,1<
out PORTB,temp ;установили разряды rjmp rADC
P2:
cpi cRazr,2 ;дробные град
brne P3
ldi r2 8,TdL ;установка Y — мл. темп.
ld temp,Y
ldi ZH,HIGH(OUT_N* 2)
ldi ZL,LOW(OUT_N*2)
add ZL,temp
lpm
out PortC,r0 ;установили сегменты
ldi temp,1<
out PORTB,temp ;установили разряды
rjmp rADC
Р3:
cpi cRazr,3 ;сотни давления
brne Р4
ldi r28,PdH ;установка Y — сотн. prs
ld temp,Y
ldi ZH,HIGH(OUT_N*2)
ldi ZL,LOW(OUT_N*2)
add ZL,temp
lpm
out PortC, r0 ;установили сегменты
ldi temp,1<
out PORTB,temp ;установили разряды
rjmp rADC
P4:
cpi cRazr,4 ;десятки давления
brne P5
ldi r2 8,PdM ;установка Y — дес. prs
ld temp,Y
ldi ZH,HIGH(OUT_N*2)
ldi ZL,LOW(OUT_N*2)
add ZL,temp
lpm
out PortC,r0 ;установили сегменты
ldi temp,1<
out PORTB,temp ;установили разряды
rjmp rADC
P5:
cpi cRazr,5 ;единицы давления
brne rADC
ldi r28,PdL ;установка Y — ед. prs
ld temp,Y
ldi ZH,HIGH(OUT_N*2)
ldi ZL,LOW(OUT_N*2)
add ZL,temp
lpm
out PortC,r0 ;установили сегменты
ldi temp,1<
out PORTB,temp ;установили разряды
rADC: inc countCyk ;обработка АЦП
sbrs countCyk,5 ;если бит 5 в countCyk равен 1, то прошло 32 такта таймера 0, будем запускать АЦП (см. readADC)
reti
clr countCyk
inc count
cpi count,65 ;если прошло 64 чтения, то сразу на обработку
breq endADC
sbrc Flag,0 ;если бит 0 флага — читаем температуру
ldi temp,0
sbrc Flag,1 ;если бит 1 флага — читаем давление
ldi temp,1
out ADMUX, temp ;установили АЦП канал
sbi ADCSRA, ADSC ;запуск новое преобразование
reti
endADC:
;расчет по 64 значениям
clr count
sbrc Flag,0
ldi r28,Tram ;установка адреса — T
sbrc Flag,1
ldi r28,Pram ;установка адреса — P
ld AregH,Y+ ;загрузка суммы из памяти
ld AregL,Y
div64L: ;деление на 64
lsr AregH ;сдвинули старший
ror AregL ;сдвинули младший
inc count
cpi count,6
brne div64L ;сдвинули-поделили на 64
subi r28,1 ;в Y опять адрес Tram или Pram
clr temp
st Y+,temp
st Y,temp ;очистили память для следующего цикла
sbrs Flag,0 ;расчет температуры
rjmp prs ;иначе давления
ldi r28,tZH ;установка адреса коэфф. Z
ld temp,Y+
mov KoeffH,temp
ld temp,Y
mov KoeffL,temp ;получили коэфф. Z температуры
;вычисление знака:
ср AregL,KoeffL
срс AregH,KoeffH
brsh b0
sub KoeffL,AregL
sbc KoeffH,AregH
mov AregL,KoeffL
mov AregH,KoeffH
sbi PortD,7 ;знак —
rjmp m0
Ь0: ;если больше
sub AregL,KoeffL
sbc AregH,KoeffH
cbi PortD,7 ;знак +
m0: ;умножение на коэфф. К
ldi r28,tKH ;установка адреса коэфф. К
ld temp,Y+
mov KoeffH,temp
ld temp,Y
mov KoeffL,temp ;получили К температуры
rcall Mp16 ;умножили
;деление на 1024
mov AregL,temp1
mov AregH,temp2 ;на 2 56
lsr AregH ;сдвинули старший
ror AregL ;сдвинули младший
lsr AregH ;сдвинули старший
ror AregL ;сдвинули младший; еще на 4
rjmp contPT
prs:
sbrs Flag,1 ;расчет давления
rjmp contPT
ldi r28,pZH ;установка адреса коэфф. Z
ld temp,Y+
mov KoeffH,temp
ld temp,Y
mov KoeffL,temp ;получили коэфф. Z давления
adc AregL,KoeffL
add AregH,KoeffH ;прибавили к величине
ldi r28,pKH ;установка адреса коэфф. К
ld temp,Y+ mov
KoeffH,temp
ld temp,Y
mov KoeffL,temp ;получили коэфф. К давления
rcall Мр16 ;умножили
;деление на 1024
mov AregL,temp1
mov AregH,temp2 ;на 256
lsr AregH ;сдвинули старший
ror AregL ;сдвинули младший
lsr AregH ;сдвинули старший
ror AregL ;сдвинули младший; еще на 4
contPT:
sbrc Flag,0
ldi r28,TdH ;установка адреса — T
sbrc Flag,1
ldi r28,PdH ;установка адреса — P
rcall bin2BCD16 ;преобраз в дв. дес.
st Y+,ResH ;запоминаем в памяти старший BCD
mov temp,ResL ;младший распаковываем
swap temp
andi temp,0b00001111
st Y+,temp
mov temp,ResL
andi temp,0b00001111
st Y,temp ;и тоже сохраняем в памяти
;установка флагов и переменных для следующего цикла
clr count
sbrc Flag,0
rjmp _F0
clr Flag
sbr Flag,0x1 ;был бит 1, устанавливаем бит 0
reti
_F0:
clr Flag ;был бит 0, устанавливаем бит 1
sbr Flag,0x2
reti ;TIME0
readADC: ;чтение АЦП по прерыванию
sbrc Flag,0
ldi r28,Tram ;установка адреса — T
sbrc Flag,1
ldi r28,Pram ;установка адреса — P
ld AregH,Y+
ld AregL,Y
in temp1,ADCL ;получаем младший
in temp,ADCH ;старший
add AregL,tempi ;суммируем
adc AregH,temp
dec r28
st Y+,AregH ;запоминаем сумму
st Y,AregL ;в памяти
reti ;ADC
Мр16: ;умножение двух 16-разрядных величин
;AregL multiplicand low byte
;AregH multiplicand high byte
;KoeffL multiplier low byte
;KoeffH multiplier high byte
;temp result byte 0 (LSB)
;tempi result byte 1
;temp2 result byte 2
clr temp2 ;очистить ставший
mul AregL,KoeffL ;умножаем младшие
mov temp,r0 ;в r0 младший результата операции mul
mov temp1,r1 ;в r01 старший результата операции mul
mul AregH,KoeffL ;умножаем старший на младший
add tempi,r0 ;в r младший результата операции mul
adc temp2,r1 ;в r01 старший результата операции mul
mul AregL,KoeffH ;умножаем младший на старший
add temp1,r0 ;в r0 младший результата операции mul
adc temp2,r1 ;в r01 старший результата операции mul
mul AregH,KoeffH ;умножаем старший на старший
add temp2,r0 ;4-й разряд нам тут не требуется, но он в r01
ret
bin2BCD16: ;преобразование 16-разрядного hex в упакованный BCD
;input: hex value low=AregL hex value high = AregH
;output: BCD value digits 1 and 0 ResL
;BCD value digits 2 and 3(=0) ResH
ldi tempi,16 ;Init loop counter
clr ResH
clr ResL
clr ZH ;clear ZH (not needed for AT90Sxx0x)
bBCDx_1: lsl AregL ;shift input value
rol AregH ;through all bytes
rol ResL;
rol ResH
dec temp1 ;decrement loop counter
brne bBCDx_2 ;if counter not zero
ret ;return
bBCDx_2:ldi r30,AtBCD2+1 ;Z points to result MSB + 1
bBCDx_3:
ld temp, — Z ;get (Z) with pre-decrement
subi temp, — $03 ;add 0x03
sbrc temp,3 ;if bit 3 not clear
st Z, temp ;store back
ld temp, Z ;get (Z)
subi temp, — $30 ;add 0x30
sbrc temp, 7 ;if bit 7 not clear
st Z,temp ;store back
cpi ZL,AtBCDO ;done all three?
brne bBCDx_3 ;loop again if not
rjmp bBCDx_1
bin2bcd8: ;преобразование 8-разрядного hex в неупакованный BCD
;вход hex= temp, выход BCD temp1 — старш.; temp — младш.
;эта процедура работает только для исходного меньше 100
clr tempi ;clear result MSD
bBCD8_1: subi temp,10 ;input = input — 10
brcs bBCD8_2 ;abort if carry set
inc temp1 ;inc MSD
rjmp bBCD8_1 ;loop again
bBCD8_2:subi temp, — 10 ;compensate extra subtraction
ret
RESET: ;точка запуска программы после включения
ldi temp,low(RAMEND) ;загрузка указателя стека
out SPL,temp
ldi temp,high(RAMEND) ;загрузка указателя стека
out SPH,temp
ldi temp,1<
out ACSR,temp ;выкл. аналог, компаратор на всякий
;установка портов вход-выход
ldi temp,0b00111111 ;разряды
out DDRB,temp
ldi temp,0b01111111 ;сегменты
out DDRC,temp
ldi temp,0b10000000 ;знак "минус"
out DDRD,temp
;установка АЦП
ldi temp, 1<
;start ADC 1/32 такт = 128 кГц ;interrupt enable
out ADCSRA,temp
;установка таймера
ldi temp,0b00000010
out TCCR0,temp
;Timer0 on div 1:8 управление разрядами 2000 Гц
;прерывания
ldi temp,(1<
out TIMSK,temp
ldi temp,255 ;сбросить все прерывательные флаги
out TIFR,temp
out GIFR,temp
;начальная установка переменных
ldi r29,1 ;YH=1, пишем в RAM, начиная с 01:00
clr count
clr countCyk
clr cRazr
clr Flag
sbr Flag,0x01 ; сначала измеряем температуру
;обнуление рабочих ячеек
clr temp
ldi r28,Tram ;Tempr
st Y+,temp
st Y,temp
ldi r2 8,Pram ;Prs
st Y+,temp
st Y,temp
;запись коэффициентов
ldi r28,tZH ;начальный адрес
;Z Tempr=471
ldi temp,High(471) ;ст.
st Y+,temp
ldi temp,Low(471) ;мл.
st Y+,temp
;К Tempr=1020
ldi temp,High(1020) ;ст.
st Y+,temp
ldi temp,Low(1020) ;мл.
st Y+,temp
;Z prs=12
ldi temp,High(12) ;ст. на самом деле = 0
st Y+,temp
ldi temp,Low(12) ;мл.
st Y+,temp
;К prs=916
ldi temp,High(916) ;ст.
st Y+,temp
ldi temp,Low(916) ;мл.
st Y,temp
sei ;разрешаем прерывания
G_cykle: ;основной цикл
rjmp G_cykle