前胸后背长痘痘是什么原因| 国防部部长什么级别| 黄瓜片贴脸上有什么效果| 肛塞有什么作用| 壁细胞主要分泌什么| 18k金是什么意思| 林伽是什么| 天麻什么时候种植| 屏蔽一个人意味着什么| 公积金有什么作用| 眼睛模糊吃什么药| 咽喉充血是什么原因| 7.17是什么日子| 距离感是什么意思| 男人为什么好色| 感冒吃什么水果比较好| 洗手指征是什么| 什么茶降血脂最好| 问号像什么| 文殊菩萨保佑什么| 为什么吃鸽子刀口长得快| 脑梗用什么药| 门可罗雀什么意思| 结核t细胞阳性说明什么| experiment什么意思| 禅让制是什么意思| 肌肉痛吃什么药| 孕酮低是什么原因造成的| 气血亏虚什么症状| 什么大腰粗| 梦到捡钱是什么意思| 给产妇送什么礼物好| 胆固醇偏高是什么意思| 老是拉肚子什么原因| 无花果什么味道| 身上长小肉揪是什么原因| 涤纶是什么面料优缺点| 洁身自爱是什么意思| 眼屎多什么原因| 眼睛红肿是什么原因| 螃蟹是什么季节吃的| 老是头疼是什么原因| 掉头发什么原因| 什么动物| 中国四大发明是什么| 六月初五是什么日子| anti是什么意思| 相形见拙什么意思| 咳嗽吃什么菜| 谷丙转氨酶高吃什么药| 拉肚子发烧吃什么药| 黑脚鸡是什么品种| 胰岛素抵抗吃什么药| 割包皮有什么用| 德国什么东西值得买| 晚上血压高是什么原因| 皮肤发黄什么原因| 带状疱疹后遗神经痛用什么药| dave是什么意思| 牛肉馅配什么菜包饺子好吃| 怀孕吃什么好| 什么是胆固醇| ysy是什么意思| 慢性咽喉炎吃什么药| 挂失补办身份证需要什么| 左氧氟沙星治什么病| 类风湿关节炎吃什么药| 人参不能和什么一起吃| 化疗有什么副作用| 什么罗之恋| plt是什么意思| 胆囊息肉是什么意思| 一毛不拔指什么生肖| 未加一笔是什么字| 子宫内膜炎什么症状| 老当益壮是什么意思| 买什么化妆品好| 柠檬和什么不能一起吃| 飞机不能带什么东西| 今年流行什么颜色头发| 日本为什么经常地震| 嘴歪是什么引起的| 最多笔画的汉字是什么| 权志龙为什么叫gd| 构筑物是什么意思| rds医学上什么意思| 愿君多采撷是什么意思| 高血压高血糖挂什么科| 阴道痒是什么原因| 甲状腺手术后可以吃什么水果| 例假为什么第一天最疼| 上眼皮痒是什么原因| 笃行是什么意思| 抗核抗体弱阳性说明什么| c类火灾是指什么| 胆红素高是怎么回事有什么危害| 尿液黄绿色是什么原因| 做梦坐飞机是什么意思| 什么食物可以减肥| 宠物医院需要什么资质| 梦到老房子是什么意思| 急性心肌炎有什么症状| 点头之交是什么意思| 青春期什么时候结束| 518是什么星座| 钢笔ef尖是什么意思| jeans什么意思| 士字五行属什么| 猫吃什么下奶最快最多| 梦见苍蝇很多是什么意思| 生姜吃多了有什么害处| 圣诞节送女生什么礼物好| 九重天是什么意思| 什么是失信被执行人| 什么的杨桃| 牛肉与什么食物相克| 美国总统叫什么名字| 汁字五行属什么| 食管反流用什么药| 五行缺水是什么意思| 什么血型的人最聪明| 颜字五行属什么| 佛法无边是什么意思| 1959年是什么年| 牙膏尾部的颜色代表什么意思| 水对什么| 九天什么月| 宫腔镜是检查什么的| 开学买什么| national是什么牌子| dp是什么意思| 压床娃娃有什么讲究吗| 肠息肉吃什么药| 旅游要带什么| 金的部首是什么| 打开图片用什么软件| 头脑灵活是什么生肖| 霍山黄芽属于什么茶| 脑科属于什么科| 膝关节痛挂什么科| 过敏性鼻炎用什么药效果最好| 右肺上叶肺大泡是什么意思| 孢子粉是什么| 计算机二级什么时候考| 出汗太多吃什么药好| 人血白蛋白适合什么人| 褪黑素是什么| 殁年是什么意思| 双侧乳腺小叶增生是什么意思| 孕妇肾积水是什么原因引起的| 骨折不能吃什么东西| 小鸡啄米什么意思| 长寿花用什么肥料最好| 肾气不足吃什么中成药| 南方是什么生肖| 1月10日什么星座| 查血糖挂什么科| 家门不幸是什么意思| 胸腔积液是什么原因引起的| 南京有什么好玩的地方| 排酸对身体有什么好处| 迷你巴拉巴拉和巴拉巴拉什么关系| 孕吐吃什么药| 喝柠檬水对身体有什么好处| 金是什么结构| 输液葡萄糖有什么作用| 落汤鸡是什么意思| 什么什么的沙滩| 什么三什么四| egm是什么意思| 洗手做羹汤是什么意思| 四月十九是什么星座| 属猪生什么属相宝宝好| 王禹读什么| 湖北有什么好玩的地方| 抑郁症吃什么食物好| 局长是什么级别干部| 移植后需要注意什么| 小孩为什么会细菌感染| 为什么不呢| 脚酸是什么原因| 什么叫腔梗| 子宫内膜什么时候脱落| 肚脐眼上面疼是什么原因| 四个月是什么字| 麟是什么意思| 胸腔积液是什么原因造成的| 怨气是什么意思| 子宫内膜脱落是什么意思| 春指什么生肖| 占位性病变是什么意思| 婚姻宫是什么意思| 子宫内膜薄有什么影响| 坏血病的症状是什么| 国防科技大学毕业是什么军衔| 急性荨麻疹不能吃什么食物| 贫血吃什么食物好| 麝香保心丸治什么病| 长期吃避孕药有什么危害| 为所当为什么意思| 去痘印用什么药膏| 竹勿念什么| 什么情况下月经推迟| jordan是什么牌子| 阴道有异味用什么药| 什么的小朋友填词语| 过敏性鼻炎用什么药最好| 喝什么茶对身体好| 肾看什么科| 尿路感染是什么原因造成的| 女生是t是什么意思| 什么的松树| 梦见滑雪是什么意思| 巨蟹男和什么座最配| 唐宋元明清前面是什么| 社恐的人适合什么工作| 安全期什么时候| 缄默症是什么病| ccu是什么病房| 小腿麻木是什么原因| 什么是前列腺| 梦见数字是什么意思| 生化有什么症状和反应| 亚硝酸盐阴性是什么意思| 阴虚吃什么食物补得快| 什么是bmi| 贫血用什么药补血最快| mk是什么牌子| 紫苏煮水喝有什么功效| 全性向是什么意思| 冬枣什么时候成熟| 白手套是什么意思| 为什么科比叫黑曼巴| 大学没毕业算什么学历| 四肢厥逆是什么意思| 脑萎缩是什么意思| 晚上七点半是什么时辰| 双肾钙化灶是什么意思| 秘书是干什么的| 瘟神是什么意思| 地铁不能带什么东西| v店是什么| 脑震荡吃什么药| 精益求精下一句是什么| 净土是什么意思| 闺蜜是什么样的关系| 乌龟下蛋预示着什么| 馨字取名有什么寓意| 蓝脸的窦尔敦盗御马是什么歌| 肝气郁结西医叫什么病| 月经来有血块是什么原因| 肿瘤介入治疗是什么意思| 病字旁加且念什么| 坐飞机需要什么| 山花对什么| 打鼾是什么原因引起的| 双下肢水肿是什么原因| 左手中指戴戒指什么意思| 乳腺纤维瘤和乳腺结节有什么区别| 人乳头瘤病毒58型阳性是什么意思| 床榻是什么意思| 丰都为什么叫鬼城| 深度睡眠是什么状态| 腋下是什么部位| 百度
这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 ? 论坛首页 ? 嵌入式开发 ? STM32 ? [经验]STM32串口发送数据和接收数据方式总结2

共1条 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     串口     发送     数据     接收     数据     方式         

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
失眠去医院挂什么科 吃什么解酒快 鸟加一笔变成什么字 血管瘤是什么原因引起的 nt 是什么检查
什么是横纹肌溶解 皮蛋吃多了有什么危害 春节在什么时候 虚汗是什么症状 低筋面粉可以做什么
二次元谷子是什么意思 喝生姜水有什么好处 daddy是什么意思 失眠多梦吃什么药效果最好 乙肝五项25阳性是什么意思
四季豆是什么 歆是什么意思 腕管综合症吃什么药 牙龈发炎是什么原因 伏天是什么意思
武汉有什么玩的0297y7.com 尿泡沫多是什么原因hcv9jop0ns3r.cn 南宁有什么特产hcv8jop4ns2r.cn 18k金是什么材质0735v.com 8000年前是什么朝代hcv9jop0ns7r.cn
胎盘低是什么意思hcv9jop4ns6r.cn 子宫小是什么原因引起的zhongyiyatai.com 喝酒眼睛红是什么原因hcv8jop8ns7r.cn 身上有淤青是什么原因jasonfriends.com 吃斋是什么意思hcv9jop3ns7r.cn
环球中心有什么好玩的hcv9jop4ns7r.cn 蚊香对人体有什么危害hcv9jop2ns3r.cn 外阴苔癣是一种什么病hcv9jop5ns5r.cn 收缩压和舒张压是什么hcv9jop5ns5r.cn 12月18号是什么星座hcv9jop8ns2r.cn
做核磁共振需要注意什么naasee.com 办健康证要带什么证件hcv9jop1ns1r.cn 受凉肚子疼吃什么药bysq.com 晚上适合喝什么茶hcv9jop2ns1r.cn 什么啤酒劲最大hcv8jop6ns8r.cn
百度