我在ATmega328P微控制器上遇到USART通信问题,希望能提供一些调试方面的帮助.

我面临的问题如下: 我在ATmega328P微控制器上实现了USART通信,通过串行传输字符串"HE".但是,当使用以下代码片段时,串行控制台上的输出重复"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函数时,似乎会出现这个问题.但是,当函数本身定义字符串时,输出是正确的.

有人可以帮助我确定这个问题的根本原因,并建议任何潜在的修复方案?

提前感谢您的帮助.

Observation: 似乎有一个问题与字符串的作用域有关.为字符串分配内存可以在串行控制台上打印正确的输出"HE".

{
    USART_init(UBRR);
    
    char *data = (char*)malloc(3);
    data[0] = 'H';
    data[1] = 'E';
    data[2] = '\0';

    print_serial(data);

    free(data);

    return;
}

推荐答案

我发现问题不在于代码本身,而在于我盲目遵循的构建步骤,

以下是视频中的构建命令:

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

有了这些调整,现在一切都按预期运作.感谢大家抽出时间.

C++相关问答推荐

插入元素后,Sizeof操作符无法正常工作

从STdin读写超过4096个字节

ISO_C_BINDING,从Fortran调用C

为什么写入系统调用打印的字符数不正确?

Char变量如何在不使用方括号或花括号的情况下存储字符串,以及它如何迭代到下一个字符?

在Apple Silicon上编译x86的Fortran/C程序

为什么此共享库没有预期的依赖项?

什么是.c.h文件?

如何在提取的索引中分配空值?

为什么用非常数指针变量改变常量静态变量时会出现分段错误?

循环中的静态变量与块中的变量和循环

无法识别C编程语言的语法,如书中所示

使用C++中的字符串初始化 struct 时,从‘char*’初始化‘char’使指针变为整数,而不进行强制转换

当用C打印过多的';\n';时输出不正确

Makefile无法将代码刷新到ATmega328p

%g浮点表示的最大字符串长度是多少?

为什么孤儿进程在 Linux 中没有被 PID 1 采用,就像我读过的一本书中声称的那样?

System V 消息队列由于某种原因定期重置

添加/删除链表中的第一个元素

C simd _m128 晶圆厂