PIC - как точно отследить отправку последнего байта посылки в UART (485

May 12, 2004 14 Replies

Hi Rifkat !



Совсем недавно 12 May 04 10:05, Rifkat Abdulin писал к All:



RA> Столкнулся со сложностью - надо точно отследить "улет" последнего RA> байта посылки (485). Прерывание (TXIF) не дает такой инфо. TRMT не RA> дает прерываний :-() работает в фоновом режиме - запустил передачу и RA> забыл, пока счетчик байт не обнулится (конвейер в обработчике RA> прерываний). Проблема возникла с необходимостью закрыть передачу (TXEN RA> в 0) - чтобы постоянно не "тарахтели" TXIF и переключить 485 на прием.



из 18-х использовал 18f452 и 18f1320 (с одним портом)



Я обычно просто запрещаю прерывания по пустоте TXREG (сброс бита TXIE), этого хватает. И пусть себе TXIF устанавливается сколько хочет. Разрешение начала передачи очередного байта проверяю как (TXIF & TXIE). Вот кусочек программы обработки прерывания для приема-передачи. Думаю, особых проблем с расшифровкой не будет.



TMR0 используется для определения момента окончания передачи и разных вспомогательных функций (отслеживание таймаутов). tmr0sost- переменная, указывающая режим использования TMR0 (там у меня MODBUS-овский тайминг с его помощью выдерживается и контролируется), используется при обработке прерывания от TMR0. com1buf- это буфер байтов порта com1nbyte- счетчик байтов com1_n_tx_bytes- общее количество передаваемых байт (длина передаваемого пакета)



=== Cut ===



/*-----------------11.03.03 14:50------------------- прерывание по RCIF --------------------------------------------------*/ while ( (RCIE == 1) && (RCIF == 1) ) { /*-----------------15.04.04 10:23------------------- выгребаем все принятые байты (из RCREG и из FIFO ) --------------------------------------------------*/ // ***** принят новый байт *********



if ( com1nbyte >= COM1_LEN_BUF ) com1nbyte = 0; com1buf[com1nbyte] = RCREG;



if ((tmr0sost == 2) ||(tmr0sost == 3) ) { com1nbyte++; //идет прием пакета tmr0sost = 3; // грузим в TMR0 межбайтовый интервал load_tmr0_const (del_interbyte); } else { //продолжается ожидание межпакетного интервала com1nbyte = 0; // грузим в TMR0 межпакетный интервал load_tmr0_const (del_interpkt); } }


/*-----------------11.03.03 14:50------------------- прерывание по TXIF --------------------------------------------------*/ while ( (TXIF == 1) && (TXIE == 1) ) { // есть что передавать /*-----------------15.04.04 10:27------------------- заталкиваем байты до заполнения TXREG (т. е. и в TXREG, и в TSR) --------------------------------------------------*/ // **** окончена передача байта *******



TXREG = com1buf[com1nbyte]; com1nbyte++; if ( com1nbyte >= com1_n_tx_bytes) { //в буфер передатчика передан последний передаваемый байт // => до окончания его передачи осталось время = 2 байта // т.е byte-> TXREG -> TSR ->



// грузим в TMR0 интервал 2байта load_tmr0_const (del_2bytes); TXIE = 0; tmr0sost = 9; } else { // 1.5+2 = 3.5 байта //разрешенный таймаут в линии равен 1.5 байта тишины //(межбайтовый интервал внутри пакета) // грузим в TMR0 интервал 3.5 байта load_tmr0_const (del_3p5bytes); } } === Cut ===


RA> Я работаю с 2мя UART (8720). В одном после отправки последнего байта я RA> по прерыванию (TXIF)анализирую в обработчике TRMT на "пустоту" - как RA> только он освободился, TXEN в 0. Hо во втором UART это не проходит - RA> после записи в TXREG последнего байта (в обработчике RA> прерываний)посылки TXIF поднимается, по выходу из обработчика проц RA> из-за TXIF=1 снова в него впадает, но TRMT еще не успевает обнулиться RA> (показать занятость) - в рез. режется последний байт (TXEN в 0). Попробуй не трогать разрешения приема-передачи, пользуйся только разрешениями прерываний (т.е. RCIE, TXIE). Может, этого будет достаточно? То есть после засовывания в TXREG последнего байта запрещаешь прерывание (TXIE=0). USART себе спокойненько все допередает, прерывания не будет. Чтобы не обрабатывать лишний раз TXIF при попадании в прерывание по другой причине, контролируй пару флагов: TXIF и TXIE.



Hу а переход на прием делай как-нибудь иначе: либо через таймер (как у меня), либо контролируя TRMT (зациклившись или периодически, зависит от требования к точности). И еще. TRMT устанавливается не в конце, а в середине последнего стопового бита. Так что если по-честному, лучше еще пол-бита подождать перед выключением передатчика.


RA> Обработка этого UARTа производится на выходе из обработчика RA> прерываний, первого - на входе. Все по high priority. Мне приходится RA> увеличивать принудительно счетчик байтов на 1. Hеужели достаточно RA> разного кол-ва команд после загрузки в TXREG, чтобы это повлияло на RA> установку TRMT в 0? Все испытывалось на 9600. У меня 9600 хорошо (в смысле без сбоев) работает на единственном уровне прерываний при скорости 9600 и кварце 500 КГц (PIC18F1320). Сказывается наличие буфера FIFO у приемника и буфера TSR у передатчика :)


WBRgrds Ruslan



RM> Попробуй не трогать разрешения приема-передачи, пользуйся только разрешениями RM> прерываний (т.е. RCIE, TXIE). Может, этого будет достаточно?

чтобы снова разрешить TXIE, нужно засечь момент окончания пред. посылки ;-)

RM> Hу а переход на прием делай как-нибудь иначе: либо через таймер (как у меня), RM> либо контролируя TRMT (зациклившись или периодически, зависит от требования к RM> точности). И еще. TRMT устанавливается не в конце, а в середине последнего RM> стопового бита. Так что если по-честному, лучше еще пол-бита подождать перед RM> выключением передатчика.

В прерываниях это как раз не хочется делать - они растягиваются ;-) Я при работе с одним портом UART обычно просто смотрю на TRMT - жду, пока он освободится, и лишь потом иду дальше. Но это опять задержка - фонового режима не получается.

С таймерами и 3.5 байта - это я делаю.

насчет TXREG - как ты его проверяешь на пустоту, не используя TXIF? Я просто не подумал "просто" глянуть на его содержимое (если он это позволяет)

Hello Rifkat.

12 Май 04 10:05, you wrote to All:

Можно узнать что делаеш

Siuchin

SS> Можно узнать что делаеш

Уже сделал - запускаю в производство. Система передачи инфо по GSM/GPRS (в развитии)АСУТП. Каждый блок имеет

485й (Modbus), GSM-модем,24 дискретных изол. входа (до 52В), 8 дискр. изол. выхода (60В/400мА), 8 АЦП (в пике). Может работать как Slave - цепляется к АРМ (авт. раб. место), так и как Master (к нему вешаются датчики и пр.) - на объекте контроля. Можно и 2 АРМа вязать. + тревожные сообщ. от указанных дискретов - SMS, "сиренка". В-общем - "павлино-утко-еж" ;-)

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required