2401_85384084 2026-03-13 17:43 采纳率: 90%
浏览 1

stc15f2k60s2单片机程序 串口出现问题

我设置的是发送8个数字的串口 为什么第一次串口接收到的就是正确的 第二次以及之后串口接收到的数据末尾就会有乱码(见最后一张图)
下图为串口.c

img


下图为串口.h

img


之后几张图为包含串口的主要程序

img

img

img

img

img

img

这张图为出现的问题

  • 写回答

1条回答 默认 最新

  • 檀越@新空间 2026-03-13 17:44
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    根据你描述的问题,“第一次串口接收到的数据是正确的,但第二次及之后的接收数据末尾出现乱码”,这通常与以下几种原因有关:


    一、可能的原因分析

    1. 缓冲区未清空或未正确管理

      • 如果使用了接收缓冲区(如 uart_rx_buffer),在每次接收后没有清空缓冲区,可能会导致后续接收时残留旧数据,造成乱码。
    2. 接收中断触发条件不准确

      • 串口接收中断(如 RI)被误触发,导致接收数据不完整或重复。
    3. 发送与接收操作冲突

      • 在发送数据后,没有及时处理接收缓冲区,可能导致接收数据覆盖或混乱。
    4. 波特率设置错误

      • 波特率不一致会导致通信不稳定,尤其是在多帧数据传输中容易出错。
    5. 串口初始化配置问题

      • SCONPCONTCON 等寄存器设置不当,也可能导致数据接收异常。

    二、建议的解决方案(有序列表)

    1. 确保接收缓冲区正确清空

    在每次接收完成后,将接收缓冲区清空,防止旧数据干扰新数据。

    // 示例代码:在接收完成后的处理函数中
    void Uart_Rx_Handler(void) {
        if (RI == 1) {
            RI = 0; // 清除接收标志位
            uart_rx_buffer[uart_rx_index] = SBUF; // 接收一个字节
            uart_rx_index++;
            if (uart_rx_index >= UART_BUFFER_SIZE) {
                uart_rx_index = 0; // 防止越界
            }
        }
    }
    

    注意: 如果你使用的是固定长度的接收(比如8个数字),应提前设定好接收长度,并在达到长度后重置索引。

    2. 检查接收中断是否被多次触发

    确保只在接收完成时才触发一次中断,避免因误触发导致数据错乱。

    // 在接收中断服务程序中,添加判断逻辑
    if (RI == 1) {
        RI = 0;
        // 处理接收逻辑
    }
    

    3. 在发送数据前清空接收缓冲区

    如果你在发送数据后立即接收,可能会有缓存数据未被清除,导致接收乱码。

    // 发送数据前清空接收缓冲区
    uart_rx_index = 0;
    for (int i = 0; i < UART_BUFFER_SIZE; i++) {
        uart_rx_buffer[i] = 0;
    }
    

    4. 检查波特率配置是否正确

    确保单片机和上位机的波特率一致,否则会出现数据丢失或乱码。

    // 例如:115200 波特率
    TMOD = 0x20; // 定时器1模式2
    TH1 = 0xFD;  // 设置为115200波特率
    TL1 = 0xFD;
    TR1 = 1;     // 启动定时器1
    

    5. 优化串口初始化代码

    确保 SCONPCON 配置正确,特别是 SM0SM1 的设置。

    SCON = 0x50; // 8位异步串行模式,允许接收
    PCON = 0x00; // 默认设置
    

    三、示例代码修改(假设你的 uart.c 中有如下结构)

    原始代码(可能存在错误):

    unsigned char uart_rx_buffer[8];
    unsigned char uart_rx_index = 0;
    
    void UART_Init(void) {
        SCON = 0x50; // 8位异步模式
        TMOD = 0x20;
        TH1 = 0xFD;
        TL1 = 0xFD;
        TR1 = 1;
        EA = 1;
        ES = 1;
    }
    
    void UART_ISR(void) interrupt 4 {
        if (RI == 1) {
            RI = 0;
            uart_rx_buffer[uart_rx_index++] = SBUF;
        }
    }
    

    修改后的代码(推荐版本):

    #define UART_BUFFER_SIZE 8
    unsigned char uart_rx_buffer[UART_BUFFER_SIZE];
    unsigned char uart_rx_index = 0;
    
    void UART_Init(void) {
        SCON = 0x50; // 8位异步模式
        TMOD = 0x20;
        TH1 = 0xFD;  // 115200 baud rate
        TL1 = 0xFD;
        TR1 = 1;
        EA = 1;
        ES = 1;
    }
    
    void UART_ISR(void) interrupt 4 {
        if (RI == 1) {
            RI = 0;
            uart_rx_buffer[uart_rx_index++] = SBUF;
            if (uart_rx_index >= UART_BUFFER_SIZE) {
                uart_rx_index = 0; // 重置索引
                // 可以在这里触发接收完成标志
            }
        }
    }
    

    四、调试建议

    • 使用 逻辑分析仪示波器 检查实际发送的信号是否稳定。
    • 在接收端打印接收到的数据,观察是否有重复或多余字符。
    • 添加日志输出,确认每次接收是否成功,以及是否被重复触发。

    五、总结

    重点总结:

    • 接收缓冲区未清空 是最常见的问题之一。
    • 接收中断未正确处理 会导致数据错乱。
    • 波特率不一致 会导致通信失败。
    • 发送与接收操作冲突 也会导致数据异常。

    请根据上述建议逐一排查,如果能提供具体的代码片段(如 uart.cuart.h),我可以进一步帮你定位问题。

    评论

报告相同问题?

问题事件

  • 修改了问题 3月13日
  • 创建了问题 3月13日