硬汉嵌入式论坛

 找回密码
 立即注册
查看: 7706|回复: 40
收起左侧

串口FIFO的comGetChar函数正确使用姿势

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2019-7-24 00:18:29 | 显示全部楼层 |阅读模式
多位网友咨询这个函数。

觉得使用不方便,希望提供一个数组方式,其实这个函数很好用。

像我们的ESP8266,GPS,GPRS等例子都是基于这个函数实现。

可以论坛置顶帖V6网盘下载相应例子。

简单使用方式一:

这里用户可以将读取的read值存到一个数组里面,每读取到一次往数组里面存一下。

1.jpg

略微复杂的使用方式二:
比如远程端发送的数据格式如下:

8.jpg

程序代码就可以这样实现:

  1. /*
  2. *********************************************************************************************************
  3. *        函 数 名: main
  4. *        功能说明: c程序入口
  5. *        形    参: 无
  6. *        返 回 值: 错误代码(无需处理)
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.         uint8_t ucKeyCode;        
  12.         uint8_t read;
  13.         uint8_t ucStatus = 0;  /* 状态机标志 */
  14.         uint8_t ucCount=0, i;
  15.         uint8_t buf[128];
  16.         
  17.         
  18.         bsp_Init();                /* 硬件初始化 */

  19.         bsp_StartAutoTimer(0, 100);        /* 启动1个100ms的自动重装的定时器 */
  20.         
  21.         /* 主程序大循环 */
  22.         while (1)
  23.         {
  24.                 /* CPU空闲时执行的函数,在 bsp.c */
  25.                 bsp_Idle();               
  26.                
  27.                 /* 判断定时器超时时间 */
  28.                 if (bsp_CheckTimer(0))        
  29.                 {
  30.                         /* 每隔100ms 进来一次 */
  31.                         /* 翻转LED2的状态 */
  32.                         bsp_LedToggle(2);        
  33.                 }
  34.                
  35.                 /* 接收到的串口命令处理 */
  36.                 if (comGetChar(COM1, &read))
  37.                 {
  38.                         switch (ucStatus)
  39.                         {
  40.                                 /* 状态0保证接收到0x01 */
  41.                                 case 0:
  42.                                         if(read == 0x01)
  43.                                         {
  44.                                                 ucStatus = 1;        
  45.                                         }
  46.                                         break;
  47.                                        
  48.                                 /* 状态1保证接收到0x03 */
  49.                                 case 1:
  50.                                         if(read == 0x03)
  51.                                         {
  52.                                                 ucStatus = 2;
  53.                                         }
  54.                                         else
  55.                                         {
  56.                                                 ucStatus = 0;
  57.                                         }
  58.                                         break;
  59.                                        
  60.                                 /* 状态2保证接收到0x0E */
  61.                                 case 2:
  62.                                         if(read == 0x0E)
  63.                                         {
  64.                                                 ucStatus = 3;
  65.                                         }
  66.                                         else
  67.                                         {
  68.                                                 ucStatus = 0;
  69.                                         }
  70.                                         break;

  71.                                 case 3:
  72.                                         buf[ucCount] = read;
  73.                                        
  74.                                         /* 接收够15个数据 */
  75.                                         if(ucCount == 15)
  76.                                         {
  77.                                                 /* 打印接收到的数据值 */
  78.                                                 printf("接收到的数据:");
  79.                                                 for(i = 0; i < ucCount + 1; i++)
  80.                                                 {
  81.                                                         printf("%x ", buf[i]);
  82.                                                 }
  83.                                                 printf("\r\n");
  84.                                                 ucStatus = 0;
  85.                                                 ucCount=0;
  86.                                         }
  87.                                         else
  88.                                         {
  89.                                                 ucCount++;
  90.                                         }
  91.                                         break;
  92.                                 
  93.                                 default:
  94.                                         break;
  95.                         }
  96.                 }
  97.                
  98.         }
  99. }
复制代码







回复

使用道具 举报

2

主题

569

回帖

575

积分

金牌会员

积分
575
发表于 2019-7-24 00:22:38 | 显示全部楼层
我在好多项目上都是用的Uart+DMA+idle接收,DMA发送。用idle的方式不太适合数据帧断断续续
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2019-7-24 00:26:01 | 显示全部楼层
leiyitan 发表于 2019-7-24 00:22
我在好多项目上都是用的Uart+DMA+idle接收,DMA发送。用idle的方式不太适合数据帧断断续续

DMA方式的就是太灵活,这里有:

基于V6的CMSIS-Driver串口应用,支持8串口DMA不定长收发,比CubeMX还要省事
http://www.armbbs.cn/forum.php?m ... 3714&fromuid=58
(出处: 安富莱电子论坛)
回复

使用道具 举报

0

主题

9

回帖

9

积分

新手上路

积分
9
发表于 2019-7-24 11:15:55 | 显示全部楼层
mark。。
串口没人用法不一样。。。。。。。。
学习一下。
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2019-8-13 11:55:27 | 显示全部楼层
谢谢Eric老师的例程,之前没有注册成功。在此分享一下我应用此例程的使用结果,我的目标是接收7个两位的16进制数,并提取三四位进行显示通过更改此例程实现。
  1.                 while (status == 1)                                                         /* 读取变送器中数据主循环 */
  2.                 {      
  3.                                 comSendBuf(COM3,_ucaBuf,sizeof(_ucaBuf));
  4.                                 bsp_DelayMS(500);
  5.                                 for(i=0;i<7;i++)                         /* 等于7时,每个都读取14位返回值 */
  6.                                 {
  7.                                 if (comGetChar(COM3, &read)) /* 接收到的串口命令处理 */
  8.                 {                                                               
  9.                         switch (ucStatus)
  10.                         {      
  11.                                                                 case 0:
  12.                                         if(read == 0x01)/* 状态0保证接收到0x01 */
  13.                                         {ucStatus = 1;}
  14.                                         break;            
  15.                                 case 1:
  16.                                         if(read == 0x03) /* 状态1保证接收到0x03 */
  17.                                         {ucStatus = 2;}
  18.                                         else
  19.                                         {ucStatus = 0;}
  20.                                         break;
  21.                                 case 2:
  22.                                         if(read == 0x02)/* 状态2保证接收到0x02 */
  23.                                         {ucStatus = 3;}
  24.                                         else
  25.                                         {ucStatus = 0;}
  26.                                         break;
  27.                                 case 3:
  28.                                                                                 sensor_buf[ucCount] = read;
  29.                                         if(ucCount == 3)                                /* 接收够4个数据 */
  30.                                         {
  31.                                                 for(i = 0; i < ucCount+1; i++)
  32.                                                 {
  33. //                                                                                                        printf("%c ", buf[i]);
  34.                                                 }
  35.                                                                                                 FormRSV->ReturnValue=sensor_buf[0]*16*16+sensor_buf[1];                        /* 16进制返回值 */
  36.                                                                                                 DispReturnValue();
  37.                                                                                                 FormRSV->TempValue=(sensor_buf[0]*16*16+sensor_buf[1])/10-273;        /* 转换成温度值*/                                       
  38.                                                                                                 DispTempValue();
  39.                                                 ucStatus = 0;
  40.                                                                                                 ucCount=0;
  41.                                         }
  42.                                         else
  43.                                         {ucCount++;}
  44.                                         break;
  45.                                 default:
  46.                                                                                 break;
  47.                         }
  48.                 }
  49.                                 }
  50.                                 ucTouch = TOUCH_GetKey(&tpX, &tpY);        /* 读取触摸事件 */
  51.                                 if (ucTouch != TOUCH_NONE)
  52.                                 {
  53.                                         switch (ucTouch)
  54.                                         {
  55.                                                 case TOUCH_DOWN:                /* 触笔按下事件 */
  56.                                                         if (TOUCH_InRect(tpX, tpY, BTN_RET_X, BTN_RET_Y, BTN_RET_H, BTN_RET_W))
  57.                                                         {
  58.                                                                 FormRSV->BtnRet.Focus = 1;
  59.                                                                 LCD_DrawButton(&FormRSV->BtnRet);
  60.                                                                 status = 0;
  61.                                                         }
  62.                                                         break;

  63.                                                 case TOUCH_RELEASE:                /* 触笔释放事件 */
  64.                                                         if (TOUCH_InRect(tpX, tpY, BTN_RET_X, BTN_RET_Y, BTN_RET_H, BTN_RET_W))
  65.                                                         {
  66.                                                                 FormRSV->BtnRet.Focus = 0;
  67.                                                                 LCD_DrawButton(&FormRSV->BtnRet);
  68.                                                                 fQuit = 1;        /* 返回 */
  69.                                                                 status = 0;
  70.                                                         }
  71.                                                         else        /* 按钮失去焦点 */
  72.                                                         {
  73.                                                                 FormRSV->BtnRet.Focus = 0;
  74.                                                                 LCD_DrawButton(&FormRSV->BtnRet);
  75.                                                                 status = 0;
  76.                                                         }
  77.                                                         break;
  78.                         }
  79.                 }
  80.                 }
复制代码
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2019-8-13 11:57:06 | 显示全部楼层
谢谢Eric老师的例程。我是通过此例程修改后完成的实时读取7个两位16进制数,并实现实时显示其中第3个和第4个的值
                while (status == 1)                                                         /* 读取变送器中数据主循环 */
                {      
                                comSendBuf(COM3,_ucaBuf,sizeof(_ucaBuf));
                                bsp_DelayMS(500);
                                for(i=0;i<7;i++)                         /* 等于7时,每个都读取14位返回值 */
                                {
                                if (comGetChar(COM3, &read)) /* 接收到的串口命令处理 */
                {                                                               
                        switch (ucStatus)
                        {      
                                                                case 0:
                                        if(read == 0x01)/* 状态0保证接收到0x01 */
                                        {ucStatus = 1;}
                                        break;            
                                case 1:
                                        if(read == 0x03) /* 状态1保证接收到0x03 */
                                        {ucStatus = 2;}
                                        else
                                        {ucStatus = 0;}
                                        break;
                                case 2:
                                        if(read == 0x02)/* 状态2保证接收到0x02 */
                                        {ucStatus = 3;}
                                        else
                                        {ucStatus = 0;}
                                        break;
                                case 3:
                                                                                sensor_buf[ucCount] = read;
                                        if(ucCount == 3)                                /* 接收够4个数据 */
                                        {
                                                for(i = 0; i < ucCount+1; i++)
                                                {
//                                                                                                        printf("%c ", buf[i]);
                                                }
                                                                                                FormRSV->ReturnValue=sensor_buf[0]*16*16+sensor_buf[1];                        /* 16进制返回值 */
                                                                                                DispReturnValue();
                                                                                                FormRSV->TempValue=(sensor_buf[0]*16*16+sensor_buf[1])/10-273;        /* 转换成温度值*/                                       
                                                                                                DispTempValue();
                                                ucStatus = 0;
                                                                                                ucCount=0;
                                        }
                                        else
                                        {ucCount++;}
                                        break;
                                default:
                                                                                break;
                        }
                }
                                }
                                ucTouch = TOUCH_GetKey(&tpX, &tpY);        /* 读取触摸事件 */
                                if (ucTouch != TOUCH_NONE)
                                {
                                        switch (ucTouch)
                                        {
                                                case TOUCH_DOWN:                /* 触笔按下事件 */
                                                        if (TOUCH_InRect(tpX, tpY, BTN_RET_X, BTN_RET_Y, BTN_RET_H, BTN_RET_W))
                                                        {
                                                                FormRSV->BtnRet.Focus = 1;
                                                                LCD_DrawButton(&FormRSV->BtnRet);
                                                                status = 0;
                                                        }
                                                        break;

                                                case TOUCH_RELEASE:                /* 触笔释放事件 */
                                                        if (TOUCH_InRect(tpX, tpY, BTN_RET_X, BTN_RET_Y, BTN_RET_H, BTN_RET_W))
                                                        {
                                                                FormRSV->BtnRet.Focus = 0;
                                                                LCD_DrawButton(&FormRSV->BtnRet);
                                                                fQuit = 1;        /* 返回 */
                                                                status = 0;
                                                        }
                                                        else        /* 按钮失去焦点 */
                                                        {
                                                                FormRSV->BtnRet.Focus = 0;
                                                                LCD_DrawButton(&FormRSV->BtnRet);
                                                                status = 0;
                                                        }
                                                        break;
                        }
                }
                }
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2019-8-13 12:08:36 | 显示全部楼层
noviceyao 发表于 2019-8-13 11:55
谢谢Eric老师的例程,之前没有注册成功。在此分享一下我应用此例程的使用结果,我的目标是接收 ...

非常感谢分享
回复

使用道具 举报

2

主题

87

回帖

93

积分

初级会员

积分
93
发表于 2020-2-25 10:16:16 | 显示全部楼层
请教一个问题:我也是参考这个例子, /* 接收到的串口命令处理 */
                if (comGetChar(COM1, &read))
                {
                        switch (ucStatus)
                        



程序进行到这   if (comGetChar(COM1, &read)),总判断为假跳过这段程序。接收不到数据,不知道哪里配置错了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2020-2-25 10:36:29 | 显示全部楼层
EastWind 发表于 2020-2-25 10:16
请教一个问题:我也是参考这个例子, /* 接收到的串口命令处理 */
                if (comGetChar(COM1,  ...

中断里面打个断点,先看看接收到数据了没
回复

使用道具 举报

2

主题

87

回帖

93

积分

初级会员

积分
93
发表于 2020-2-25 11:00:32 | 显示全部楼层
中断能进,发送没问,用AC6编译的不影响吧。
static void UartIRQ(UART_T *_pUart)
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2020-2-25 11:04:45 | 显示全部楼层
EastWind 发表于 2020-2-25 11:00
中断能进,发送没问,用AC6编译的不影响吧。
static void UartIRQ(UART_T *_pUart)

AC6没事,别的没什么要注意的了。

能进中断,数据也没错的话,那就没问题。

其它问题你再找找。
回复

使用道具 举报

2

主题

87

回帖

93

积分

初级会员

积分
93
发表于 2020-2-25 15:24:38 | 显示全部楼层
谢谢 硬汉。
找到毛病了,我把
uint8_t read;
        uint8_t ucStatus = 0;  /* 状态机标志 */
        uint8_t ucCount=0, i;
        uint8_t buf[128];
这几个变量定义到while循环中了。造成每回读read时,都初始化一会。
以后要注意这个简单的问题。也给大家提个醒。
回复

使用道具 举报

32

主题

295

回帖

391

积分

高级会员

积分
391
发表于 2020-2-28 16:06:36 | 显示全部楼层
非常感谢分享,这个结构确实很好用,比如之前做的项目TTL接一个2.4G射频接收发模块做为主机;下面会有1000个2.4G射频模块作为从机,都会不定时的往上发送数据(温度、湿度、天然气信息); 串口接收到数据之后放入串口FIFO;每次接收到数据会使用回调函数开启一个软件定时器,软件定时超时时间是5~10ms,软件定时器超时时间到之后,会释放一个信号量,告诉线程现在有数据了,需要去处理;
不知道大家还有没有其它方式,能够更好、更合理的处理接收数据;
回复

使用道具 举报

2

主题

12

回帖

18

积分

新手上路

积分
18
发表于 2020-8-27 14:33:03 | 显示全部楼层
硬汉哥你好!看了你这个串口fifo   有一个实际需求是 当作为主机的时候  也就是发送 等待从机回 这种利用你这个怎么实现了?一直没想到好的方法。因为涉及超时,重发等等
回复

使用道具 举报

2

主题

12

回帖

18

积分

新手上路

积分
18
发表于 2020-8-27 15:39:33 | 显示全部楼层
weiyuliang 发表于 2020-2-28 16:06
非常感谢分享,这个结构确实很好用,比如之前做的项目TTL接一个2.4G射频接收发模块做为主机;下面会有1000 ...

假如   有一个实际需求是 当作为主机的时候  也就是发送 等待从机回 这种利用你这个怎么实现了?一直没想到好的方法。因为涉及超时,重发等等  这个怎么实现?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2020-8-27 16:57:46 | 显示全部楼层
jaywen 发表于 2020-8-27 14:33
硬汉哥你好!看了你这个串口fifo   有一个实际需求是 当作为主机的时候  也就是发送 等待从机回 这种利用你 ...

论坛置顶帖下载V6标准库里面的GPS,ESP8266之类的串口例子看下,就更熟练了。
回复

使用道具 举报

2

主题

12

回帖

18

积分

新手上路

积分
18
发表于 2020-8-27 18:48:45 | 显示全部楼层
eric2013 发表于 2020-8-27 16:57
论坛置顶帖下载V6标准库里面的GPS,ESP8266之类的串口例子看下,就更熟练了。

我看了哈 !不是很适合我。因为你那个是阻塞的 while 一直在那等待  这样感觉fifo的意义不大了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2020-8-27 20:08:04 | 显示全部楼层
jaywen 发表于 2020-8-27 18:48
我看了哈 !不是很适合我。因为你那个是阻塞的 while 一直在那等待  这样感觉fifo的意义不大了

这个不是简单的while死循环

RTOS下:
这种方式简单易移植,单独安排在一个任务里面即可。对其它任务毫不影响。

裸机下:
这种方式也是简单易移植,仅需一个.C和一个h文件,用户就可以使用,无需状态机之类的应用层移植。
更关键的点在每个while里面有个bsp_Idle函数,这个函数可以实现触摸检测,网络协议轮询等操作。从而也不会影响其它需要周期执行的功能,裸机的性能全部发挥了出来。
回复

使用道具 举报

34

主题

111

回帖

213

积分

高级会员

程序小白

积分
213
QQ
发表于 2020-11-18 15:48:00 | 显示全部楼层
有个疑问如何实现串口接收一组数据, 比如认为 接收到 ‘\N’ 字符,是一个完整的一组数据, 以便对一组数据解析。    直接通过 comgetchar 加 while() 循环实现?
回复

使用道具 举报

34

主题

111

回帖

213

积分

高级会员

程序小白

积分
213
QQ
发表于 2020-11-18 22:30:24 | 显示全部楼层
因为单片机要实现 scpi协议。。才有上面的要求。。。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2020-11-19 09:14:50 | 显示全部楼层
清风徐来 发表于 2020-11-18 15:48
有个疑问如何实现串口接收一组数据, 比如认为 接收到 ‘\N’ 字符,是一个完整的一组数据, 以便对一组数 ...

可以的,看GPS的例子。
回复

使用道具 举报

34

主题

111

回帖

213

积分

高级会员

程序小白

积分
213
QQ
发表于 2020-11-19 16:28:38 | 显示全部楼层
eric2013 发表于 2020-11-19 09:14
可以的,看GPS的例子。

看了,受益良多。 如果没有结束符 或者 有结束符 ((如结尾有0x0D 0x0A)) 这两种情况,处理方法类似,都有状态机的思想。  需要的数据先放入数组中,方便后面处理
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2020-11-20 09:42:02 | 显示全部楼层
清风徐来 发表于 2020-11-19 16:28
看了,受益良多。 如果没有结束符 或者 有结束符 ((如结尾有0x0D 0x0A)) 这两种情况,处理方法类似,都有 ...

对,这个试试,FIFO机制就显现出他的优势了。
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2021-5-25 23:41:31 | 显示全部楼层
mark  好东西啊!!!!!!!!!!
回复

使用道具 举报

2

主题

28

回帖

34

积分

新手上路

积分
34
发表于 2022-8-23 23:23:54 | 显示全部楼层
我用这种方式,发现上位机如果每次发送1K数据包,串口这边会丢包,是不是因为在while大循环中太过频率调用comGetChar导致串口接收中断时不时被关闭,如果关闭时候刚好有数据进来这个时候不能触发中断,下次再有数据进来就直接覆盖上一次收到的rdr寄存器数据?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2022-8-24 01:52:53 | 显示全部楼层
阴世幽泉 发表于 2022-8-23 23:23
我用这种方式,发现上位机如果每次发送1K数据包,串口这边会丢包,是不是因为在while大循环中太过频率调用c ...

是不是bsp_uart_fifo.h的缓冲开小了,没有及时读取的话,数据被会被后面的新数据覆盖了。

这个ymodem的例子就是上位机发送1024字节的。

BSP视频教程第22期:基于串口的XYZmodem文件传输协议实现,含上位机和下位机全开源,制作了一个Ymodem方式固件更新(2022-08-08)
https://www.armbbs.cn/forum.php? ... 4625&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

2

主题

28

回帖

34

积分

新手上路

积分
34
发表于 2022-8-27 12:00:37 | 显示全部楼层
eric2013 发表于 2022-8-24 01:52
是不是bsp_uart_fifo.h的缓冲开小了,没有及时读取的话,数据被会被后面的新数据覆盖了。

这个ymodem ...

感谢硬汉大神分享,应该是我这边程序没处理好
回复

使用道具 举报

5

主题

24

回帖

39

积分

新手上路

积分
39
发表于 2022-10-26 11:58:42 | 显示全部楼层
EastWind 发表于 2020-2-25 15:24
谢谢 硬汉。
找到毛病了,我把
uint8_t read;

我好像也是这个毛病
回复

使用道具 举报

5

主题

24

回帖

39

积分

新手上路

积分
39
发表于 2022-10-26 12:45:45 | 显示全部楼层
额,测试了之后还是发现这种方式comGetChar只会返回0,就是进不了if
回复

使用道具 举报

5

主题

24

回帖

39

积分

新手上路

积分
39
发表于 2022-10-26 15:09:52 | 显示全部楼层
winddevil 发表于 2022-10-26 12:45
额,测试了之后还是发现这种方式comGetChar只会返回0,就是进不了if

已经查证能进中断能存到BUFFER,只是把寄存器换成了F0系列的TDR\RDR双寄存器替代DR寄存器,数据的定义定义成全局的static了,但是返回值仍然是0,我再打几个断点查证一下
回复

使用道具 举报

5

主题

24

回帖

39

积分

新手上路

积分
39
发表于 2022-10-26 15:50:47 | 显示全部楼层
winddevil 发表于 2022-10-26 15:09
已经查证能进中断能存到BUFFER,只是把寄存器换成了F0系列的TDR\RDR双寄存器替代DR寄存器,数据的定义定 ...

查证是进入了ORE中断了,具体的晚上发帖分享一下,找到了问题,但是不一定解决问题
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2022-10-27 01:00:12 | 显示全部楼层
winddevil 发表于 2022-10-26 15:50
查证是进入了ORE中断了,具体的晚上发帖分享一下,找到了问题,但是不一定解决问题

STM32确实容易出这个ORE问题,中断里面加上对应的标志判断靠谱些。
回复

使用道具 举报

2

主题

12

回帖

18

积分

新手上路

积分
18
发表于 2022-11-15 09:51:48 | 显示全部楼层
eric2013 发表于 2020-8-27 20:08
这个不是简单的while死循环

RTOS下:

RTOS下放在任务里,那就是osDelay(1)这种方式去查询是吧。还可以改良一下,在中断里释放信号量,任务里等待接收信号量
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2022-11-15 10:00:48 | 显示全部楼层
yc5682668 发表于 2022-11-15 09:51
RTOS下放在任务里,那就是osDelay(1)这种方式去查询是吧。还可以改良一下,在中断里释放信号量,任务里等 ...

不改量更好。

加这个你还得处理不定长接收问题,如果任务不能及时处理还会有丢失本次消息通知问题,如果1次1个字节,频繁率超级高等等一些列问题。

使用这个,由于它是串口FIFO,没有及时处理时,还在FIFO里面。容错率要高很多。而且查询CPU率不到千分之一。

回复

使用道具 举报

2

主题

12

回帖

18

积分

新手上路

积分
18
发表于 2022-11-15 11:21:26 | 显示全部楼层
eric2013 发表于 2022-11-15 10:00
不改量更好。

加这个你还得处理不定长接收问题,如果任务不能及时处理还会有丢失本次消息通知问题,如 ...

osDelay(1)这样查询对于数据量较大时解析起来会不会闲的比较慢?如果数据量较大时,一般是怎样的处理思路?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2022-11-16 14:36:33 | 显示全部楼层
yc5682668 发表于 2022-11-15 11:21
osDelay(1)这样查询对于数据量较大时解析起来会不会闲的比较慢?如果数据量较大时,一般是怎样的处理思路 ...

数据量大也处理的过来。
回复

使用道具 举报

4

主题

8

回帖

20

积分

新手上路

积分
20
发表于 2023-5-5 18:40:41 | 显示全部楼层
如果本次收到是数据不足15个  ,下次再发过来的数据就对应不上了,因为 不足15个数据 ,ucCount没有清零,下下次再发15个数据有可能又正确接收
回复

使用道具 举报

4

主题

8

回帖

20

积分

新手上路

积分
20
发表于 2023-5-5 18:47:27 | 显示全部楼层
如果接收的数据不足15个,ucCount不能清零  ,下次收到的数据就对应不上,下下次再发15个数据可能就的正确的
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2023-5-6 09:40:50 | 显示全部楼层
yidaoke 发表于 2023-5-5 18:40
如果本次收到是数据不足15个  ,下次再发过来的数据就对应不上了,因为 不足15个数据 ,ucCount没有清零, ...

楼主位只是个简单分享,实际应用,自己定制好协议,做好容错。
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
发表于 2023-9-8 15:33:45 | 显示全部楼层
请教一个问题,是否设计一个函数,直接把RxBuffer的数据直接copy到一个数组中,直接输出
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-26 06:02 , Processed in 0.309210 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表