Страница 1 из 1

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

Добавлено: Вт апр 07, 2015 15:47:23
Карась
Программа обмена данными с терминалом по 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);
	}
}




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

Добавлено: Вт апр 07, 2015 16:46:09
Карась
Да, забыл: тактовая частота 8 MHz, скорость UART 9600.

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

Добавлено: Вт апр 07, 2015 19:30:42
mas123
В передатчике ( UART_Write ) код неоптимальный - зачем использовать цикл и str, когда можно просто указатель смещать.
В приемнике ( UART_Read ) дырка - переполнение буфера.

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

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

void UART_Read(char *str)
{
....
    memset(str, 0, sizeof(str));
Что будет, если примем 100500 символов, а перевода строки так и не будет?
А, да и зачем 100500, буфер-то у тебя всего на 32 байта. И без контроля на переполнение.
И снова - зачем str, когда можно было просто двигать указатель.

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

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

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

Добавлено: Вт апр 07, 2015 20:59:22
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
.....

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

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