打印
[其他ST产品]

[经验] 串口接收不定长数据

[复制链接]
597|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jcky001|  楼主 | 2023-6-8 11:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
串口接收不定长数据程序(适合没有空闲中断的单片机),采用的是定时器判断是否接收结束,程序在STM32F4探索者上测试发送间隔50ms以上不会出现粘包现象,20ms偶尔会出现粘包现象。
typedef struct
{
        uint8_t Rec_Flag;
        uint8_t Process;
        uint8_t timeout;/* 单位ms */
        uint8_t Rx_Length;
        uint8_t Tx_Buf[64];
        uint8_t Rx_Buf[64];
}USART_RTx_TypeDef;

extern USART_RTx_TypeDef USART2_RTx;


void USART2_IRQHandler(void)
{
  if(LL_USART_IsActiveFlag_RXNE(USART2) != RESET)
  {
    USART2_RTx.Rx_Buf[USART2_RTx.Rx_Length++]=USART2->DR;
    switch(USART2_RTx.Process)
    {
      case 0:
        USART2_RTx.Timeout=3;
        USART2_RTx.Process=1;
        LL_TIM_EnableCounter(TIM1);
        break;
      case 1:
        USART2_RTx.Timeout=3;
        break;
      default:
        USART2_RTx.Timeout=0;
        USART2_RTx.Process=0;
        LL_TIM_DisableCounter(TIM1);
        break;
    }
  }
}


void TIM1_UP_TIM10_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */
  if(LL_TIM_IsActiveFlag_UPDATE(TIM1) != RESET)
  {
    LL_TIM_ClearFlag_UPDATE(TIM1);
    USART2_RTx.Timeout--;
    if(USART2_RTx.Timeout == 0)
    {
      USART2_RTx.Rec_Flag=1;/* 接收完成标志 */
      LL_TIM_DisableCounter(TIM1);
      USART2_RTx.Process=0;
    }
  }
}

使用特权

评论回复
沙发
sjnh| | 2023-6-8 13:15 | 只看该作者
你这个取决于定时器中断周期和USART2_RTx.Timeout的值,减小定时器周期精度就高了;
不过让我做我会定时器设定一个值(modbus 3.5个周期,9600bps 4ms),在串口中断中清除定时器重新开始计数,定时器产生中断即接收包完成

使用特权

评论回复
板凳
usysm| | 2023-6-10 17:07 | 只看该作者
过DMA和中断方式接收不定长数据

使用特权

评论回复
地板
AloneKaven| | 2023-6-10 23:37 | 只看该作者
用中断可以实现吗?

使用特权

评论回复
5
mikewalpole| | 2023-6-13 22:02 | 只看该作者
#include "stm32f4xx.h"
#include <string.h>
#include <stdio.h>

#define RX_BUFFER_SIZE 256

uint8_t rx_buffer[RX_BUFFER_SIZE];
uint16_t rx_index = 0;
UART_HandleTypeDef huart;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (rx_index >= RX_BUFFER_SIZE) {
        rx_index = 0; //缓冲区溢出,重新开始接收数据
    }
    rx_buffer[rx_index++] = huart->Instance->DR; //将接收到的数据存入缓冲区
    HAL_UART_Receive_IT(&huart, &rx_buffer[rx_index], 1); //继续开启中断接收
}

void DMA_Init(void){
    //配置DMA通道,设置传输方向、内存地址、外设地址、数据长度等参数
}

void UART_Init(void) {
    //配置UART,设置波特率、数据位、停止位、校验位等参数,同时使能接收DMA和接收中断
}

int main(void) {
    HAL_Init();
    //初始化系统时钟等
    DMA_Init(); //初始化DMA通道
    UART_Init(); //初始化UART
    while(1){
        //可以在此处进行数据处理
    }
}

使用特权

评论回复
6
Stahan| | 2023-6-13 22:57 | 只看该作者
造成粘包的原因是什么?

使用特权

评论回复
7
guijial511| | 2023-6-13 23:23 | 只看该作者
用中断接收更合理吧

使用特权

评论回复
8
biechedan| | 2023-6-14 11:50 | 只看该作者
如果帧尾正确,则提取出整个数据帧,并进行相应的处理;否则继续等待接收下一个字节。

使用特权

评论回复
9
louliana| | 2023-6-14 13:06 | 只看该作者
定义了帧头为0xAA,帧尾为0x55。在UART的中断处理函数中,当接收到一个字节时,将其存储到rx_buffer数组中,并判断帧头是否正确。

使用特权

评论回复
10
saservice| | 2023-6-14 19:15 | 只看该作者
可以参考相关文档和示例代码,学习如何使用DMA和中断来实现串口接收不定长数据。

使用特权

评论回复
11
MessageRing| | 2023-6-14 22:36 | 只看该作者
可以用轮询方式来实现的吗

使用特权

评论回复
12
hilahope| | 2023-6-15 22:47 | 只看该作者
在使用串口接收不定长数据时,需要合理设置DMA传输和中断优先级,避免产生冲突和错误。

使用特权

评论回复
13
belindagraham| | 2023-6-19 09:38 | 只看该作者
DMA+串口               

使用特权

评论回复
14
updownq| | 2023-6-21 13:21 | 只看该作者
串口传输时数据按照字节流方式进行,因此需要确定合适的帧头和帧尾以及帧格式。

使用特权

评论回复
15
LOVEEVER| | 2023-6-22 15:56 | 只看该作者
usysm 发表于 2023-6-10 17:07
过DMA和中断方式接收不定长数据

DMA技术确实可以解决这个问题,DMA就是数据直接中转保存

使用特权

评论回复
16
星辰大海不退缩| | 2023-6-30 14:32 | 只看该作者
串口发送有时候跟电压有关系我遇到一次本来3.3V供电,实际为5V供电就导致问题发生

使用特权

评论回复
17
szt1993| | 2023-6-30 17:28 | 只看该作者
其实个人感觉还是DMA取值问题,不断进行快速读取

使用特权

评论回复
18
Undshing| | 2023-7-1 22:30 | 只看该作者
这个也可以用中断实现吧

使用特权

评论回复
19
童雨竹| | 2023-12-30 07:02 | 只看该作者

这些引线越窄越好

使用特权

评论回复
20
Wordsworth| | 2023-12-30 08:05 | 只看该作者

图像由前景和背景组成,在灰度直方图上,前景和背景会形成高峰,在双峰之间的最低谷处就是阈值。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1443

主题

4019

帖子

6

粉丝