У меня возникают небольшие проблемы с устранением неполадок при попытке отправки и получения данных в 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. На самом деле я не понимаю, почему это не так, как написано в книге.
Я не вижу, где вы поместили правильное 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.
Надеюсь, это поможет.
ДоксиЛовер
Мистер Бонжур