Регистры USART

Tima123
Offline
Зарегистрирован: 29.01.2020

Здравствуйте, уважаемые форумчане. Изучаю регистры USART atmega328p.

Нашел следующий код:

#include <avr/io.h>
#define F_CPU 16000000UL //16MHz
#include <util/delay.h>

uint8_t i = 0;

void UARTInit(void) {
    UBRRH = 0;
    UBRRL = 103; //baud rate 9600
    UCSRB = (1<<RXEN)|(1<<TXEN);
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8 bit, 1 stop bit
}

void UARTSend(uint8_t data) {
    while(!(UCSRA & (1<<UDRE)));
    UDR = data;
}

int main(void) {
    UARTInit();
    while(1) {
        i++;
        UARTSend(i);
        _delay_ms(1000);
    }
}

Переделал его для Arduino UNO:

uint8_t i = 0;

void setup() 
{
 UARTInit();
}

void loop()
{
  i++;
  UARTSend(i);
  delay(1000);
}

void UARTInit(void) {
    UBRRH = 0;
    UBRRL = 103; //baud rate 9600
    UCSRB = (1<<RXEN)|(1<<TXEN);
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8 bit, 1 stop bit
}

void UARTSend(uint8_t data) {
    while(!(UCSRA & (1<<UDRE)));
    UDR = data;
}

но при проверке пишет ошибку что регистры не объявлены, например вот "'UBRRH' was not declared in this scope".

Код я переделал для ардуино для того чтобы проверить работу USART через регистры в мониторе порта, но видимо что-то сделал неправильно. Хотелось бы узнать побольше. Возможно ли вообще запрограммировать USART через регистры в Ардуине? Или это возможно только на чистом avr? Кому не сложно подскажите, пожалуйста.

 

rkit
Offline
Зарегистрирован: 23.11.2016

Импорты забыл.

b707
Offline
Зарегистрирован: 26.05.2017

потому что на атмеге328 эти регистры называются UBRR0L и UBBR0H

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

не UBRRH, а UBRR0H

и так везде с портами, константами ...

сверяйтесь с именами в iom328p.h

Tima123
Offline
Зарегистрирован: 29.01.2020

Спасибо, частично помогло. Исправил код

uint8_t i = 0;

void setup() 
{
 UARTInit();
}

void loop()
{
  i++;
  UARTSend(i);
  delay(1000);
}

void UARTInit(void) {
    UBRR0H = 0;
    UBRR0L = 103; //baud rate 9600
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    UCSR0C = (1<<UMSEL01)|(1<<UCSZ01)|(1<<UCSZ00); //8 bit, 1 stop bit
}

void UARTSend(uint8_t data) {
    while(!(UCSR0A & (1<<UDRE0)));
    UDR0 = data;
}

Но вылезло другое(. В мониторе порта показывает вот:

 

вроде по таблице для 16 MHz  UBRR0L = 103 (это 9600 бод), но показывает кракозябру.

sadman41
Offline
Зарегистрирован: 19.10.2016

А что вы ожидали увидеть вместо вопросиков?

Tima123
Offline
Зарегистрирован: 29.01.2020

Ожидал увидеть  что то вроде этого

sadman41
Offline
Зарегистрирован: 19.10.2016

Так Serial Monitor не показывает ASCII-коды символов. Возьмите другую терминальную программу.

Tima123
Offline
Зарегистрирован: 29.01.2020

мда, танцы с бубнами только начинаются)

b707
Offline
Зарегистрирован: 26.05.2017

Тима, вы пока символы от байтов с трудом отличаете, колитесь, нафига вам регистры?
Чтобы гордо сказать своей девушке "я не какой-то ардуинщик, я код на регистрах пишу"?:)

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

1<<UMSEL01 это вы что то неверно задали !

(1<<UCSZ01)|(1<<UCSZ00) достаточно для стандартного асинхронного режима 8N1.

Хотите увидеть цифры - передавайте от 0x30 до 0x39.

Tima123
Offline
Зарегистрирован: 29.01.2020

Я хочу научится программировать чистые AVR, а для этого нужно изучить все от и до. И нет это не для того чтобы девушку удивить)). Хоть и медленно, но все же доходит понимание). Дальше больше. Потом буду изучать stm32, у меня даже отладочная плата уже есть STM32F103C8.

Tima123
Offline
Зарегистрирован: 29.01.2020

Да я тоже так подумал. Но в учебном коде было написано 1<<URSEL. Сам код был написан для atmega8. Я думал что это почти одно и тоже что и atmega328p, просто размер flash памяти немного разный, а регистры и все остальное совпадают. Но вот посмотрев регистр UCSR0C, то там и вовсе нету бита URSEL, только UMSEL.

Tima123
Offline
Зарегистрирован: 29.01.2020

сейчас попробую

Tima123
Offline
Зарегистрирован: 29.01.2020

Нет, не получилось. Тоже самое показывает

Вот измененный код

void setup() 
{
 UARTInit();
 delay(1000);
 UARTSend(0x30);
 delay(1000);
 UARTSend(0x31);
 delay(1000);
 UARTSend(0x32);
 delay(1000);
 UARTSend(0x33);
 delay(1000);
 UARTSend(0x34);
 delay(1000);
 UARTSend(0x35);
 delay(1000);
 UARTSend(0x36);
 delay(1000);
 UARTSend(0x37);
 delay(1000);
 UARTSend(0x38);
 delay(1000);
 UARTSend(0x39);
}

void loop()
{

}

void UARTInit(void) {
    UBRR0H = 0;
    UBRR0L = 103; //baud rate 9600
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); //8 bit, 1 stop bit
}

void UARTSend(uint8_t data) {
    while(!(UCSR0A & (1<<UDRE0)));
    UDR0 = data;
}

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

328p на какой частоте трудится ? delay(1000) не нужны - вы же проверяете готовность буфера UART ...

sadman41
Offline
Зарегистрирован: 19.10.2016

А где цыкл хоть какой-нибудь завалящий? Что за хардкор пошел сразу?

Без логического анализатора сложновато будет почувствовать все эти низкоуровневые штучки-дрючки.

Tima123
Offline
Зарегистрирован: 29.01.2020

На 16 MHz.

Tima123
Offline
Зарегистрирован: 29.01.2020

Не понял вас, в смысле?

rkit
Offline
Зарегистрирован: 23.11.2016

Почитай что такое кодировка

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Всё должно работать !

Tima123
Offline
Зарегистрирован: 29.01.2020

А что это за программа-симулятор? Надо бы тоже на ней попробовать.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Proteus