UART на моем atmega328. Регистр данных о статусе USART (UCSR0A) никогда не устанавливался

У меня возникают небольшие проблемы с устранением неполадок при попытке отправки и получения данных в UART моего atmega. Я не знаю, связано ли это с неправильной настройкой тактового цикла или с тем, что я сделал неправильное предположение о том, каким должен быть код, но я взял его из книги примеров.

Я ожидаю записать данные в usart, а затем просто прочитать их обратно. Я просто пытаюсь вывести светодиод на данный момент, но он никогда не светится, так что я предполагаю, что мой код никогда не выйдет из usartReadChar().

Я работаю с atmega328p, а макрос пин/регистр от iom328p. Тактовая частота настроена на 1Mh.

Отличие от книги только в том, что он использует atmega168.

Чего я не понимаю, так это того, что я не заблокирован для отправки данных в usart (пустой регистр данных Usart (UDRE0) на самом деле всегда пуст). Но бит завершения приема (RCX0) в регистре состояния (UCSR0A) также никогда не устанавливается. Как будто бит состояния вообще никогда не работает.

Я безуспешно пытался изменить тактовую частоту процессора. Кстати, я не уверен, как вычислить скорость передачи данных моего usart, и я не уверен, действительно ли это влияет на мой код, поскольку я только локально отправляю данные с AVR. Так мне нужно синхронизировать его с моим процессором?

Я пробовал множество вариантов установки usartInit(), но они никогда не работают.

вот мой код:

#include <avr/io.h>
#include <util/delay.h>


  void initUSART(void) {

  UBRR0H = UBRRH_VALUE;                        /* defined in setbaud.h */
  UBRR0L = UBRRL_VALUE;
#if USE_2X
  UCSR0A |= (1 << U2X0);
#else
  UCSR0A &= ~(1 << U2X0);
#endif
                                  /* Enable USART transmitter/receiver */
  UCSR0B = (1 << TXEN0) | (1 << RXEN0);
  UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);   /* 8 data bits, 1 stop bit */
}

char usartReadChar(){
    while(! (UCSR0A & (1 << RXC0))){}

    return UDR0;
}

void usartWriteChar(char data){
    while(! (UCSR0A & (1 << UDRE0))){}

    UDR0 = data;
}

int main(){
    DDRB   = 0xff;

    char data;
    initUSART();
    usartWriteChar('a');

    while(1){
      data = usartReadChar();
// actually, never reach

      PORTB  = (1 << 0);
    }

    return 0;
}

Когда я скомпилирую его со скоростью 9600 бод, я не получаю никаких предупреждений о скорости передачи. Но если я выберу неправильный Бод, конечно, у меня есть такого рода предупреждение.

/avr/include/util/setbaud.h:227:4: предупреждение: #предупреждение "Достигнутая скорость передачи данных ниже допустимой" [-Wcpp] # предупреждение "Достигнутая скорость передачи данных ниже допустимой"

Итак, я предполагаю, что моя скорость передачи данных верна. Что может быть не так тогда? Ваша помощь будет принята с благодарностью. Спасибо.

* редактировать *

Я отказался от попыток вывести что-то локально в свой avr. Итак, для отладки я подключил свой чип FT232R к контактам rx и tx моего atmega, чтобы посмотреть, может ли что-то выводиться из регистра состояния UCSR0A, и это сработало.

Что странно, так это то, что на самом деле функция отладки для отправки данных в регистр передатчика вообще не работала, даже если UCSR0A говорил, что занят передачей данных.

Согласно книге, данные, отправленные из программы arduino, должны работать, но у меня это совершенно не работало. Но с моего FT232 программа прекрасно работает, как будто USART не был на самом деле инициализирован, когда я вызывал инструкцию для отправки данных в us art. Но поскольку это все синхронно, я знаю, что это не так.

Я нашел много тем о настройке USART на avr, но никто не говорит тестировать отладочную программу, как в моей книге. Поэтому мне интересно, действительно ли это особенность atmega168. На самом деле я не понимаю, почему это не так, как написано в книге.

У вас есть заглушка на последовательном порту?
Привет Докси. Нет, я этого не делал. Речь идет о размещении двух проводов в линии rx / tx?

Ответы (1)

Я не вижу, где вы поместили правильное F_CPUопределение, которое является обязательным для setbaud.h.

Вы также должны определить BAUDмакрос для использования UBRR(L|H)_VALUE, например:

#define F_CPU 1e6       // 1Mhz clock
#include <avr/io.h>
#include <util/delay.h>

void initUSART(void) {
 #define BAUD 9600
 #include <util/setbaud.h> 
 UBRR0H = UBRRH_VALUE;
 UBRR0L = UBRRL_VALUE;
// ...
}

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

И не забудьте подтягивающие резисторы (около 10 кОм) на линиях TX/RX.

Надеюсь, это поможет.