Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: USART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
UniBomb
Доброго времени суток уважаемые!

Значит перейдём сразу к сабжу:

Имеются два устройства, назовём их условно мастером и слейвом. Мастер и слейв должны общаЦЦа меж собой через 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)


Изначально мастер был в режиме передатчика. Ну код не очень сложный, думаю понятно что к чему. Так вот мне была поставлена задача уменьшить время с 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           ;усарт -> ражим передатчика

если интересно, то вот программа слейва:
Код
        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:


Теперь поподробнее. Представленная программа у слейва преставляет собой обработчик прерывания "приём завершён". У мастера и у слейва обработка прерывания по завершению передачи одиноков - усарт переводится в режим приёмника.

Сижу над этим уже неделю - так к слейву претензий нет - он всё прекрасно принимает и передаёт. За неделю я придумал мириады способов это проверить... А вот слейв меня расстраивает - предавать он в принципе передаёт, но вот обратно принимает не всегода. Причём закономерность мне выявить ну никак не удаётся. Из ста пакетов он может принять 64, 78, 55, 23, 70 и т.д. Причём ни разу 100 пакетов он не принял... Подскажите, в чём дело, может я чего не так делаю...


ЗЫ:. к слову:

бодрейт 38,4к, 1 стоп бит, 8 бит, бит четности, микроконтроллер рабоет на частоте 8Mz.
BlackJack
Что-то похожее на лечение гланд.
Зачем нужны все эти задержки?
получил флаг TXC после последнего байта пакета -значит можно переключится на прием и просто ждать RXC.
UniBomb
Согласен.... Но (повторюсь) я вычитал, что переключение режимов происхожит от 70 до 3000 мкс, поэтому я их и поставил. Сперва у меня так и было, но... После отправки пакета и приёмом ответных данных должно пройти какое то время. Так как все слейвы опрашиваются поочерёдно и ничего кроме опроса не происходит, то вероятнее всего в удр записываются данные ещёдо того как был установлен ТХС. Была сделана проверка флага, тогда программа на этом зацикливалась и отказывалась идти дальше. Потом была мысль, что происходит рассинхронизация мастера и слейва, т.е. слейв передаёт пакеты когда мастер ещё не переключился в режим приёма, тогда были поставлены задержки в программу слейва. Блин..... cranky.gif Потом пытался поставить проверку флага RXC, но и из этого ничего путного не вышло, так как раз пакеты не доходят, то и собственно говоря флаг установлен не будет, поэтому программа опять зацикливалась. Потом был организован цикл, длительностью в 40 милисекунд, выход из которого происходил двумя способами - либо по истечению этого времени, либо по установке флага RXC. Из этого тоже ничего путного не вышло... И только увеличением этого цикла я добился (уже сегодня!) более-менее устойчивого приёма, но не всегда с первого раза... вернее с первого раза получалось довольно таки не всегда. (Но не верю я что при такой скорости предача происходит более 200 милисекунд).... sad.gif
BlackJack
Цитата(UniBomb @ Oct 10 2005, 17:36)
Согласен.... Но (повторюсь) я вычитал, что переключение режимов происхожит от 70 до 3000 мкс, поэтому я их и поставил.
....
выход из которого происходил двумя способами - либо по истечению этого времени, либо по установке флага RXC. Из этого тоже ничего путного не вышло... И
*


Фигня smile.gif. у меня адм485 переключается сразу. в том смысле, что передернул вывод, а следующей командой можно в UDR писать. на 38400 начало не глотает, проверено. Хотя по сути рс485 вначале и должна идти преамбула=активная пауза.

Флаги-то зачем? используй прерывание. Все равно UDR надо прочитать, даже если была ошибка фрейминга. А еще с АДМ бывает такая фишка: без растягивающих резисторов она иногда работает лучше.
VladislavS
Реальные гланды smile.gif

Вот так работает в более десятка разных устройств и мастреров, и слэйвов:
Код
#pragma vector=USART_TXC_vect
__interrupt void UTX()
{
 PORTC&=~(1<<PC5);
};

#pragma vector=USART_RXC_vect
__interrupt void URX()
{
 unsigned char RCV_data = UDR;
}

void SendUART(unsigned char data)
{
 while ( !(UCSRA&(1<<UDRE)) );
 PORTC|=(1<<PC5);
 UDR=data;
};

На PC5, как нетрудно догадаться, висит R/W
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.