Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Теперь в секции прерываний заменим 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
ldi temp,0xFF
cp AddrL,temp
ldi temp,0x7F
cpc AddrH, temp
breq clr_FE;если равен, на clr_FE
adiw AddrL,1 ; иначе сохраняем след, адрес:
clr ZH
ldi ZL,EaddrL ;в EEPROM
mov temp,AddrL
rcall WriteEEP
inc ZL
mov temp,AddrH
rcall WriteEEP
reti ;выход из прерывания
clr_FE ;если конец памяти:
clr temp
ldi ZH,1 ;старший RAM
ldi ZL,FEnRAM
st Z,temp ;сбрасываем разрешение записи
clr ZH ;старший EEPR
ldi ZL,FEnEE
rcall WriteEEP
sbr Flag,4 ;бит «конец памяти»
clr temp
out TCCR1A,temp ;отмена переключающего режима для вывода PD5-OC1A
reti ;на выход из прерывания
Как мы видим, здесь каждые 15 с идет запись в EEPROM текущего адреса (того, по которому должна производиться следующая запись), т. е. если в какой-то момент питание пропадет, то при следующей загрузке запись все равно начнется с текущего адреса. При достижении конца памяти отключится переключающий режим для вывода OC1A, и светодиод перестанет мигать, сигнализируя о конце памяти.
Отметим, что запись идет через каждые четыре байта, т. е. для заполнения 32 кбайтов внешней памяти придется 8192 раза обновить содержимое ячеек. Таким образом, для достижения теоретического предела по количеству циклов записи в EEPROM (100 тыс.) нужно как минимум двенадцать раз заполнить внешнюю память. На самом же деле число допустимых циклов еще намного больше (автор специально запускал запись каждые три секунды на пару месяцев, но сбоев так и не добился), потому можно не опасаться, что мы исчерпаем ресурс встроенной EEPROM.
Заметки на полях
Обратите внимание, что в процедурах I 2С имеются псевдонимы: DATAи ClkAесть те же регистры, что и temp1и temp2в основной программе. Я предостерегал вас от такой практики, но в данном случае ничего страшного не произойдет, т. к. использование этих регистров разнесено во времени — обращение к I 2С никогда не сможет произойти во время расчетов, где задействованы temp1и temp2. В дальнейшем эти регистры нам где-нибудь еще пригодятся.
Теперь займемся процедурами чтения содержимого внешней памяти и осуществления установок разрешения-запрещения записи. Естественно, это придется делать через компьютер (а куда еще читать?), и мы используем уже инициализированный нами UART. Нам потребуется реализовать четыре процедуры:
• Запретить запись во flash.
• Разрешить запись во flash.
• Прочесть содержимое flash.
• Обнулить адрес flash, чтобы начать запись с начала.
Добавим в текст программы, в основной цикл (по метке Gcykle, обязательно после команды rcall in_com) следующие строки:
…
cpi temp,0xF0 ;запись во flash разрешить breq proc_F0
cpi temp,0xF1 ;запись во flash запретить breq proc_F1
cpi temp,0xF2 ;читать flash breq proc_F2
cpi temp,0xF8 ;запись во flash с начала, обнулить адрес
breq proc_F8
…
Посылая соответствующие команды ( $F0и т. д.) с компьютера, мы будем вызывать соответствующую процедуру. Проще всего оформить процедуры разрешения и запрещения так, как в листинге 16.8.
Листинг 16.8
proc_F0: ;F0 запись flash разрешить
rcall EnableFlash
rjmp Gcykle
proc_F1: ;F1 запись flash запретить
rcall DisFlash
rjmp Gcykle
…
EnableFlash:
cli
;сначала проверяем бит «конец памяти»
sbrc Flag,2
rjmp exit_FE
;проверяем байт разрешения, если нет, пишем его в память
ldi ZH,1 ;старший RAM
ldi ZL,FEnRAM
ld temp,Z
cpi temp,$FF
breq exit_FA
ldi temp,$FF
st Z,temp
clr ZH ;старший EEPR
ldi ZL,FEnEE
rcall WriteEEP
ldi temp,$AA ;все Ok
rcall out_com
sei
ret
exi t_FA:
ldi temp,$FA ;ответ в комп. — уже разрешен
rcall out_com
sei
ret
exit_FE:
ldi temp,$FE ;ответ в комп. — конец памяти
rcall out_com
sei
ret
DisFlash:
cli
clr temp
ldi ZH,1 ;старший RAM
ldi ZL,FEnRAM
st Z,temp
clr ZH ;старший EEPR
ldi ZL,FEnEE
rcall WriteEEP
ldi temp,$AA ;ответ в комп. — все Ok
rcall out_com
sei
ret
Мы используем запрещение прерываний, потому что процедуры достаточно долгие и запросто можно «испортить» temp по ходу дела, а здесь это уже недопустимо. Кроме того, они включают запись в EEPROM, во время которой прерывания надо все равно запрещать. Из этих процедур мы также видим, зачем нам понадобился отдельный флаг «конец памяти» — если он установлен, то разрешить запись будет нельзя. Это можно будет сделать только одновременно со сбросом адреса, что необратимо, и данные после этого уже прочесть будет нельзя. Потому мы сначала займемся их чтением (листинг 16.9).
Листинг 16.9
proc_F2: ;F2 читать flash
rcall ReadFullFlash
rjmp Gcykle
…
ReadFullFlash:
cli
mov YH,AddrH ;сохраняем текущий адрес в Y
mov YL,AddrL
clr AddrL ;чтение начнем с начала памяти
clr AddrH
loopRF:
cp AddrL, YL ;не дошли ли до текущего
срс AddrH, YH
breq end_RF ;если дошли, то конец чтения
rcall ReadFlash ;собственно чтение
mov temp,DATA ;данные из DATA в temp
rcall out_com ;передаем наружу
adiw AddrL,1 ;следующий адрес
rjmp loopRF
end_RF:
mov AddrH,YH ;восстанавливаем текущий адрес
mov AddrL,YL
sei
ret
Процедура эта будет долгой, если записан сколько-нибудь существенный кусок в памяти (для передачи 32 кбайт со скоростью 9600 потребуется порядка полминуты, да еще и чтение по I 2С), и на все это время прерывания будут запрещены. Для нашего измерителя это выльется только в исчезновение на это время индикации, но могут быть ситуации, когда следует предотвратить выключение контроллера на такое время — например, чтобы не потерять данные, когда настанет момент очередной записи. В дальнейшем мы учтем этот момент (хотя это, как вы увидите, сильно усложнит программу). А пока
Читать дальшеИнтервал:
Закладка: