Значит перейдём сразу к сабжу:
Имеются два устройства, назовём их условно мастером и слейвом. Мастер и слейв должны общаЦЦа меж собой через USART. Но они не общаются, вернее не всегда. Мастер и слейв оснащены интерфейсными микросхемами ADM483.
Была готовая рабочая программа, у мастера она выглядела так:
Код
out UDR,temp
sei
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
cli
sbi PORTD,2 ;установка усарта в режим передатчика (используется
;интерфейсная микросхема ADM485)
sei
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
cli
sbi PORTD,2 ;установка усарта в режим передатчика (используется
;интерфейсная микросхема ADM485)
Изначально мастер был в режиме передатчика. Ну код не очень сложный, думаю понятно что к чему. Так вот мне была поставлена задача уменьшить время с 640 милисекунд до минимально возмаожного. (DEL64MS - п/п задержки на 64 мс).
Вот что у меня получилось:
Код
zapr: UCSRA,UDRE ;проверяю на готовность УДРа принимать инфу
rjmp zapr
out UDR,temp ;засылаю передаваемые данные
rcall DEL1MS ;без особого смысла
rcall TxComp ;не знаю почему, но после передачи программа не
;уходит в обработчик прерывания сразу. если
;слейвов несколько (мастер их поочерёдно
;опрашивает), то прерывание срабатывает только
;после последнего слейв
rcall DEL1MS ;это я вычитал, что переключение в режим
rcall DEL1MS ;передатчика происходит от 300 до 3000
rcall DEL1MS ;микросекун
ldi r17,0xFF ;почти пустой цикл, который длится около 40
lp1: ldi r18,0xFF ;милисекунд. Выход из цикла происходит
lp2: sbic UCSRA,RXC ;тогда, когда приходят данные.
rjmp otv ;По логике в принципе 40 мс должно хватить
dec r18 ;что бы слейв отреагировал и выдол ответ
breq lp2 ;
dec r17 ;
breq lp1 ;
sbi PORTD,2 ;усарт -> ражим передатчика
rjmp zapr
out UDR,temp ;засылаю передаваемые данные
rcall DEL1MS ;без особого смысла
rcall TxComp ;не знаю почему, но после передачи программа не
;уходит в обработчик прерывания сразу. если
;слейвов несколько (мастер их поочерёдно
;опрашивает), то прерывание срабатывает только
;после последнего слейв
rcall DEL1MS ;это я вычитал, что переключение в режим
rcall DEL1MS ;передатчика происходит от 300 до 3000
rcall DEL1MS ;микросекун
ldi r17,0xFF ;почти пустой цикл, который длится около 40
lp1: ldi r18,0xFF ;милисекунд. Выход из цикла происходит
lp2: sbic UCSRA,RXC ;тогда, когда приходят данные.
rjmp otv ;По логике в принципе 40 мс должно хватить
dec r18 ;что бы слейв отреагировал и выдол ответ
breq lp2 ;
dec r17 ;
breq lp1 ;
sbi PORTD,2 ;усарт -> ражим передатчика
если интересно, то вот программа слейва:
Код
in temp,UDR
sbis temp,7
rjmp enrx
....
....
....
....
enrx: cp temp,temp1
brne end
rcall del1ms
rcall del1ms
rcall del1ms
rcall del1ms
lds Z,DataToTransmit
mov temp,Z
out UDR,temp
end:
sbis temp,7
rjmp enrx
....
....
....
....
enrx: cp temp,temp1
brne end
rcall del1ms
rcall del1ms
rcall del1ms
rcall del1ms
lds Z,DataToTransmit
mov temp,Z
out UDR,temp
end:
Теперь поподробнее. Представленная программа у слейва преставляет собой обработчик прерывания "приём завершён". У мастера и у слейва обработка прерывания по завершению передачи одиноков - усарт переводится в режим приёмника.
Сижу над этим уже неделю - так к слейву претензий нет - он всё прекрасно принимает и передаёт. За неделю я придумал мириады способов это проверить... А вот слейв меня расстраивает - предавать он в принципе передаёт, но вот обратно принимает не всегода. Причём закономерность мне выявить ну никак не удаётся. Из ста пакетов он может принять 64, 78, 55, 23, 70 и т.д. Причём ни разу 100 пакетов он не принял... Подскажите, в чём дело, может я чего не так делаю...
ЗЫ:. к слову:
бодрейт 38,4к, 1 стоп бит, 8 бит, бит четности, микроконтроллер рабоет на частоте 8Mz.