胸前骨头疼是什么原因| 小黄鱼是什么鱼| 尿酸高会出现什么症状| 肛瘘是什么情况| 小鸟什么| 荔枝什么时候过季| 公招是什么意思| 罗红霉素胶囊治什么病| penguin是什么意思| 妈妈的弟弟的老婆叫什么| blush是什么颜色| 肚脐眼臭是什么原因| 金银花有什么功效| names是什么意思| 驾校体检都检查什么| 血糖低吃什么| 胃反酸什么原因| 包粽子的叶子叫什么| 肩周炎吃什么药好| 查血管堵塞做什么检查| amp是什么意思| noxa20是什么药| 孩子高低肩有什么好办法纠正| 为什么会有地震| 智齿是什么意思| 吃什么补充酪氨酸酶| 吃生葵花籽有什么好处和坏处吗| 鹅口疮用什么药效果好| 什么是朱砂| balea是什么牌子| 孕妇建档需要什么资料| 老是打嗝是什么病的征兆| 网黄什么意思| 嘴唇上长水泡是什么原因| fc什么意思| 女性内分泌失调有什么症状| mt什么意思| 纷扰是什么意思| 正常龟头什么样子| 运筹帷幄是什么意思| 没有宇宙之前是什么| 比利时用什么货币| 母亲节送什么颜色的康乃馨| 免去职务是什么意思| 女生肾虚是什么原因| 萎缩性鼻炎用什么药| 警察两杠三星是什么级别| 风寒是什么意思| 可可粉是什么| 怀不上孕做什么检查| 激凸是什么意思| 肝气郁结喝什么茶| 什么食物嘌呤高| 什么是芥菜| 封神是什么意思| 万字第二笔是什么| 挫伤是什么意思| 做梦梦到已故的亲人是什么意思| 喝什么去湿气| 心寒是什么意思| 生动形象是什么意思| 甲鱼和什么一起炖最好| 副高相当于什么级别| shark是什么意思| 白斩鸡是什么意思| 什么蛋不能吃| 14年属什么| 有什么神话故事| 得了幽门螺杆菌是什么症状| 狗狗拉血是什么原因| 室内传导阻滞什么意思| 鸟加一笔是什么字| 血红蛋白浓度偏低是什么原因| 夏天用什么泡脚最好| 头发粗硬是什么原因| 炖牛肉放什么调料最好| 五大仙家什么仙最厉害| 血压低吃什么中成药| 马来酸曲美布汀片什么时候吃| 死去活来是什么生肖| st是什么单位| 什么人不能喝蜂蜜| 喉咙痛吃什么药好| 89年的属什么| 忌口不能吃什么| 失去理智什么意思| 早上头晕是什么原因| 与什么俱什么| 男朋友生日送什么礼物| 美国为什么打伊拉克| 世界上最大的单位是什么| 菟丝子有什么功效| 一阵什么| 百雀羚属于什么档次| 卧底大结局是什么| 吃百合有什么好处| 酮体是什么| 骨质破坏是什么意思| 什么的腊梅| 小case是什么意思| 胃大肚子大是什么原因| 嘴巴苦是什么原因引起的| 经常呛咳是什么病的征兆| 师傅和师父有什么区别| 狮子是什么科| 乌龟不能吃什么| 叶酸什么时候吃| 0n是什么意思| 宫颈多发潴留囊肿是什么意思| 狗狗睡姿代表什么图解| 室上性早搏是什么意思| 92年是什么命| 蛞蝓是什么| 地龙是什么| 印度人为什么叫阿三| 检查血液挂什么科| 急性尿路感染吃什么药| 吃头孢不能吃什么| 倪妮和倪萍什么关系| 白狗子是什么意思| 炼奶是什么| 印度为什么叫三哥| 田童念什么| 什么是疣体| 花中隐士是什么花| 绿洲是什么意思| 猫三联什么时候打| 反应性增生是什么意思| 一个口一个者念什么| 梦见袜子破了是什么意思| 朱元璋为什么杀徐达| 吃什么补充蛋白| 怀孕抽烟对孩子有什么影响| 在家做什么小生意| 小m是什么意思| 什么的夜晚| 生气吃什么药可以顺气| 吃什么助消化| 燃烧脂肪是什么感觉| 每个月14号都是什么情人节| 膝关节疼痛挂什么科| 螳螂吃什么东西| 台湾为什么叫4v| 胖头鱼是什么鱼| 儿童调理脾胃用什么药最好| 夏枯草是什么样子| 血压正常心跳快是什么原因| 张国立老婆叫什么名字| grader是什么意思| 梦到女儿丢了什么预兆| 治疗股癣用什么药膏| 什么呀| 甲醛中毒吃什么药| 眼神迷离什么意思| 二尖瓣反流是什么意思| 什么泡水喝杀幽门螺杆菌| 关节痛吃什么药| 肾积水有什么危害| 高就是什么意思| 什么鱼蛋白质含量高| 良善是什么意思| 过敏性紫癜是什么病| 10月27日什么星座| 婕字五行属什么| 75c是什么罩杯| 酸性体质是什么意思| 什么是梦| 吃什么死的比较舒服| 缺锌容易得什么病| 50pcs是什么意思| 宝宝流鼻涕吃什么药| 女生吃什么可以丰胸| 山本耀司的品牌叫什么| 夏天受凉感冒吃什么药| 绣球花什么时候修剪| rag什么意思| 巧克力是什么材料做的| 属鸡的跟什么属相最配| 中药什么时间喝效果最好| 吃什么东西对心脏好| 均码是什么码| 肠道感染吃什么消炎药| 白细胞数目偏高是什么意思| 边缘视力是什么意思| 黄芪长什么样子| 派石项链有什么功效| 胃息肉是什么原因引起的| 贲门不舒服有什么症状| 10年什么婚| 女人右手中指有痣代表什么| 种植什么最赚钱农村| 鱼油吃多了有什么副作用| 什么是羊蝎子| 孕期小腿抽筋什么原因| 尿的颜色有点红褐色是什么原因| 来姨妈下面疼是为什么| 灰色配什么色好看| 四月27日是什么星座| pep是什么意思| 1983年五行属什么| 为什么香蕉不能放冰箱| 什么时候可以查高考成绩| 86年属什么生肖| 宇字属于五行属什么| 人中有痣代表什么| 海参吃了有什么好处| 刮目相看是什么意思| 免冠是什么意思| 什么动物不长胡须| 田宅宫代表什么| 梦见老鼠是什么征兆| 伏特加是用什么酿造的| 甘少一横读什么| 月经提前十天是什么原因| 什么馅饺子好吃| 执行标准是什么意思| 户籍地址是什么| 什么地发现| 北京的区长是什么级别| 屈光度是什么意思| 张牙舞爪的张是什么意思| 头臂长是什么意思| 头皮问题挂什么科| 梅毒是什么病| 女人左眼皮跳是什么预兆| 嘴角烂了是什么原因| 并是什么意思| 鼻塞用什么药好| 珩字五行属什么| 桃树什么时候修剪最好| 刻章需要什么材料| 狼入虎口是什么意思| 清明吃什么| 大专什么专业好就业| 为什么会胎停| 客片什么意思| 生灵涂炭是什么意思| 出离心是什么意思| 尿hcg阳性是什么意思| 羽字五行属什么的| 女人银屑病一般都长什么地方| 质子是什么意思| 梦见骆驼是什么意思| 小孩走路迟是什么原因| 乘务长是干什么的| 调侃什么意思| 蟹黄是螃蟹的什么东西| 妇科检查清洁度3度什么意思| 改嫁是什么意思| 辰字五行属什么| 月经来的少是什么原因| 百香果是什么季节的| 环移位了有什么症状| 手淫导致的阳痿早泄吃什么药| 知了为什么一直叫| 补中益气丸适合什么人吃| 霉菌性阴道炎什么症状| 竹者念什么| 市盈率是什么意思| 1.12是什么星座| 痣长在什么地方不好| 香港电话前面加什么| 直接胆红素偏高是什么意思| 男人吃什么可以补精| 百度
这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 ? 论坛首页 ? 嵌入式开发 ? STM32 ? [经验]STM32串口发送数据和接收数据方式总结2

共7条 1/1 1 跳转至

[经验]STM32串口发送数据和接收数据方式总结2

工程师
2025-08-04 19:53:00     打赏
百度 民警调取村委会现场视频,调查在场证人进行取证通过多种方式清楚地还原了事实经过。

2、 直接使用printf函数。很多朋友都知道想要STM32要直接使用printf不行的。需要加上以下的重映射函数:

如果不想添加以上代码,也可以勾选以下的Use microLI选项来支持printf函数使用:

相关笔记:
串口接收数据串口接收最后应有一定的协议,如发送一帧数据应该有头标志或尾标志,也可两个标志都有。
这样在处理数据时既能能保证数据的正确接收,也有利于接收完后我们处理数据。串口的配置在这里就不在赘述,这里我以串口2接收中断服务程序函数且接收的数据包含头尾标识为例。




  1. #define Max_BUFF_Len 18 unsigned char Uart2_Buffer[Max_BUFF_Len]; unsigned int Uart2_Rx=0; void USART2_IRQHandler()  {

  2. if(USART_GetiTStatus(USART2,USART_IT_RXNE) != RESET) //中断产生   {

  3.   USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志     

  4.   Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2);     //接收串口1数据到buff缓冲区   Uart2_Rx++; 

  5.         

  6.   if(Uart2_Buffer[Uart2_Rx-1] == 0x0a || Uart2_Rx == Max_BUFF_Len)    //如果接收到尾标识是换行符(或者等于最大接受数就清空重新接收)   {

  7.    if(Uart2_Buffer[0] == '+')                      //检测到头标识是我们需要的     {

  8.     printf("%s\r\n",Uart2_Buffer);        //这里我做打印数据处理     Uart2_Rx=0;                                   

  9.    } 

  10.    else    {

  11.     Uart2_Rx=0;                                   //不是我们需要的数据或者达到最大接收数则开始重新接收    }

  12.   }

  13. }

  14. }


复制代码


数据的头标识为“\n”既换行符,尾标识为“+”。该函数将串口接收的数据存放在USART_Buffer数组中,然后先判断当前字符是不是尾标识,如果是说明接收完毕,然后再来判断头标识是不是“+”号,如果还是那么就是我们想要的数据,接下来就可以进行相应数据的处理了。但如果不是那么就让Usart2_Rx=0重新接收数据。
这样做的有以下好处:

  • 可以接受不定长度的数据,最大接收长度可以通过Max_BUFF_Len来更改

  • 可以接受指定的数据

  • 防止接收的数据使数组越界

这里我的把接受正确数据直接打印出来,也可以通过设置标识位,然后在主函数里面轮询再操作。
以上的接收形式,是中断一次就接收一个字符,这在UCOS等实时内核系统中频繁的中断,非常消耗CPU资源,在有些时候我们需要接收大量数据时且波特率很高的情况下,长时间中断会带来一些额外的问题。
所以以DMA形式配合串口的IDLE(空闲中断)来接受数据将会大大的提高CPU的利用率,减少系统资源的消耗。首先还是先看代码。




  1. #define DMA_USART1_RECEIVE_LEN 18 void USART1_IRQHandler(void)                                  {     

  2.     u32 temp = 0;  

  3.     uint16_t i = 0;  

  4.       

  5.     if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  

  6.     {  

  7.         USART1->SR;  

  8.         USART1->DR; //这里我们通过先读SR(状态寄存器)和DR(数据寄存器)来清USART_IT_IDLE标志             DMA_Cmd(DMA1_Channel5,DISABLE);  

  9.         temp = DMA_USART1_RECEIVE_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); //接收的字符串长度=设置的接收长度-剩余DMA缓存大小          for (i = 0;i < temp;i++)  

  10.         {  

  11.             Uart2_Buffer[i] = USART1_RECEIVE_DMABuffer[i];  

  12.                 

  13.         }  

  14.         //设置传输数据长度           DMA_SetCurrDataCounter(DMA1_Channel5,DMA_USART1_RECEIVE_LEN);  

  15.         //打开DMA           DMA_Cmd(DMA1_Channel5,ENABLE);  

  16.     }        

  17. }


复制代码


之前的串口中断是一个一个字符的接收,现在改为串口空闲中断,就是一帧数据过来才中断进入一次。而且接收的数据时候是DMA来搬运到我们指定的缓冲区(也就是程序中的USART1_RECEIVE_DMABuffer数组),是不占用CPU时间资源的。
关于IDLE中断可查看:
最后在讲下DMA的发送:




  1. #define DMA_USART1_SEND_LEN 64 void DMA_SEND_EN(void) {

  2. DMA_Cmd(DMA1_Channel4, DISABLE);      

  3. DMA_SetCurrDataCounter(DMA1_Channel4,DMA_USART1_SEND_LEN);   

  4. DMA_Cmd(DMA1_Channel4, ENABLE);

  5. }


复制代码


这里需要注意下DMA_Cmd(DMA1_Channel4,DISABLE)函数需要在设置传输大小之前调用一下,否则不会重新启动DMA发送。
有了以上的接收方式,对一般的串口数据处理是没有问题的了。下面再讲一下,在ucosiii中我使用信号量+消息队列+储存管理的形式来处理我们的串口数据。先来说一下这种方式对比其他方式的一些优缺点。
一般对串口的处理形式是"生产者"和"消费者"的模式,即本次接收的数据要马上处理,否则当数据大量涌进的时候,就来不及"消费"掉生产者(串口接收中断)的数据,那么就会丢失本次的数据处理。所以使用队列就能够很方便的解决这个问题。
在下面的程序中,对数据的处理是先接受,在处理,如果在处理的过程中,有串口中断接受数据,那么就把它依次放在队列中,队列的特征是先进先出,在串口中就是先处理先接受的数据,所以根据生产和消费的速度,定义不同大小的消息队列缓冲区就可以了。缺点就是太占用系统资源,一般51单片机是没可能了。下面是从我做的项目中截取过来的程序:




  1. OS_MSG_SIZE  Usart1_Rx_cnt;          //字节大小计数值 unsigned char Usart1_data;           //每次中断接收的数据 unsigned char* Usart1_Rx_Ptr;        //储存管理分配内存的首地址的指针 unsigned char* Usart1_Rx_Ptr1;       //储存首地址的指针 void USART1_IRQHandler()  {

  2. OS_ERR err;

  3. OSIntEnter();


  4.   if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET) //中断产生    {   

  5.     USART_CleaRFlag(USART1, USART_FLAG_RXNE);     //清除中断标志   

  6.     Usart1_data = USART_ReceiveData(USART1);     //接收串口1数据到buff缓冲区   

  7.   if(Usart1_data =='+')                     //接收到数据头标识   { //   OSSemPend((OS_SEM*  )&SEM_IAR_UART,  //这里请求信号量是为了保证分配的存储区,但一般来说不允许 //   (OS_TICK  )0,                   //在终端服务函数中调用信号量请求但因为 //   (OS_OPT   )OS_OPT_PEND_NON_BLOCKING,//我OPT参数设置为非阻塞,所以可以这么写 //   (CPU_TS*  )0, //   (OS_ERR*  )&err);  //   if(err==OS_ERR_PEND_WOULD_BLOCK)     //检测到当前信号量不可用 //   { //     printf("error"); //   }        Usart1_Rx_Ptr=(unsigned char*) OSMemGet((OS_MEM*)&UART1_MemPool,&err);//分配存储区    Usart1_Rx_Ptr1=Usart1_Rx_Ptr;          //储存存储区的首地址   }

  8.   if(Usart1_data == 0x0a )       //接收到尾标志   {                    

  9.    *Usart1_Rx_Ptr++=Usart1_data;

  10.    Usart1_Rx_cnt++;                         //字节大小增加    OSTaskQPost((OS_TCB    *  )&Task1_TaskTCB,

  11.                                    (void      *  )Usart1_Rx_Ptr1,    //发送存储区首地址到消息队列                                    (OS_MSG_SIZE  )Usart1_Rx_cnt,

  12.                                    (OS_OPT       )OS_OPT_POST_FIFO,  //先进先出,也可设置为后进先出,再有地方很有用                                    (OS_ERR    *  )&err);

  13.          

  14.    Usart1_Rx_Ptr=NULL;          //将指针指向为空,防止修改    Usart1_Rx_cnt=0;      //字节大小计数清零   }

  15.   else   {

  16.    *Usart1_Rx_Ptr=Usart1_data; //储存接收到的数据    Usart1_Rx_Ptr++;

  17.    Usart1_Rx_cnt++;

  18.   } 

  19. }    

  20. OSIntExit();

  21. }


复制代码



上面被注释掉的代码为我是为了防止当分区中没有空闲的存储块时加入信号量,打印出报警信息。当然我们也可以将存储块直接设置大一点,但是还是无法避免当没有可有存储块时会程序会崩溃现象。希望懂的朋友能告知下~。
下面是串口数据处理任务,这里删去了其他代码,只把他打印出来了而已。




  1. void task1_task(void *p_arg) {

  2. OS_ERR err;

  3. OS_MSG_SIZE Usart1_Data_size;

  4. u8 *p;


  5. while(1)

  6. {

  7.   p=(u8*)OSTaskQPend((OS_TICK  )0, //请求消息队列,获得储存区首地址    (OS_OPT    )OS_OPT_PEND_BLOCKING,

  8.    (OS_MSG_SIZE* )&Usart1_Data_size,

  9.    (CPU_TS*   )0,

  10.    (OS_ERR*   )&err);


  11.   printf("%s\r\n",p);        //打印数据  

  12.   delay_ms(100);

  13.   OSMemPut((OS_MEM* )&UART1_MemPool,    //释放储存区   (void*   )p,

  14.   (OS_ERR*  )&err);

  15.        

  16.   OSSemPost((OS_SEM* )&SEM_IAR_UART,    //释放信号量   (OS_OPT  )OS_OPT_POST_NO_SCHED,

  17.   (OS_ERR* )&err);

  18.        

  19.   OSTimeDlyHMSM(0,0,1,500,OS_OPT_TIME_PERIODIC,&err);     

  20. }

  21. }


复制代码





关键词: STM32     串口     发送     数据     接收     数据     方式         

专家
2025-08-04 20:10:45     打赏
2楼

学习


工程师
2025-08-04 21:07:02     打赏
3楼

挺实用的技巧!


工程师
2025-08-04 21:35:31     打赏
4楼

MicroLIB  确实要打钩才行


工程师
2025-08-04 21:46:14     打赏
5楼

重新定义fput才是关键~


工程师
2025-08-04 23:37:13     打赏
6楼

总结的相当不错


工程师
2025-08-04 23:34:55     打赏
7楼

总结的不错


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
胎停了有什么明显症状 今年流行什么颜色头发 生肖蛇五行属什么 什么是金砖国家 发膜什么牌子效果最好
经期吃什么缓解痛经 蛇的尾巴有什么作用 鹦鹉叫什么名字好听 什么药治牙疼最快 严重脱发是什么原因
94岁属什么 便秘吃什么中药 gg什么意思 谨字五行属什么 忙碌的动物是什么生肖
后背不舒服是什么原因 鱼腥草泡水喝有什么功效 朋友是什么意思 足底筋膜炎什么症状 乳房旁边疼是什么原因
喝完酒吃什么解酒最快hcv9jop5ns7r.cn 顺产收腹带什么时候用最佳hcv7jop5ns5r.cn 卫生间除臭用什么最好hcv9jop5ns5r.cn 身份证什么时候开始有的zhongyiyatai.com b2b是什么意思hcv8jop1ns7r.cn
手脚脱皮是什么原因导致的hlguo.com 水杯用什么材质的好xinmaowt.com 得失是什么意思imcecn.com 72年属什么hcv9jop6ns1r.cn 打hcg针有什么作用hcv7jop6ns1r.cn
荨麻疹吃什么药hcv7jop6ns3r.cn 血去掉一撇念什么adwl56.com ldpe是什么材料hcv8jop2ns4r.cn 浅蓝色裙子配什么颜色上衣好看hcv7jop9ns0r.cn 中国的四大发明是什么hcv9jop0ns3r.cn
松花粉是什么hcv8jop8ns1r.cn 鬼斧神工是什么意思imcecn.com 碎银子是什么茶hcv9jop8ns2r.cn 一蹴而就什么意思hcv8jop4ns4r.cn 布施什么意思hcv8jop6ns9r.cn
百度