AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
23.08.2013, 22:34
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
[РЕШЕНО] Глюк с UART при засыпании
Приветствую!
Подскажите, куда копать, мысли закончились Как правильно готовить USART к переходу в спящий режим?
Ковырялся с чтением АЦП и записью результатов в порт (всё с прерываниями и засыпанием) и упёрся в непонятность - при входе в любой режим сна в порт посылается ещё кусок мусора. Кусок всегда одинаковый, как будто шлётся лишняя память. При изменении и перезаливке программы меняется. Если после записи в порт добавлять задержку от 1мс, то, вроде, мусор не шлётся. Перед засыпанием "очищаю" выходной буфер ожиданием UDRE и TXC. Попробовал уже в АВР-студии просимулировать - там всё работает корректно.
Электрически - мега328Р на макетке, встроенный RC на 8МГц, питание 3.3В, TX/RX напрямую подключены к FT232RL (с неё же идёт питание через 1117-3.3) и (в процессе эксперментов) через резисторы 10к на землю.
UART на прерываниях по UDR/RXC, самопал, но практически 1:1 традиционный FIFO, буфер не переполняется. Глюк повторяется даже при выводе 1 символа.
Пример ниже честно выводит в порт текст "StartADC", глотает последний символ и добавляет несколько байт мусора.
Код:
|
// куски кода
// Appnote: AVR4013, не влияет на глюк
// DDRD = 0x00;
// PORTD = 0xFF;
UBRR=BAUD38400;
UCSRA=0;
UCSRB = (1‹‹RXCIE) | (1‹‹RXEN) | (1‹‹TXEN);
ADC_DDR &= ~((1‹‹ADC0) | (1‹‹ADC1) | (1‹‹ADC2));
ADC_DIDR |= (1‹‹ADC0) | (1‹‹ADC1) | (1‹‹ADC2);
ADMUX = (1‹‹REFS0) | (1‹‹ADLAR) | (0‹‹MUX0);
ADCSRA = (1‹‹ADEN) | (1‹‹ADPS2) | (0‹‹ADPS1) | (1‹‹ADPS0);
//...
ISR (ADC_vect) {
adcval=ADCW;
uart_putch('.'); //TEST
}
//...
//Собственно запуск:
uart_print("Start ADC\n");
uart_tx_flush(); // wait UDRE & TCX =! 0
// UCSRB &= ~((1‹‹TXEN) | (1‹‹RXEN)); - не влияет
// _delay_ms(5); // вот с этим всё начинает работать
set_sleep_mode(SLEEP_MODE_ADC);
sleep_bod_disable();
sleep_enable();
ADCSRA |= (1‹‹ADSC) | (1‹‹ADIE); // Start ADC
sleep_cpu();
sleep_disable();
for (;;) { ; } |
Последний раз редактировалось av0000; 26.08.2013 в 21:40.
Причина: решено
|
|
|
|
24.08.2013, 00:24
|
|
Гражданин KAZUS.RU
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
//Собственно запуск:
uart_print("Start ADC\n");
uart_tx_flush(); // wait UDRE & TCX =! 0
|
Мало данных: что собой представляет uart_print?
Сообщение от av0000
|
Попробовал уже в АВР-студии просимулировать - там всё работает корректно.
|
Что там работает? Мега в симуляторе к Com-порту подключена?
Сообщение от av0000
|
Перед засыпанием "очищаю" выходной буфер ожиданием UDRE и TXC.
|
А перед посылкой следующего байта флаг TXC очищается? Если нет, то он так и останется установленным после посылки первого байта и к концу строки будет равен 1, хотя байт ещё не передался, а только начал передаваться. Или у вас прерывание на tx_complete есть?
|
|
|
Сказали "Спасибо" _Артём_
|
|
|
24.08.2013, 01:14
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
Сообщение от _Артём_
|
Мало данных: что собой представляет uart_print?
|
uart_print - тупое в цикле while (*str) uart_putch(*str++). В аттаче, вроде, актуальная версия uart.c (485й pin тут не используется)...
Сообщение от _Артём_
|
Что там работает? Мега в симуляторе к Com-порту подключена?
|
Просто симуятор с выводом в hapsim. Ради этого добра пришлось лезть в виртуалку (под убунту сижу)
Сообщение от _Артём_
|
А перед посылкой следующего байта флаг TXC очищается?
...
Или у вас прерывание на tx_complete есть?
|
А вот это интересная мысль! Нет, не очищается и tx_complete в данном случае нет. В железе проверить смогу только в понедельник - макетка на работе. Но это, мне кажется, не должно давать до десятка переданных байт. Грешил на "подвисающие" в воздухе ноги, но "мусор" всегда одинаковый до перекомпиляции...
Количество мусора коррелирует с длиной переданной строки - на '.' раз в секунду - пара байтов (x00, xF9 кажется), на "....." - 4 точки и байт 8 мусора (всё примерно, поскольку железка на работе)
Последний раз редактировалось av0000; 24.08.2013 в 01:16.
|
|
|
|
24.08.2013, 07:39
|
|
Заблокирован
Регистрация: 23.09.2007
Сообщений: 761
Сказал спасибо: 84
Сказали Спасибо 352 раз(а) в 151 сообщении(ях)
|
Re: Глюк с UART при засыпании
Я бы не посылал ничего в UART в прерывании АЦП, даже для теста.
Последний раз редактировалось kosmos440o; 24.08.2013 в 07:43.
|
|
|
|
24.08.2013, 10:17
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
Сообщение от kosmos440o
|
Я бы не посылал ничего в UART в прерывании АЦП, даже для теста.
|
Само собой! Это уже издержки отладки и поиска места глюка. Изначально в прерывании была проверка десятка условий и переключение измеряемого канала, но, в процессе отладки, оставлял даже пустой обработчик.
|
|
|
|
24.08.2013, 16:57
|
|
Почётный гражданин KAZUS.RU
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 7,027
Сказал спасибо: 3,031
Сказали Спасибо 3,204 раз(а) в 2,174 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
Как правильно готовить USART к переходу в спящий режим?
Ковырялся с чтением АЦП и записью результатов в порт (всё с прерываниями и засыпанием) и упёрся в непонятность - при входе в любой режим сна в порт посылается ещё кусок мусора.
|
Моё мнение - копать в uart_tx_flush(). В обычном режиме - достаточно опрашивать только UDRE, так будет использоваться внутренный буфер. Перед переходом в спящий - дождаться установки TXC.
Ну и Х.З., что там в архиве.
Сообщение от av0000
|
В аттаче, вроде, актуальная версия uart.c (485й pin тут не используется)...
...
Нет, не очищается и tx_complete в данном случае нет.
|
Как я понимаю, код из архива может вести передачу только при разрешённом прерывании по UDRE.
|
|
|
|
24.08.2013, 18:01
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
Сообщение от ForcePoint
|
Моё мнение - копать в uart_tx_flush(). В обычном режиме - достаточно опрашивать только UDRE, так будет использоваться внутренный буфер. Перед переходом в спящий - дождаться установки TXC.
|
Там почти так и происходит, разве что TXC ждётся всегда (а не только перед сном), _но_ перед ожиданием не очищается, на что намекнул _Артём_.
Сообщение от ForcePoint
|
Как я понимаю, код из архива может вести передачу только при разрешённом прерывании по UDRE.
|
Да. Код стандартный, как его традиционно и делают в обработчике UDRE: есть, что передавать - в UDR его, закончилось - запретили UDRIE.
Добавлено только обнуление счётчиков буфера - также на время поиска глюка.
Пока остается дождаться понедельника и попробовать вариант с чисткой TСX.
|
|
|
|
25.08.2013, 03:07
|
|
Почётный гражданин KAZUS.RU
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
Код:
|
//Собственно запуск:
uart_print("Start ADC\n");
uart_tx_flush(); // wait UDRE & TCX =! 0 |
|
Не уверен, что "Start ADC\n" имеет завершающий нуль.
|
|
|
|
25.08.2013, 11:02
|
|
Частый гость
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Глюк с UART при засыпании
Сообщение от Godzilla82
|
Не уверен, что "Start ADC\n" имеет завершающий нуль.
|
Не, вот тут-то всё правильно. Это же Си, там с asciiz строками всё честно
Кроме того, не было б там нуля - мусор бы печатался и при использовании _delay_ms(5), с которой всё нормально работает. Кстати, в мусоре и нулей хватает порой…
Более того, всё работает даже если в цикле _без_задержек_ ждать готовности ADC, но не засыпать.
|
|
|
|
25.08.2013, 13:30
|
|
Почётный гражданин KAZUS.RU
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
|
Re: Глюк с UART при засыпании
Сообщение от av0000
|
Код:
|
UBRR=BAUD38400;
UCSRA=0;
UCSRB = (1‹‹RXCIE) | (1‹‹RXEN) | (1‹‹TXEN);
//...
// UCSRB &= ~((1‹‹TXEN) | (1‹‹RXEN)); - не влияет
for (;;) { ; } |
|
Залез в даташит. Везде ссылки на UBRR0, UCSR0A, UCSR0B, UDR0 и т.п.
Последний раз редактировалось Godzilla82; 25.08.2013 в 14:06.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 13:53.
|
|