Dear Yuriy,
17 Nov 03 18:24, Yuriy K wrote to Serge Bryxin:
SB>> OK. Вот программа
SB>> [interrupts table]
SB>> reset: SB>> [some init stuff] SB>> ldi ZH, high(batt_full*2) SB>> ldi ZL, low(batt_full*2) SB>> clr tmp ; char #0 SB>> rcall LCD_prog_char ; prog custom symbol SB>> [more stuff] SB>> main_loop: SB>> [code] SB>> rjmp main_loop
SB>> LCD_prog_char: SB>> ori tmp, 0x40 ; set CGRAM addr command SB>> rcall lcd_put_cmd SB>> ldi counter,8 SB>> prog_char_loop: SB>> lpm SB>> mov tmp, r0 SB>> rcall lcd_put_data SB>> adiw ZL, 1 SB>> dec counter SB>> brne prog_char_loop SB>> ret
SB>> [some more code]
SB>> batt_full: SB>> .db 0x2,0x7,0x7,0x7,0x7,0x7,0x7,0x0
YK> Где код для lcd_put_cmd, lcd_put_data?
Пожалуйста:
LCD_put_data: sbi LCD_CTRL,LCD_RS ;Set data mode rjmp LCD_put LCD_put_cmd: cbi LCD_CTRL,LCD_RS ;Set command mode ;Fallthru LCD_put: nop nop cbi LCD_CTRL,LCD_E ; E is low push tmp swap tmp rcall LCD_out4 ; Set data and strobe it with E pop tmp ; Retrieve copy rcall LCD_out4 ; Set data and strobe it with E ldi tmp, 3 ; 40uS min rcall delay_20uS ; 60us ret
LCD_out4: cbi LCD_DATA,LCD_D0 sbrc tmp, 0 sbi LCD_DATA,LCD_D0 cbi LCD_DATA,LCD_D1 sbrc tmp, 1 sbi LCD_DATA,LCD_D1 cbi LCD_DATA,LCD_D2 sbrc tmp, 2 sbi LCD_DATA,LCD_D2 cbi LCD_DATA,LCD_D3 sbrc tmp, 3 sbi LCD_DATA,LCD_D3 sbi LCD_CTRL,LCD_E ;Toggle E High nop cbi LCD_CTRL,LCD_E ;Back to Low ret
;*** delay = tmp * 20uS *** delay_20uS: push tmp1 mov tmp1, tick_20uS sub tmp1, tmp brcc d20_loop subi tmp1, -250 tst tmp1 brne d20_loop ldi tmp1, 250 d20_loop: cp tmp1, tick_20uS brne d20_loop pop tmp1 ret
SB>> Обработчики прерываний регистр Z не используют. YK> Абсолютно уверен в этом?
Hу... опять же можно написать "уверен". Hо дойдем уж до конца. Да простят меня все за столь пространный постинг.
t1int: push tmp in tmp, SREG push tmp inc TCNT1S brne t1int_done inc TCNT1SS t1int_done: pop tmp out SREG, tmp pop tmp reti
t0int: ; we come here each 20uS push tmp in tmp, SREG push tmp in tmp, TCNT0 ; +1 tick subi tmp, -(TIM_RELOAD+3); +1tick : compensate! out TCNT0, tmp ; +1tick Reload timer counter ;* 20uS counter service dec tick_20uS brne t0int_done ;* elapsed 5mS ldi tick_20uS,250 ;* 5mS counter service dec tick_5mS breq elapsed_1S ;* correction to 200uS !STRANGE! cpi tick_5mS,132 breq correction_200uS cpi tick_5mS,66 breq correction_200uS rjmp no_correction_200uS correction_200uS: subi tick_20uS,-5 ; correct 200uS error ori flags, 1<<batt_flash_flag no_correction_200uS: rjmp t0int_done elapsed_1S: ldi tick_5mS,200 ori flags, 1<<DISP_flag t0int_done: pop tmp out SREG, tmp pop tmp reti
Больше прерываний нет. (Я в этом уверен). Hу и для полноты картины: определение _всех_ мнемоник регистров, встретившихся выше (действительно всех, они собраны в одном месте):
.def tmp = r16 .def tmp1 = r17 .def lcdl = r18 .def counter = r19 .def TCNT1S = r20 .def TCNT1SS = r21 .def tick_20uS=r22 .def tick_5mS= r23 .def flags = r24
SB>> В симуляторе это работает _нормально_ _всегда_ (!). YK> Hе суть важно. _Симулятор_ ничего не доказывает.
Почему? Если некоторая команда моей программы обнуляет ZH - она и в симуляторе обнулит, никуда не денется. Исключение могут составлять обработчики прерываний, но... см. выше.
YK> Значит тебе надо выяснить кто, где и зачем обнуляет ZH.
Я на это потратил достаточно времени :-)
YK> Повторяю в третий раз - я лично писал пару-тройку проектов под 2313, YK> причем достаточно давно. Таблицы и команда LPM там использовались самые YK> разные и в большом количестве, никаких отклонений от даташита замечено не YK> было.
Да я верю... Причем это тоже не первый мой проект под 2313, и в предыдущих тоже таблицы и LPM использовались. А вот налетел в первый раз.
О! Вот оно! Hе поленился, залез в архив со старым проектом. И да, данные размещены после
0x00FF. И работало же! А вот это - не работало.
Я тоже повторю в третий раз: в принципе я не могу исключить ситуацию, что это проявлялось на единственном экземпляре 2313. Hо я как-нибудь, как время будет, перенесу данные обратно вниз и попробую с другими кристаллами (у меня должны найтись и из той партии, и из других, и, я надеюсь, тот самый отыщу). Из любопытства.
Sincerely yours, Old Greaser.