UART начинающим программистам AVR

Обсуждаем контроллеры компании Atmel.
Ответить
Карась
Открыл глаза
Сообщения: 67
Зарегистрирован: Ср май 28, 2008 14:33:11
Откуда: Россия, Саров
Контактная информация:

UART начинающим программистам AVR

Сообщение Карась »

Программа обмена данными с терминалом по UART: Вводит строку и возвращает её обратно.
Может кому пригодится как пример кода.

Код: Выделить всё

#include <avr\io.h>
#include <string.h>

void UART_Init(void)
{
   UBRRH = 0;
   UBRRL = 51;
   UCSRC = _BV(URSEL) | (3<<UCSZ0);
   UCSRB = _BV(TXEN) | _BV(RXEN);
}

void UART_Write(const char *str)
{
    int i;

    for (i=0; str[i]; i++) {
        while (!(UCSRA & _BV(UDRE)));
        UDR = str[i];
   }

}

void UART_Read(char *str)
{
    int i = 0;
    char ch;

    memset(str, 0, sizeof(str));

    do {
      while (!(UCSRA & _BV(RXC)));
      ch = UDR;
      str[i] = ch;
      i++;
      while (!(UCSRA & _BV(UDRE)));
      UDR = ch;
    } while (ch != 0x0D);
}

int main(void)
{
   char str[32];

   asm("wdr");
   WDTCR = _BV(WDCE) | _BV(WDE);
   WDTCR = 0;
   UART_Init();

   for (;;) {
      UART_Read(str);
      UART_Write(str);
   }
}



Карась
Открыл глаза
Сообщения: 67
Зарегистрирован: Ср май 28, 2008 14:33:11
Откуда: Россия, Саров
Контактная информация:

Re: UART начинающим программистам AVR

Сообщение Карась »

Да, забыл: тактовая частота 8 MHz, скорость UART 9600.
mas123
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Re: UART начинающим программистам AVR

Сообщение mas123 »

В передатчике ( UART_Write ) код неоптимальный - зачем использовать цикл и str[i], когда можно просто указатель смещать.
В приемнике ( UART_Read ) дырка - переполнение буфера.

Это занулит не весь буфер *str, как хотелось бы, а лишь байтик.

Код: Выделить всё

void UART_Read(char *str)
{
....
    memset(str, 0, sizeof(str));

Что будет, если примем 100500 символов, а перевода строки так и не будет?
А, да и зачем 100500, буфер-то у тебя всего на 32 байта. И без контроля на переполнение.
И снова - зачем str[i], когда можно было просто двигать указатель.

Код: Выделить всё

    do {
      while (!(UCSRA & _BV(RXC)));
      ch = UDR;
      str[i] = ch;
      i++;
      while (!(UCSRA & _BV(UDRE)));
      UDR = ch;
    } while (ch != 0x0D);
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Re: UART начинающим программистам AVR

Сообщение oleg110592 »

а если тактовая частота другая или скорость UART нужна тоже другая, чего делать? Думаю надо добавить:

Код: Выделить всё

#define F_CPU 16000000UL  // 16 MHz

// Define baud rate
#define USART_BAUDRATE 38400   
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
.....
void USART_Init(void){
   // Set baud rate
   UBRRH = (BAUD_PRESCALE >> 8);// Load upper 8-bits into the high byte of the UBRR register
   UBRRL = BAUD_PRESCALE;// Load lower 8-bits into the low byte of the UBRR register
.....
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: UART начинающим программистам AVR

Сообщение ARV »

вообще-то для корректной установки регистров скорости UART существует "библиотечный" модуль util/setbaud.h. ну и для начинающего "в стиле ардуино" (т.е. не сильно переживающего за объем кода) я рекомендовал бы использовать мое простейшее решение
кстати, хоть я и не начинающий, и ардуино не применяю, сам активно использую именно этот подход - он куда как гибче предложенного здесь...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

Вернуться в «AVR»