Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

Закрытая тема
Опции темы
Непрочитано 25.08.2013, 13:35   #11
niXto
Почётный гражданин KAZUS.RU
 
Аватар для niXto
 
Регистрация: 13.10.2007
Адрес: Беларусь
Сообщений: 8,048
Сказал спасибо: 60
Сказали Спасибо 3,954 раз(а) в 2,309 сообщении(ях)
niXto на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Как я понимаю, смотреть ассемблерный листинг нынче считается дурным тоном...
Реклама:
niXto вне форума  
Непрочитано 25.08.2013, 13:46   #12
av0000
Частый гость
 
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
av0000 на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от Godzilla82 Посмотреть сообщение
Залез в даташит. Везде ссылки на UBRR0, UCSR0A, UCSR0B, UDR0 и т.п.

Ну и сами

Код:
uart_print()
uart_tx_flush()
uart_putch()
в студию.
всякие регистры без нулей - просто дефайны под конкретный контроллер. Код целиком есть в аттаче второго письма, но для желающих дублирую:
Код:
// defs:
#define NOINLINE __attribute__((__noinline__))

// dual-port fix
#ifndef UDRE
    #define UDR     (UDR0)
    #define UDRE    (UDRE0)
    #define UBRRH   (UBRR0H)
    #define UBRRL   (UBRR0L)
    #define UCSRA   (UCSR0A)
    #define UCSRB   (UCSR0B)
    #define UCSRC   (UCSR0C)
    #define RXCIE   (RXCIE0)
    #define TXCIE   (TXCIE0)
    #define UDRIE   (UDRIE0)
    #define RXEN    (RXEN0)
    #define TXEN    (TXEN0)
    #define U2X     (U2X0)
    #define URSEL   (URSEL0)
    #define UCSZ0   (UCSZ00)
    #define UCSZ1   (UCSZ01)
    #define UCSZ2   (UCSZ02)
    #define TXC     (TXC0)
    #define RXC     (RXC0)

#endif

#if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
  #define USART0_UDRE_vect     (USART_UDRE_vect)
  #define USART0_TXC_vect     (USART_TX_vect)
  #define USART0_RXC_vect     (USART_RX_vect)
#endif

// кусочки uart.c
#define UART_TX_BUF_MASK (UART_TX_BUF_SIZE-1)
#define UART_RX_BUF_MASK (UART_RX_BUF_SIZE-1)

static volatile struct {
    uint8_t in, out, cnt;
    uint8_t buf [UART_TX_BUF_SIZE];
} _tx;

NOINLINE uint8_t uart_putch(uint8_t data) {
    uint8_t sreg = SREG;

    // Return failure for non-blocking mode
    #ifdef UART_BLOCK
        #warning *** UART IN BLOCKING MODE ***
        while(_tx.cnt ›= UART_TX_BUF_SIZE) { ; }
    #else
        if (_tx.cnt ›= UART_TX_BUF_SIZE) return 0;
    #endif

    cli();
    #ifdef RS485PORT
        RS485PORT |= (1‹‹RS485PIN); // switch to TX
    #endif

    _tx.buf[_tx.in] = data;
    _tx.in = (_tx.in + 1) & UART_TX_BUF_MASK;
    _tx.cnt++;
    UCSRB |= (1‹‹UDRIE);

    SREG=sreg;
    return 1;
}

void uart_tx_flush(void) {
    while (_tx.cnt) {
        UCSRB |= (1‹‹UDRIE);
    }
    while (
            (UCSRA & ((1‹‹UDRE)|(1‹‹TXC))) !=  ((1‹‹UDRE)|(1‹‹TXC))
          ) { ; }
}

NOINLINE uint8_t uart_print(const char *str) {
    while (*str ) {
        if (!uart_putch(*str++)) return 0;
    }
    return 1;
}

ISR(USART0_UDRE_vect) {
    if (_tx.cnt) {
        UDR = _tx.buf[_tx.out];
        _tx.out = (_tx.out + 1) & UART_TX_BUF_MASK;
        _tx.cnt--;
    }

    if (_tx.in==_tx.out) {
        _tx.cnt = 0;
        _tx.in = 0;
        _tx.out = 0;
        UCSRB &= ~(1 ‹‹ UDRIE);
    }
}
av0000 вне форума  
Непрочитано 25.08.2013, 13:52   #13
av0000
Частый гость
 
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
av0000 на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от niXto Посмотреть сообщение
Как я понимаю, смотреть ассемблерный листинг нынче считается дурным тоном...
Ну, почему же
Пока просто до этой стадии не дошло ибо давненько на столь низкий уровень не заползал (с неделю назад вообще кощунство устроил - начал с java под андроид ковыряться), потому и не задумывался.

Подозревал-то какую-нить очевидность или невниательность, ан - нет, сходу никто носом не ткнул (разве что про принудительную чистку TXC)
av0000 вне форума  
Непрочитано 25.08.2013, 14:06   #14
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

PHP код:
void uart_tx_flush(void) {
    while (
_tx.cnt) {
        
UCSRB |= (1‹‹UDRIE);
    }
    while (
            (
UCSRA & ((1‹‹UDRE)|(1‹‹TXC))) !=  ((1‹‹UDRE)|(1‹‹TXC))
          ) { ; }

То есть пока _tx.cnt›0 (есть, что отправлять), разрешаем передатчик.
И ждём, пока в регистре состояния установятся флаги прерываний UDRE и TXC.

Причём, единожды установленный TXC нигде не сбрасывается.

В даташите не нашёл момента, когда очищается флаг UDRE. Или сам, после выполнения прерывания, или при записи 1. Если сам, то этот цикл могёт зациклится.
Godzilla82 вне форума  
Непрочитано 25.08.2013, 14:10   #15
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Сообщение от av0000 Посмотреть сообщение
Электрически - мега328Р на макетке, встроенный RC на 8МГц, питание 3.3В, TX/RX напрямую подключены к FT232RL (с неё же идёт питание через 1117-3.3) и (в процессе эксперментов) через резисторы 10к на землю.[/CODE]
То есть, когда трансмиттер отключён (нога на вход), формируется старт-бит?
Godzilla82 вне форума  
Непрочитано 25.08.2013, 14:28   #16
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

я бы переписал


PHP код:
 
void uart_tx_flush
(void) {
while (
_tx.cnt);
//                     {
//                     UCSRB |= (1‹‹UDRIE);
//                     }
// зачем каждый раз разрешать прерывания, когда они сами должны
// разрешатся при передаче очередного байта.
// Если этого не происходит - надо исправлять ошибки с передачей.
while ( (UCSRA & (1‹‹TXC)) !=  0);
// здесь ждём окончания передачи последнего байта.

PHP код:
 
ISR
(USART0_UDRE_vect) {
if (
_tx.cnt) {
             
UCSRA = (UCSRA 0b00011111) | (1‹‹TXC) ;
             
UDR _tx.buf[_tx.out];
             
_tx.out = (_tx.out 1) & UART_TX_BUF_MASK;
             
_tx.cnt--;
             }

if (
_tx.in==_tx.out) {
                     
_tx.cnt 0;
                     
_tx.in 0;
                     
_tx.out 0;
                     
UCSRB &= ~(‹‹ UDRIE);
                     }


Последний раз редактировалось Godzilla82; 25.08.2013 в 15:07.
Godzilla82 вне форума  
Непрочитано 25.08.2013, 15:45   #17
av0000
Частый гость
 
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
av0000 на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Godzilla82,
UDRE сам очищается при выходе из прерывания, если прерывания разрешены. (есть где-то там строчка в даташите про это)

Сообщение от Godzilla82 Посмотреть сообщение
То есть, когда трансмиттер отключён (нога на вход), формируется старт-бит?
по поводу лишнего кода и 10k на "землю" - это издержки поиска источника глюков. там вообще сейчас лишних действий с избытком. Из серии "be paranoid" как любят писать наши англо-говорящие друзья, присваивая что-то переменной _за_ бесконечным циклом

Сообщение от Godzilla82 Посмотреть сообщение
я бы переписал
Не уверен на счёт проверки только TXC - он может взвестись между посылками. Исходно было 3 проверки:
1. Ждём обнуления _tx.cnt ("тупо", как предложенном варианте)
2. Ждём взвода UDRE
3. Ждём взвода TXC

Сообщение от Godzilla82 Посмотреть сообщение
UCSRA = (UCSRA & 0b00011111) | (1‹‹TXC) ;
А вот так делать, ЕМНИП, нельзя. Возможно, конкретно про UCSRA я и ошибаюсь, но в даташите регулярно говорится использовать промежуточную переменную для подобного.

Собственно, пока всё сводится к регулярному сбросу TXC. Завтра начну пробовать именно с этого.
av0000 вне форума  
Непрочитано 25.08.2013, 17:08   #18
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Сообщение от av0000 Посмотреть сообщение
UDRE сам очищается при выходе из прерывания, если прерывания разрешены. (есть где-то там строчка в даташите про это)
Обычно, когда есть - явно пишут. Конкретно про UDRE на MEGA328 я не нашёл.

Сообщение от av0000 Посмотреть сообщение
по поводу лишнего кода и 10k на "землю" - это издержки поиска источника глюков.
Издержки - издержками, но зачем посылать старт-бит. ФТ-шка будет думать, что началась передача байта. И по идее должна зафиксировать ошибку фрейма.

Сообщение от av0000 Посмотреть сообщение
Не уверен на счёт проверки только TXC - он может взвестись между посылками.
Программа "однопотоковая". Следовательно, как мы попали в функцию flush(), ничто не должно увеличить _tx.cnt.
В ней мы ждём, чтобы количество данных для отправки _tx.cnt стало равным нулю.
Как только дождались - в этот момент передаётся последний байт. Флаг перед передачей очищен. И мы ждём, когда он возведётся. Всё. Проверять UDRE нет смысла. Тем более, если он сам может очиститься (что сомнительно) после выполнения прерывания.

Сообщение от av0000 Посмотреть сообщение
А вот так делать, ЕМНИП, нельзя. Возможно, конкретно про UCSRA я и ошибаюсь, но в даташите регулярно говорится использовать промежуточную переменную для подобного.
Си при компиляции сам выделит для промежуточных результатов какой-нить регистр. Не вижу ничего криминального. Кроме как упрощения.
RXC0 - флаг USART Receive Complete.
UDRE0 - флаг USART Data Register Empty
Явно не написано, что эти флаги можно сбросить записью 1.
Поэтому сброс флага TXC можно упростить:
PHP код:
 
UCSRA 
|= (1‹‹TXC) ; 

Последний раз редактировалось Godzilla82; 25.08.2013 в 17:13.
Godzilla82 вне форума  
Сказали "Спасибо" Godzilla82
av0000 (25.08.2013)
Непрочитано 25.08.2013, 18:17   #19
av0000
Частый гость
 
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
av0000 на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Godzilla82, Прорыл мануал, про UDRE говорит, что он сбрасывается записью в UDR и в него надо всегда писать "0" для совместимости. Так что всё верно.

ЗЫ: резисторы, разумеется, уберу. Там, кстати, другая засада есть - у FT232 выходы-то 5В, а я схему от 3.3 питаю, неаккуратненько получается (с). А городить преобразование уровней неохота - 232 порт нужен только сейчас, в макете...
av0000 вне форума  
Непрочитано 25.08.2013, 18:27   #20
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Сообщение от av0000 Посмотреть сообщение
Прорыл мануал, про UDRE говорит, что он сбрасывается записью в UDR и в него надо всегда писать "0" для совместимости.
Тогда не совсем понятно с прерыванием. Ну выставился он в 1. Теперь, если прерывание разрешено, оно возникает. Но мы в нём ничего не пишем в UDR0. И UDRIE0 не трогаем. При выходе из прерывания - так как флаг остался взведённым - опять будет возникать прерывание?

Логичнее обрабатывать прерывание по TXC. Завершилась передача 1 байта - прерывание. Флаг очистился. Меньше телодвижений.

А согласование уровней - через резисторы 330 ом.
Godzilla82 вне форума  
Закрытая тема

Закладки

Метки
avr, sleep, usart


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Омывание стирального бака СМА при полоскании Слесарь Делимся опытом 33 29.05.2013 00:03
Проблемы с передачей по UART, нужна помощь sansan25 Микроконтроллеры, АЦП, память и т.д 3 28.01.2012 13:19
Водка и как с ней бороться SerjT Отвлекитесь, эмбеддеры! 108 29.09.2009 21:25
Проблема с электропитанием квартиры tourent Источники питания и свет 85 16.09.2009 07:51
[Решено] Сборник перлов любителей кабельщины mikesmith Отвлекитесь, эмбеддеры! 135 14.08.2007 15:49


Часовой пояс GMT +4, время: 23:37.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot