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