Прием и передача данных через USART XMEGA

Posted by Reason89 | Posted in , ,


    В передаче данных по USART нет ничего сложного. Сначала вы ждете пока регистр данных опустошится, а предыдущие данные будут отправлены. А потом просто подставляете в регистр передачи данных, новую посылку.
    Флаг DREIF оповещает о наличии данных в регистре передачи данных. Этот бит находится в регистре состояния USART. Более подробно об этом вы можете узнать на странице 278 в руководстве к МК XMEGA.
    Код для отправки одного символа, довольно прост:
void sendChar(char c)
{
    while( !(USARTC0_STATUS & USART_DREIF_bm) ); //Wait until DATA buffer is empty
    USARTC0_DATA = c;
Если нужно отправить строку из символов:
void sendString(char *text)
{
    while(*text)
    {
        sendChar(*text++);
    }
}
В качестве примера:
int main(void)
{
    setUpSerial();
    while(1)
    {
        _delay_ms(3000);
        sendString("Hello World!\n\r");
    }
}
Для чтения данных по USART осуществляется практически так же. Используется тот же регистр данных, только необходимо проверять другой бит в регистре STATUS:
char usart_receiveByte()

{
    while( !(USARTC0_STATUS & USART_RXCIF_bm) ); //Interesting DRIF didn't work.
    return USARTC0_DATA;    
}
    Обычно используют прерывания, для получения данных.
    При передаче данных полезно делать проверку на ошибки:
//Биты Регистра STATUS
//#define USART_FERR_bm            Флаг ошибки в посылке
//#define USART_PERR_bm            Ошибка паритета
//#define USART_BUFOVF_bm        Флаг переполнения буфера
//#define USART_DREIF_bm        Флаг прерывания по опустошению буфера
//USART_RXCIF_bm                Флаг по завершению передачи
char getChar0(void)

{
    char buffer0;    
    while (1)
        {          
        while( !(USARTC0_STATUS & USART_RXCIF_bm) );
        buffer0=USARTC0_DATA;
        if ((USARTC0_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0)
        return buffer0;
        };    
}
    Общий код с функцией инициализации и функциями приема передачи, у меня выглядит так:
 // Функция включения USART_C0, cкорость 115200 bod
void StartUsartC0()
{   
    USARTC0_BAUDCTRLB = 0;
    USARTC0_BAUDCTRLA = 0x04;
    USARTC0_CTRLA = 0; //Отключение прерываний
    USARTC0_CTRLC = USART_CHSIZE_8BIT_gc; //8 data bits, no parity and 1 stop bit 
    USARTC0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; //Включение приема передатчика
    PORTC_OUTSET = PIN3_bm; 
    PORTC_DIRSET = PIN3_bm; 
    PORTC_OUTCLR = PIN2_bm;
    PORTC_DIRCLR = PIN2_bm;
}
// Функция получения данных USART_C0.
char getChar0(void)
{
    char buffer0;   
    while (1)
        {         
        while( !(USARTC0_STATUS & USART_RXCIF_bm) );
        buffer0=USARTC0_DATA;
        if ((USARTC0_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0)
        return buffer0;
        };   
}
// Фунуция передачи данных USART_C0
void sendChar0(char c0)
{
    while( !(USARTC0_STATUS & USART_DREIF_bm) );
    USARTC0_DATA = c0;
}

Инициализация USART в XMEGA

Posted by Reason89 | Posted in , ,


    Большинство проектов на МК подразумевают связь между ПК и устройством. Либо передача данных между двумя устройствами.
    Вдаваться в то, что такое USART и по какому принципу я не буду, в интернете информации и без того хватает.
    В свою очередь, я приведу примеры работы и настройки модуля USART для МК XMEGA.
    Инициализация USART
    Для начала работы необходимо инициализировать модуль. В качестве примера буду использовать 32 МГц.В Datasheet на странице 284 есть таблица для работы скорости.

    Предположим нам необходима скорость передачи 9600 bod, на мой взгляд самая распространенная. Я стараюсь не использовать умножение скорости передачи(CLK2X = 0), кроме того стараюсь так же не использовать BSCALE. За счет этого расчет скорости упрощается. BSCALE может быть задан от -7 до +7. Его обычно используют, для подстройки скорости, как можно ближе к заданной.
    Слишком тонкая настройка здесь не нужна, во всяком случае как следует из документации. погрешность бывает до 13%.


    Мы в праве использовать для настройки только целые числа, поэтому округляем до 207 и проверяем что из этого вышло.
    Получили довольно близкое значение, с погрешностью меньше 1%. В итоге BSCALE = 0, BSEL = 207. Группа этих битов находится в регистрах BAUDCTRLA и BAUDCTRLB.

USARTC0_BAUDCTRLB = 0;   // BSCALE = 0
USARTC0_BAUDCTRLA = 0xCF;   // BSEL = 207 

    После того как настроили скорость, нужно задать все остальные настройки, такие как размер посылки, стоп бит и бит четности. Это все задается в регистре CTRLC. Я буду использовать в примере 8 бит данных, асинхронный режим с одни стоп битом и без бита четности
USARTC0_CTRLC = USART_CHSIZE_8BIT_gc; 
    Заключительным этапом в настройке является заполнение регистра CTRLB.
    Теперь нас интересуют  два бита RXEN и TXEN, которые включают приемник и передатчик.
// Разрешить принимать и передавать
 USARTC0_CTRLB = USART_TXEN_bm | USART_RXEN_bm;
По умолчанию USART настроен на асинхронную передачу данных, то есть работает в режиме UART.
void setUpSerial()
{
    // Baud rate selection
    // BSEL = (32000000 / (2^0 * 16*9600) -1 = 207.333 -> BSCALE = 0
    // FBAUD = ( (32000000)/(2^0*16(207+1)) = 9615.384 -> it's alright
    USARTC0_BAUDCTRLB = 0; //Just to be sure that BSCALE is 0
    USARTC0_BAUDCTRLA = 0xCF; // 207
    //Disable interrupts, just for safety
    USARTC0_CTRLA = 0;
    //8 data bits, no parity and 1 stop bit 
    USARTC0_CTRLC = USART_CHSIZE_8BIT_gc;
     //Enable receive and transmit
    USARTC0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; // And enable high speed mode
} 
     Отличительной особенностью XMEGA является то, что порты можно переназначать под себя.  По умолчанию TX и RX занимают PC3 и PC2. В более новых версиях Xmega их можно заменить на PC7 и PC6. Более наглядно это представлено в таблице:
     В каждой группе портов есть регистр REMAP, где можно переключаться между альтернативными выводами.

Если в вкратце, то вы просто должны установить бит USART0 в 1, тогда будут использоваться альтернативные выводы.

// Ради примера, я просто переназначил выводы USART с PC3 и PC2 в PC7 и PC6
 PORTC_REMAP | = 0x16;  // Стр 152 в спецификации, перераспределяет USART0
 PORTC_OUTSET = PIN7_bm;  
 PORTC_DIRSET = PIN7_bm;  
 PORTC_OUTCLR = PIN6_bm;
 PORTC_DIRCLR = PIN6_bm;  

Файл Excel для автоматического расчета скорости