当前位置: 首页 > news >正文

细说MCU串口函数及使用printf函数实现串口发送数据的方法

目录

1、硬件及工程 

2、串口相关的库函数

(1)串口中断服务函数:

(2)串口接收回调函数:

(3)串口接收中断配置函数:

(4)非中断发送:

(5)中断发送:

3、使用printf函数串口发送数据

(1)包含头文件

(2)修改发送字符函数putchar()

(3)修改3

(4)修改4

4、下载运行


1、硬件及工程 

        文章依赖的硬件及工程配置同本文作者的其他文章:细说ARM MCU的串口接收数据的实现过程-CSDN博客 https://wenchm.blog.csdn.net/article/details/139541112

2、串口相关的库函数

        MCU串口通讯用到的HAL库函数有下面几个:

(1)串口中断服务函数:

HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

(2)串口接收回调函数:

HAL_UART_R×CpltCallback(UART_HandleTypeDef *huart)

(3)串口接收中断配置函数:

HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size)

(4)非中断发送:

HAL_UART_Transmit(*huart,pData,Size,Timeout)

(5)中断发送:

HAL_UART_Transmit_IT(*huart,pData,Size)

3、使用printf函数串口发送数据

        在MCU中,可以利用printf函数将信息送到MCU的外设上。比较常用的场合就是通过串口发送数据。

(1)包含头文件

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

(2)修改发送字符函数putchar()

        由于STM32CubeIDE使用的是GNU C/C++编译器,所以printf使用的底层函数是putchar函数,具体来说就是__io_putchar(int ch)。

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{CommFlag = 1;HAL_UART_Receive_IT(&huart2,(uint8_t *)RxBuffer,RXBUFFERSIZE);
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{HAL_GPIO_WritePin(BUZ_GPIO_Port,BUZ_Pin,GPIO_PIN_RESET);HAL_Delay(100);	//延时HAL_GPIO_WritePin(BUZ_GPIO_Port,BUZ_Pin,GPIO_PIN_SET);for(uint8_t i = 0; i < RXBUFFERSIZE; i++){printf(" RxBuffer[%d] = 0x%02x\r\n",i,RxBuffer[i]);}
}int __io_putchar(int ch)		//putchar实现
{HAL_UART_Transmit(&huart2,(uint8_t*)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */

        需要把上面的实现代码放到注释对中。可以放到注释对/*USER CODEBEGIN 4*/和/*USER CODE END 4 */之间。与前面介绍的两个回调函数HAL_UART_RxCpltCallback()和HAL_GPIO_ EXTI_Callback()放到一起。

        在上面putchar函数的定义中,串口发送函数使用的是库函数HAL_UART_Transmit(),每次发送1字节的数据。

        完成上面的工作后,就可以使用printf函数通过串口发送数据了。

(3)修改3

/* USER CODE BEGIN PV */
uint8_t CommOkMessage[] = "Everything is OK\r\n";
uint8_t CommErrMessage[] = "Received Error Data\r\n";
uint8_t CommFlag =0;
uint8_t RxBuffer[RXBUFFERSIZE] = {0};
/* USER CODE END PV */

(4)修改4

        本文例子实现如下功能:程序执行后,MCU首先通过串口发送提示字符串“Please Enter Data:”;随后,等待接收数据;MCU通过中断接收到3字节数据后,会将它们存储到RxBuffer数组中;最后,利用按键B1来查看送来的数据,即在按下B1键后,通过串口送出RxBuffer数组中接收到的数据。

        要实现上述功能,首先要在while(1)循环前使用printf函数通过串口送出提示输入数据的信息:

/* Infinite loop *//* USER CODE BEGIN WHILE */printf("Please Enter Data:\r\n");while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if ((RxBuffer[0] == 0x53) && (RxBuffer[2] == 0x45) && (CommFlag == 1)){CommFlag = 0;printf("Everything is OK!:\r\n");if(RxBuffer[1] == 0x10){HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);//HAL_UART_Transmit(&huart2,CommOkMessage,19,1000);}else{HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);//HAL_UART_Transmit_IT(&huart2,CommErrMessage,22);}}}/* USER CODE END 3 */

        然后,修改按键中断处理的回调函数HAL_GPIO_EXTI_Callback(),加入串口发送数据的代码。具体实现如上面第(2)步。

4、下载运行

        在printf函数中,%d是按整型数据输出,%x是按十六进制格式输出,%02x中的02表示位宽为2,不够的话前边补0。

        编译、下载、运行程序后,在串口助手的接收区,会看到提示输入数据的字符“Please Enter Data:”。通过串口助手按十六进制格式送出数据53 10 45后,串口助手会接收到字符“Everything is OK”,表示数据已经正确收到。如果想查看具体收到的是什么数据,可以按一下NUCLEO-G474RE板上的B1键,在串口助手上就会显示所接收到的数据。

        准备就绪,会收到消息“Please Enter Data:” 

        连续发送3次数据53 10 45 ,会收到3次数据正确的消息“Everything is OK”

        

        连续发送4次数据53 10 45 ,会收到4次数据正确的消息“Everything is OK” ,并不是程序写错了,而是程序没写判断数据的对错,程序只是判断数据是否准备妥当了。妥当了,就OK。

      

        按下B1键,看看MCU接收到了什么数据并显示到串口助手上,按一下B1显示一次。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 贝尔编程是干什么的:深入探索其核心理念与应用领域
  • Python基础教程(十六):正则表达式
  • 【前端面试】动态表单篇
  • Java课程设计:基于ssm的旅游管理系统系统(内附源码)
  • 征集2024年西咸新区科技计划项目(第一批)申报类别要求和申报时间流程指南
  • 常用数字滤波器类型
  • GDB调试C++程序
  • 如何让 uboot启动时自动执行指令?(执行“mtdparts default”命令)
  • 在css样式中使用em和px。各有什么优势,在表现上有什么区别?
  • 杂项——编码器控制小车走固定距离(stm32)
  • rtl8723du android5.1 6818 (蓝牙 部分)(第四部分)
  • 简单脉冲动画效果实现
  • ssm学生成绩管理系统-海豚
  • ubuntu, esp-idf, arduino
  • Vue路由的使用
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【刷算法】求1+2+3+...+n
  • 5、React组件事件详解
  • JavaScript中的对象个人分享
  • mongo索引构建
  • PHP 的 SAPI 是个什么东西
  • QQ浏览器x5内核的兼容性问题
  • Sass 快速入门教程
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • 闭包,sync使用细节
  • 测试如何在敏捷团队中工作?
  • 给第三方使用接口的 URL 签名实现
  • 关于使用markdown的方法(引自CSDN教程)
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 浏览器缓存机制分析
  • 面试总结JavaScript篇
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​flutter 代码混淆
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • # Redis 入门到精通(九)-- 主从复制(1)
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • ###项目技术发展史
  • #LLM入门|Prompt#3.3_存储_Memory
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (四)汇编语言——简单程序
  • (一) storm的集群安装与配置
  • (一)插入排序
  • (一)模式识别——基于SVM的道路分割实验(附资源)
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据