Листинг 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 потребуется порядка полминуты, да еще и чтение по I2С), и на все это время прерывания будут запрещены. Для нашего измерителя это выльется только в исчезновение на это время индикации, но могут быть ситуации, когда следует предотвратить выключение контроллера на такое время — например, чтобы не потерять данные, когда настанет момент очередной записи. В дальнейшем мы учтем этот момент (хотя это, как вы увидите, сильно усложнит программу). А пока

Листинг 16.10

proc_F8:  ;F8 clear address

        rcall ClearAddr

rjmp Gcykle

ClearAddr:

        cbr Flag,4  ;обнуляем бит конец памяти

        clr AddrH  ;обнуляем адрес

        clr AddrL

        clr ZH  ;и записываем его в EEPROM

        ldi ZL,EaddrL

        mov temp,AddrL  ;можно и просто clr temp

        rcall WriteEEP

        inc ZL

        mov temp,AddrH

        rcall WriteEEP

        ldi temp,$AA  ;ответ в комп. все Ok

        rcall out_com

sei

ret

Теперь у нас есть измеритель температуры и давления, записывающий данные во внешнюю память, откуда они могут быть прочитаны в любой момент. В главе 18 мы займемся вопросом приема данных через компьютер. А здесь нам осталось только объединить измеритель с часами, чтобы можно было задавать точный и достаточно длительный интервал измерения. И для этой цели нам также пригодится интерфейс I2С.

Часы с интерфейсом I2С
Перейти на страницу:

Поиск

Похожие книги