UniBomb 0 9 октября, 2005 Опубликовано 9 октября, 2005 · Жалоба Доброго времени суток уважаемые! Значит перейдём сразу к сабжу: Имеются два устройства, назовём их условно мастером и слейвом. Мастер и слейв должны общаЦЦа меж собой через 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 0 10 октября, 2005 Опубликовано 10 октября, 2005 · Жалоба Что-то похожее на лечение гланд. Зачем нужны все эти задержки? получил флаг TXC после последнего байта пакета -значит можно переключится на прием и просто ждать RXC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UniBomb 0 10 октября, 2005 Опубликовано 10 октября, 2005 · Жалоба Согласен.... Но (повторюсь) я вычитал, что переключение режимов происхожит от 70 до 3000 мкс, поэтому я их и поставил. Сперва у меня так и было, но... После отправки пакета и приёмом ответных данных должно пройти какое то время. Так как все слейвы опрашиваются поочерёдно и ничего кроме опроса не происходит, то вероятнее всего в удр записываются данные ещёдо того как был установлен ТХС. Была сделана проверка флага, тогда программа на этом зацикливалась и отказывалась идти дальше. Потом была мысль, что происходит рассинхронизация мастера и слейва, т.е. слейв передаёт пакеты когда мастер ещё не переключился в режим приёма, тогда были поставлены задержки в программу слейва. Блин..... :cranky: Потом пытался поставить проверку флага RXC, но и из этого ничего путного не вышло, так как раз пакеты не доходят, то и собственно говоря флаг установлен не будет, поэтому программа опять зацикливалась. Потом был организован цикл, длительностью в 40 милисекунд, выход из которого происходил двумя способами - либо по истечению этого времени, либо по установке флага RXC. Из этого тоже ничего путного не вышло... И только увеличением этого цикла я добился (уже сегодня!) более-менее устойчивого приёма, но не всегда с первого раза... вернее с первого раза получалось довольно таки не всегда. (Но не верю я что при такой скорости предача происходит более 200 милисекунд).... :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BlackJack 0 10 октября, 2005 Опубликовано 10 октября, 2005 · Жалоба Согласен.... Но (повторюсь) я вычитал, что переключение режимов происхожит от 70 до 3000 мкс, поэтому я их и поставил. .... выход из которого происходил двумя способами - либо по истечению этого времени, либо по установке флага RXC. Из этого тоже ничего путного не вышло... И <{POST_SNAPBACK}> Фигня :). у меня адм485 переключается сразу. в том смысле, что передернул вывод, а следующей командой можно в UDR писать. на 38400 начало не глотает, проверено. Хотя по сути рс485 вначале и должна идти преамбула=активная пауза. Флаги-то зачем? используй прерывание. Все равно UDR надо прочитать, даже если была ошибка фрейминга. А еще с АДМ бывает такая фишка: без растягивающих резисторов она иногда работает лучше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 10 октября, 2005 Опубликовано 10 октября, 2005 · Жалоба Реальные гланды :) Вот так работает в более десятка разных устройств и мастреров, и слэйвов: #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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться