| AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
Глюк с UART при засыпании
02.09.2013, 07:53
|
|
|
Гражданин KAZUS.RUN
Регистрация: 29.12.2012
Адрес: Питер
Сообщений: 980
Сказал спасибо: 131
Сказали Спасибо 230 раз(а) в 157 сообщении(ях)
|
Re: Глюк с UART при засыпании
|
Код:
|
ISR(USART1_TX_vect) // обработчик передачи на шину rs485
{
if (tx1_len == 0)
PORTG &= ~(1 ‹‹ 2); // switch tranceiver to receive
if (tx1_len › 0)
{
TCNT0 = 0x100 - rs485_timeout;
UDR1 = tx1_transmission[tx1_ptr];
tx1_ptr++;
tx1_len--;
}
} |
В своё время делал так
|
|
|
|
02.09.2013, 10:35
|
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
_Артём_, TXCIE как флаг не годится - байт ещё не передан в этот момент. Всё равно ждать TXC. А вот сам TXC при пустом буфере - вполне  . И да, сон - это всё, что кроме Idle (либо ADC, либо PWR_DOWN), а 485-й - закладка на универсальность, потому как бывает и так, и эдак.
Godzilla82, не, _delay_ms сама по себе - зло  мало того, что "тормозит" программу без учёта скорости передачи, так ещё и от неё код распухает ибо она практически везде инлайнится. У кого-то подсмотрел и активно пользую обёртку с принудительным __noinline__ для экономии
Wiza_, Ну, как-то так и у меня сделано. Пока, правда, раздельно в UDRIE и TXCIE, но, по мере чистки, сольётся в TXCIE.
|
|
|
|
02.09.2013, 14:46
|
|
|
Гражданин KAZUS.RUN
Регистрация: 16.06.2005
Сообщений: 942
Сказал спасибо: 25
Сказали Спасибо 174 раз(а) в 123 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
- отправили последний байт в обработчике TXC
- счетчик байт обнулили /TXC сбросился/
- О! вот тут ответ на вопрос - здесь же запретили прерывания, раз счётчик нулевой.
- в tx_flush ждём взвода TXC
|
Ну, можно и так, усложнить, и потом героически преодолеть. 
Хотя проще в прерывании ТХС уменьшить счётчик, и если он стал равен 0, выход из прерывания (для 485 интерфейса отключаем передатчик, включаем приём). Иначе пихаем у UDR очередной символ из буфера, и выход из прерывания. И тогда флуш вообще не нужон, ведь в прерывание мы попадаем уже после завершения передачи символа, т.е. условие флуша выполнено, в отличии от прерывания UDRE.
|
|
|
|
02.09.2013, 18:07
|
|
|
Гражданин KAZUS.RUN
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
TXCIE как флаг не годится - байт ещё не передан в этот момент. Всё равно ждать TXC. А вот сам TXC при пустом буфере - вполне .
|
Годится в случае использования для передачи прерывания TXC, а не DRE. Тогда пока передача активна прерывание TXC разрешено, после передачи последнего байта прврывание TXC запрещается (TXCIE=0). В основной программе проверяем TXCIE.
|
|
|
|
02.09.2013, 19:34
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от _Артём_
|
|
Тогда пока передача активна прерывание TXC разрешено, после передачи последнего байта прврывание TXC запрещается (TXCIE=0). В основной программе проверяем TXCIE.
|
В сотый раз говорю - зачем запрещать - разрешать. Ни к чему эти телодвижения. Да ещё при отправке каждого байта.
У нас и так есть флаг _tx.cnt - количество байт, требующих отправки. Если ноль - значит всё. Ждём, пока передаётся последний байт и в сон или на дачу - кому как. А ждать можно и через delay(). Не намного она код распушает. Да и используем её только в 1 месте - перед сном, ну попозже уснули на миллисекунду - ничё страшного, подумаешь - бессоница мучала.
|
|
|
|
02.09.2013, 19:37
|
|
|
Гражданин KAZUS.RUN
Регистрация: 29.12.2012
Адрес: Питер
Сообщений: 980
Сказал спасибо: 131
Сказали Спасибо 230 раз(а) в 157 сообщении(ях)
|
Re: Глюк с UART при засыпании
Поддерживаю. ТХС запрещать не имеет никакого смысла
delay использовать - тоже никакого
|
|
|
|
03.09.2013, 09:34
|
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
Народ!
Не ссорьтесь  Никто и не говорит о запрете/разрешении TXCIE при передаче каждого байта! Только по окончании передачи буфера. Повторюсь, хоть какой, но признак окончания отправки таки нужен при использовании глубокого сна...
Кажется, дошло, что имелось в виду:
|
PHP код:
|
ISR(USART_TXC_vect) {
if (_tx.cnt) _tx.cnt--;
if (_tx.cnt) {
_tx.out = (_tx.out + 1) & UART_TX_BUF_MASK;
UDR = _tx.buf[_tx_out];
}
}
// ...
void flush_tx() {
while(_tx.cnt ) ;
}
|
Последний раз редактировалось av0000; 03.09.2013 в 09:40.
|
|
|
|
03.09.2013, 20:26
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
что имелось в виду:
|
PHP код:
|
ISR(USART_TXC_vect) {
if (_tx.cnt) _tx.cnt--;
if (_tx.cnt) {
_tx.out = (_tx.out + 1) & UART_TX_BUF_MASK;
UDR = _tx.buf[_tx_out];
}
}
// ...
void flush_tx() {
while(_tx.cnt ) ;
}
|
|
Так оно побыстрее работать будет, да и код поменьше:
|
PHP код:
|
ISR(USART_TXC_vect)
{
if (_tx.cnt) {
_tx.cnt--;
_tx.out++;
_tx.out &= UART_TX_BUF_MASK;
UDR = _tx.buf[_tx_out];
}
}
void flush_tx()
{
while(_tx.cnt );
_delay_ms(5);
}
|
_delay_ms(5) необходима, так как _tx.cnt становится равным нулю ещё до окончания передачи байта.
Для скорости 115200 достаточно _delay_us(90);
|
|
|
|
04.09.2013, 00:17
|
|
|
Гражданин KAZUS.RUN
Регистрация: 16.06.2005
Сообщений: 942
Сказал спасибо: 25
Сказали Спасибо 174 раз(а) в 123 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
|
Повторюсь, хоть какой, но признак окончания отправки таки нужен при использовании глубокого сна
|
И чем не устраивает равенство нулю счётчика байт?
|
Код:
|
ISR(USART1_TX_vect) // прерывание завершения передачи символа
{
ByteCountUART--; // уменьшаем счётчик переданных байт
if(!ByteCountUART) // если передали все байты
{
TransiverOff(); // отключаем передатчик RS485
return; // завершаем прерывание
}
UDR1 = *PosBuferUART1++; // если послали не всё, посылаем очередной байт
} |
Очевидно же, что если ByteCountUART равен 0, передача была полностью завершена, и можно спать или заниматься чем угодно.
|
|
|
|
04.09.2013, 10:30
|
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
Someone, в итоге примерно так и вышло.
Оговорка: декремент счётчика без проверки может вызвать переполнение, потому, уменьшаем только если не ноль
А по поводу UDRE - я понял, в чём бонус - в отличие от TXC, прерывание возникает при пустом буфере - не требуется дублировать код отправки первого байта в uart_putch().
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 19:20.
|
|