麻辣不加辣 2024-05-13 08:27 采纳率: 20%
浏览 32

[STM32]PC端通过串口发送多个字符,但每次在mcu上智能存入前2个字节


程序的思路是每次接收到一字节,就输出所有已接收的数据。用来检验数据是否接收成功。

程序如下:

img

串口助手收发如下:

每次都发送“AA BB CC DD”4直接数据,但每次都只有前两字节成功发送。

img

========================================================================

但在把输出的程序,移动到数组写满后的清空数组函数里,却能够输出完整的内容

img

输出与接收结果

img

========================================================================

========================================================================

请教各位这是什么原因,为什么那段程序放在前面就无法存入完整的内容?

  • 写回答

3条回答 默认 最新

  • 笑面虎 2024-05-13 08:27
    关注

    以下内容由CHATGPT及笑面虎共同生成、有用望采纳:


    您想要解决的问题: 您想要解决的问题是在STM32微控制器上使用串口通信时,每次从PC端发送的“AA BB CC DD”四个字节数据,但在MCU上只能存入前两个字节“AA BB”,而后两个字节“CC DD”无法存入接收缓冲区的问题。

    图片内容:

    1. 第一张图片(2bdc9c02-4010-4c72-ae43-6aa6f46ce457_7eeec51b9e164e6bad12b3966df48c1a.png)显示了USART中断处理函数的代码片段,其中包括接收缓冲区的声明、中断判断逻辑和数据接收处理。
    2. 第二张图片(3fdfcbbd-3263-4f50-a78a-b680ea81bf38_b3b1dbea307540dfb388918063ed4054.png)显示了USART中断处理函数的另一部分代码,其中包括数据发送和判断结束位的逻辑。
    3. 第三张图片(9016b27e-1b96-4e69-8892-1517799d242f_a0112e39de134320840d3812ec0c7f63.png)展示了使用串口助手进行数据发送和接收的情况,显示了发送和接收的数据以及串口配置。
    4. 第四张图片(a7a0b500-b0b6-4a54-800b-7f6111372e1b_df9ea4378e4c422cb8600416fb35a821.png)展示了发送区的数据,显示了已发送的字节。

    问题出现原因: 问题可能出现的原因是在中断处理函数中,接收到的数据没有正确地存储到缓冲区中,或者在存储过程中存在逻辑错误,导致只有前两个字节被正确接收和处理。

    问题解决方案:

    1. 确保中断标志位正确设置,并且中断确实被触发。
    2. 检查ubRxlIndex的值是否正确递增,并且没有越界。
    3. 确认USART_ReceiveData(USART1)确实能够接收到数据,并且没有在其他地方被覆盖或修改。
    4. 检查是否有其他地方的逻辑错误,比如错误的数组索引或者条件判断。

    提供代码: 由于您提供的图片中代码不完整,且存在一些语法错误,以下是一个简化的示例代码,用于正确接收和发送数据:

    #define BUFFERSIZE 15
    static uint8_t ubRxlIndex = 0;
    static uint8_t aRxlBuffer[BUFFERSIZE];
    
    void USART1_IRQHandler(void) {
        if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
            if (ubRxlIndex < BUFFERSIZE) {
                aRxlBuffer[ubRxlIndex++] = USART_ReceiveData(USART1);
            }
        }
        if (/* 你的结束位判断逻辑 */) {
            // 处理接收到的数据
            ubRxlIndex = 0; // 重置索引,准备下一次接收
        }
    }
    

    代码运行方式:

    1. 将上述代码替换到您的USART中断处理函数中。
    2. 确保您的STM32开发环境设置正确,包括编译器、烧录器和调试器。
    3. 使用STM32CubeMX配置串口,并生成初始化代码。
    4. 在Keil uVision、STM32CubeIDE或其他IDE中编译并烧录到STM32微控制器。

    代码预期运行结果: 如果代码正确,您应该能够在MCU上接收到完整的四个字节“AA BB CC DD”,并且能够在串口助手中看到发送的完整数据。

    推荐相关链接:

    展开全部

    评论 编辑记录
  • 专家-皆知 2024-05-13 08:28
    关注

    检查MCU代码中读取与处理串口缓冲区的逻辑,确保能正确接收并存储全部数据。

    以上回复有部分引自免费微信小程序:皆我百晓生。 如问题尚未解决,还请稍待,如有疑问请回复进一步沟通。

    评论
    专家-皆知 回复 麻辣不加辣 2024-05-13 08:28

    从您提供的代码片段来看,问题可能在于中断处理函数中的逻辑顺序。当接收到新的字符时,程序立即尝试打印已接收到的所有数据,并在之后进行缓冲区的清空操作。由于中断处理的时间限制以及串口通信的实时性,这可能导致在某些情况下,还未接收到完整的数据包就被迫进行了打印和清空操作。

    为了解决这个问题,可以将打印和清空缓冲区的操作移到一个单独的地方,比如主循环或者定时器中断。这样,即使在中断处理过程中没有接收到完整的数据包,也不会影响后续数据的接收。这里是一个修改过的版本:

    首先,在主循环中添加一个标志变量来检查是否需要打印和清空缓冲区:

    volatile bool print_buffer_flag = false;
    

    然后,调整中断处理函数中的逻辑,仅在接收到结束符时设置print_buffer_flag,并在接收到新字符时更新缓冲区索引:

    void USART1_IRQHandler(void)
    {
        if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
        {
            if (ul_rx_Flag == 1 && ubRxlIndex < BUFFERSIZE1)
            {
                aRx1Buffer[ubRxlIndex++] = USART_ReceiveData(USART1);
                if (aRx1Buffer[ubRxlIndex - 1] == 0x01) // 假设0x01是结束符
                    print_buffer_flag = true;
                else
                    USART_SendData(USART1, aRx1Buffer[ubRxlIndex - 1]);
            }
        }
    }
    

    接下来,在主循环中检查print_buffer_flag,并在其为真时执行打印和清空操作:

    while (1)
    {
        if (print_buffer_flag)
        {
            print_and_clear_buffer();
            print_buffer_flag = false;
        }
    
        // 其他主循环任务...
    }
    
    void print_and_clear_buffer()
    {
        u8 i = 0;
        while (aRx1Buffer[i] != '\0')
        {
            printf("%X", aRx1Buffer[i++]);
        }
        printf("\n\n");
        memset(aRx1Buffer, '\0', BUFFERSIZE1);
        ubRxlIndex = 0;
        printf("0x%X 0x%X\n", OxFE, OxFF); // 错误提示
    }
    

    通过这样的改动,你可以确保在接收到完整的数据包后才进行打印和清空操作,避免了因中断处理时间限制导致的问题。注意,这里的0x01只是一个示例,实际应用中你需要根据实际的协议来确定结束符。同时,这个实现依赖于串口通信中存在明确的结束符,如果没有,那么需要另外的方法来决定何时打印和清空缓冲区,例如设定一个合理的最大等待时间。

    回复
  • 檀越@新空间 2024-05-13 08:28
    关注

    下午好🌅🌅🌅
    本答案参考ChatGPT-3.5

    这个问题的根本原因是在于数据接收和处理的逻辑问题。每次接收到一个字节时就直接输出是不正确的,因为这样无法判断什么时候一个完整的数据帧被接收完毕并可以进一步处理。

    解决方案:

    1. 在代码中加入数据缓冲区,每次接收到一个字节就向缓冲区中添加,直到接收完整的一个数据帧时再进行处理。

    2. 在处理完整帧的逻辑中判断收到的数据是否符合期望,如果符合再进行相应的处理。

    具体代码实现:

    #define FRAME_SIZE 4 // 数据帧长度
    
    uint8_t frameBuffer[FRAME_SIZE]; // 数据缓冲区
    uint8_t frameIndex = 0; // 当前已接收到的字节数
    
    void receiveData(uint8_t data) {
        if (frameIndex < FRAME_SIZE) { // 如果缓冲区未满
            frameBuffer[frameIndex++] = data; // 添加字节到缓冲区
            if (frameIndex == FRAME_SIZE) { // 如果缓冲区已满
                if (frameBuffer[0] == 0xAA && frameBuffer[1] == 0xBB) { // 判断是否符合期望的数据帧
                    // 处理接收到的数据
                }
                frameIndex = 0; // 清空缓冲区
            }
        }
    }
    

    在实现中,我们定义了一个长度为4的数据缓冲区frameBuffer和当前已接收到的字节数frameIndex。每次接收到一个字节时,将字节添加到缓冲区中,并判断缓冲区是否已满。

    如果缓冲区已满,则判断收到的数据是否符合期望的数据帧格式,如果符合则进行相应的处理,否则清空缓冲区等待下一次接收。如果缓冲区未满则继续等待接收。

    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部