Итак, записываем в секции определений программы измерителя, там, где адреса SRAM:
…
;Нех-данные — «сырые», без пересчета
.equ Thex = 0х0А ;0А,0В — старший и младший байты температуры
.equ Phex = 0х0С ;0C,0D — старший и младший байты давления
.equ FEnRAM = $0Е ;флаг, если равен $FF, то писать во flash
…
Отдельно запишем адреса в EEPROM (первые восемь у нас заняты коэффициентами):
.equ FEnEE = 0x10 ;флаг если равен $FF, то писать во flash
.equ EaddrL = 0x11 ;младший байт тек. адреса
.equ EaddrH = 0x12 ;старший байт тек. адреса
Обратите внимание, что запись во flash разрешена, если байт FEnEEравен $FF, т. е. в самом начале, когда EEPROM еще пуста, запись по умолчанию разрешается. В процедуре обработки данных дописываем процедуры сохранения «сырых» значений температуры и давления по указанным адресам. Они у нас содержатся в регистрах AregH: AregL. В начале обработки данных по температуре, после имеющегося оператора rjmp prsдописываем:
ldi ZL,Thex;запоминаем температуру
st Z+,AregH
st Z,AregL
А там, где начинается расчет давления, после оператора rjmp contPTзаписываем:
ldi ZL,Phex ;запоминаем давление
st Z+,AregH
st Z,AregL
Теперь инициализируем таймер. В загрузочную секцию вместо строк инициализации Timer 0 ( ldi temp, (1<) и out TIMSK, temp) добавляем:
;++++++++Set Timer 1
ldi temp,high(58594)
out OCR1АН, temp
ldi temp,low(58594)
out OCR1AL,temp
ldi temp,0b01000000
out TCCR1A,temp ;переключающий режим для вывода PD5-0C1A
ldi temp,0b00001101
out TCCR1B,temp ;1/1024 очистить после совпадения
ldi temp, (1<<<0CIE1A) ;разреш. прерывания
;по совпадению для Timer 1 и переполнению Timer 0
out TIMSK,temp
К выводу OC1A(вывод 19 для ATmega8535) можно присоединить светодиод, который будет попеременно гореть и гаснуть с периодом 30 с, показывая, что запись работает.
Далее в секции начальной загрузки инициализируем регистры адреса. Получится довольно сложная процедура (листинг 16.6), которая должна проверять значения адреса в EEPROM, и если он есть (т. е. память не пуста и там не записаны все единицы), то еще и сравнивать его с последним возможным адресом (32767 или 7FFFh).
Листинг 16.6
:=======инициализация адреса flash
clr ZH ;старший EEPROM
ldi ZL,EaddrL ;младший EEPROM
rcall ReadEEP
mov AddrL,temp
ldi ZL,EaddrH
rcall ReadEEP
mov AddrH,temp;теперь в AddrH:AddrL адрес из EEPROM
ldi temp,0xFF;если все FF, то память была пуста
ср AddrL,temp
ldi temp,0xFF
cpc AddrH, temp
brne cont_1
clr AddrH ;если пуста, то присваиваем адрес = 0
clr AddrL
clr ZH ;старший EEPROM
ldi ZL,EaddrL ;младший EEPROM
mov temp,AddrL
rcall WriteEEP ;и записываем его опять в EEPROM
inc ZL
mov temp,AddrH
rcall WriteEEP
cont_1: ;теперь проверку на последний адрес $7FFF
ldi temp,0xFF
cp AddrL,temp
ldi temp,0x7F
cpc AddrH, temp
brne cont_2
sbr Flag,4 ;4 бит регистра Flag = конец памяти
cont_2: ;загрузка байта разрешения записи flash
clr ZH ;старший EEPROM
ldi ZL,FEnEE
rcall ReadEEP
ldi ZH,1 ;старший RAM
ldi ZL,FEnRAM ;младший RAM
st Z,temp ;сохраняем значение флага
Отдельный бит «конец памяти» в регистре Flag (бит 2, т. е. устанавливается он командой sbr Flag, 4, см. главу 13 ) нам понадобится позднее, для того, чтобы можно было временно запретить запись во flashвнешней командой, не сбрасывая значения адреса и независимо от того, достигнут конец памяти или нет.
Теперь в секции прерываний заменим retiна rjmp TIM1_COMPAв строке для прерывания Timer1 Compare А (шестое сверху, не считая RESET), и напишем его обработчик (листинг 16.7).
Листинг 16.7
TIM1_COMPA: ;15 секунд
;проверять разрешение записи во flash
ldi ZH,1 ;старший RAM
ldi ZL,FEnRAM
ld temp,Z
cpi temp,$FF
breq flag_WF
reti ;если запрещено, то выходим из прерывания
flag_WF:
ldi ZL,Thex ;адрес значения в SRAM
ld DATA,Z+ ;старший T
rcall WriteFlash ;пишем во flash
adiw AddrL,1
ld DATA,Z+ ;младший T
rcall WriteFlash
adiw AddrL,1
ld DATA,Z+ ;старший Р
rcall WriteFlash
adiw AddrL,1
ld DATA,Z+ ;младший P
rcall WriteFlash
;проверяем адрес на 7FFF
Читать дальше
Конец ознакомительного отрывка
Купить книгу