我在 ATmega328P 微控制器上遇到 USART 通信问题,希望得到一些调试帮助。
我面临的问题如下: 我已经在 ATmega328P 微控制器上实现了 USART 通信,以通过串行方式传输字符串“HE”。但是,当使用以下代码片段时,串行控制台上的输出会无休止地重复“H H H H H ...”:
#define FOSC 16000000UL
#define BAUD 9600
#define UBRR FOSC/16/BAUD-1
void USART_init(unsigned int ubrr)
{
// Setting Baud rate
UBRR0H = (unsigned char)(ubrr >> 8);
UBRR0L = (unsigned char)ubrr;
//Enable receiver and transmitter
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
//Set frame format: 8data, 2stop bits
UCSR0C = (1 << USBS0) | (1 << UCSZ00) | (1 << UCSZ01);
return;
}
void USART_Transmit(unsigned char data)
{
while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
return;
}
void print_serial(char* data)
{
USART_Transmit(data[0]);
USART_Transmit(data[1]);
USART_Transmit(data[2]);
return;
}
int main()
{
USART_init(UBRR);
print_serial("HE");
return 0;
}
但是,当使用以下修改后的代码片段时,输出符合预期,仅打印一次“HE”:
#define FOSC 16000000UL
#define BAUD 9600
#define UBRR FOSC/16/BAUD-1
void USART_init(unsigned int ubrr)
{
// Setting Baud rate
UBRR0H = (unsigned char)(ubrr >> 8);
UBRR0L = (unsigned char)ubrr;
//Enable receiver and transmitter
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
//Set frame format: 8data, 2stop bits
UCSR0C = (1 << USBS0) | (1 << UCSZ00) | (1 << UCSZ01);
return;
}
void USART_Transmit(unsigned char data)
{
while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
return;
}
void print_serial()
{
char *data = "HE";
USART_Transmit(data[0]);
USART_Transmit(data[1]);
USART_Transmit(data[2]);
return;
}
int main()
{
USART_init(UBRR);
print_serial();
return 0;
}
当将字符串“HE”作为参数传递给 print_serial 函数时,似乎会出现问题。但是,在函数本身内定义字符串时,输出是正确的。
任何人都可以帮我找出此问题的根本原因并提出任何可能的解决方案吗?
预先感谢您的协助。
观察: 似乎可能存在与字符串范围相关的问题。为字符串分配内存允许在串行控制台上打印正确的输出“HE”。
{
USART_init(UBRR);
char *data = (char*)malloc(3);
data[0] = 'H';
data[1] = 'E';
data[2] = '\0';
print_serial(data);
free(data);
return;
}
我发现问题不在于代码本身,而在于我盲目遵循此youtube视频
的构建步骤以下是视频中的构建命令:
avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c main.c -o main.o
avr-gcc -o main.o main.bin
avr-objcopy -O ihex -R .eeprom main.bin main.hex
经过仔细检查,我意识到在第二个命令
avr-gcc -o main.o main.bin
中,我需要指定目标频率和控制器(-DF_CPU=16000000UL -mmcu=atmega328p
)。但是,如果从第一个命令中删除 -c
标志,则第二个命令是不必要的,因为没有多个 c 文件或库。当我使用 SimulIDE 仔细检查数据存储器时,这个问题变得很明显,发现字符串字符被写入通用和 GPIO 寄存器,从而导致意外行为。
确定问题后,我对命令进行了如下修改:
avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p main.c -o main.bin
avr-objcopy -O ihex -R .eeprom main.bin main.hex
通过这些调整,现在一切都按预期进行。谢谢大家的宝贵时间。