Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Enot555
Доброго времени суток!
Подскажите, пожалуйста, как вывести контроллер (ATmega8) из режима передачи?
При организации прерываний по USART_DR_Empty и USART_Transmit_Complete после окончания передачи устанавливаются флаги UDRE и TXE и, поскольку UDRE имеет приоритет по прерываниям, то до TXE дело никогда не доходит. Как сбросить UDRE без записи в него новых данных (которые он воспринимает как данные для передачи следующего бита и так далее...)
ae_
UDRE не нужно сбрасывать, UDRE=1 сразу после сброса и означает, что UART готов передавать данные. Надо просто запрещать прерывания UDRIE=0, когда больше нечего передавать.
Enot555
[quote name='ae_' date='Apr 26 2008, 03:22' post='403016']
UDRE не нужно сбрасывать, UDRE=1 сразу после сброса и означает, что UART готов передавать данные. Надо просто запрещать прерывания UDRIE=0, когда больше нечего передавать.



спасибо, понял


[quote name='ae_' date='Apr 26 2008, 03:22' post='403016']
UDRE не нужно сбрасывать, UDRE=1 сразу после сброса и означает, что UART готов передавать данные. Надо просто запрещать прерывания UDRIE=0, когда больше нечего передав

Хотя нет, попробовал на практике и не понял, ведь когда осуществляется прерывание по UDRIE, еще идет передача битов последнего байта. Как тогда контролировать окончание передачи, по последнему биту сдвигового регистра? Если так, то какой его (регистра) адрес (не нашел ни в одном описании)?.
tazik
Цитата
Хотя нет, попробовал на практике и не понял, ведь когда осуществляется прерывание по UDRIE, еще идет передача битов последнего байта.


Совершенно верно

Цитата
Как тогда контролировать окончание передачи, по последнему биту сдвигового регистра? Если так, то какой его (регистра) адрес (не нашел ни в одном описании)?.


Если Вы хотите "контролировать окончание передачи, по последнему биту сдвигового регистра", то используйте прерывание по TXC:UART Transmit complete.

This flag is
especially useful in half-duplex communications interfaces, where a transmitting application
must enter receive mode and free the communications bus immediately after
completing the transmission.

Т.е. этот флаг особенно полезен при работе с полудуплексным интерфейсом, когда передающее приложение должно перейти в режим приема и освободить линию связи сразу после завершения передачи.

Адреса внутреннего сдвигового регистра ни в одном описании Вы не найдете. Зачем оно нужно, если есть флаг TXC.

Похоже, что в Вашем случае линии TXD и RXD физически разделены (т.е. прием и передача по 2 разным проводам). Тогда лучше использовать прерывание UDRE: UART Data register empty.

Либо UDRE, либо TXC - сразу оба использовать не нужно (в общем случае)
Enot555
Либо UDRE, либо TXC - сразу оба использовать не нужно (в общем случае)

Спасибо, с использованием прерывания TXCIE побайтную передачу организовал.
Но все же мучает вопрос, как (можно ли) организовать передачу массива с использованием прерывания UDRIE, и после окончания передачи всего массива выключить передатчик. Ведь когда осуществляется прерывание по UDRIE, еще идет передача битов из сдвигового регистра, и если выключить передатчик из подпрограммы обработки прерывания, передача последнего байта завершена не будет.
mdmitry
ДляATmega128
Код
ISR(USART1_UDRE_vect)
/*************************************************************************
Function: UART Data Register Empty interrupt
Purpose:  called when the UART is ready to transmit the next byte
**************************************************************************/
/* signal handler for uart data buffer empty interrupt */
{

    if(uart_txd_Tail != uart_txd_Head)
    {
        UDR1 = uart_txd_buffer[uart_txd_Tail];
    
        /* calculate and store new buffer index */
        uart_txd_Tail++;
        uart_txd_Tail &= UART_TXD_BUFFER_MASK;
    }
    else
    {
        /* tx buffer empty, disable UDRE interrupt */
        UCSR1B &= ~_BV(UDRIE1);
    }

}


Работа с кольцевым буфером. Посмотрите avrlib, я модифицировал код оттуда.
Для работы с кольцевым буфером надо несколько функций:
Код
int uart_rputc(const uint8_t symbol)
/* Запись символа в кольцевой буфер */
/* Возвращаемое значение:    */
/* >= 0 - OK,                */
/* < 0  - error, buffer FULL */
{
    if((uart_txd_Tail - uart_txd_Head - 1) != 0)
    {
        uart_txd_buffer[uart_txd_Head] = symbol;
        uart_txd_Head++;
        uart_txd_Head &= UART_TXD_BUFFER_MASK;        
        
        UCSR1B |= _BV(UDRIE1);

        return symbol;
    }
    return EXIT_FAILUREN;        /* buffer is full */    

}

и
Код
uint8_t uart_rwrite(const uint8_t *buf, const uint8_t datalength)
/* Запись блока данных в кольцевой буфер */
/* Возвращаемое значение:             */
/* >= 0 - число записанных символов */
{
    register uint8_t res = 0, count;
    
    for(count = datalength; count != 0; ++buf, --count){
        if(uart_rputc(*buf) >= 0)
            ++res;
    }
    return(res);
}

UART работает на 115200.
tazik
Цитата(Enot555 @ Apr 26 2008, 19:18) *
Ведь когда осуществляется прерывание по UDRIE, еще идет передача битов из сдвигового регистра, и если выключить передатчик из подпрограммы обработки прерывания, передача последнего байта завершена не будет.


В принципе, mdmitry уже дал исчерпывающий ответ...

А как вы предполагаете выключать передатчик? Сбросом бита TXEN в UART Control register?
В документации по этому поводу написано:
Bit 3 – TXEN: Transmitter Enable
This bit enables the UART transmitter when set (one). When disabling the transmitter
while transmitting a character, the transmitter is not disabled before the character in the
shift register plus any following character in UDR has been completely transmitted.

В общем, даже если Вы запретите работу передатчика. Он все-таки завершит передачу данных из промежуточного регистра и следующего символа в регистре UDR (если он есть) и только после этого выключится.

Так что можете смело выключать передатчик - данные не потеряются
Enot555
Цитата
Так что можете смело выключать передатчик - данные не потеряются


Спасибо, впредь буду внимательнее читать Datasheet
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.