细说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)串口中断服务函数:

cpp 复制代码
HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

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

cpp 复制代码
HAL_UART_R×CpltCallback(UART_HandleTypeDef *huart)

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

cpp 复制代码
HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size)

(4)非中断发送:

cpp 复制代码
HAL_UART_Transmit(*huart,pData,Size,Timeout)

(5)中断发送:

cpp 复制代码
HAL_UART_Transmit_IT(*huart,pData,Size)

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

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

(1)包含头文件

cpp 复制代码
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

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

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

cpp 复制代码
/* 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

cpp 复制代码
/* 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函数通过串口送出提示输入数据的信息:

cpp 复制代码
/* 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显示一次。

相关推荐
夜间去看海3 小时前
基于单片机的智能浇花系统
单片机·嵌入式硬件·智能浇花
VirtuousLiu3 小时前
LM74912-Q1用作电源开关
单片机·嵌入式硬件·ti·电源设计·lm74912·电源开关
打地基的小白3 小时前
软件I2C-基于江科大源码进行的原理解析和改造升级
stm32·单片机·嵌入式硬件·通信模式·i2c
Echo_cy_4 小时前
STM32 DMA+AD多通道
stm32·单片机·嵌入式硬件
朴人4 小时前
【从零开始实现stm32无刷电机FOC】【实践】【7.2/7 完整代码编写】
stm32·单片机·嵌入式硬件·foc
追梦少年时4 小时前
STM32中断——外部中断
stm32·单片机·嵌入式硬件
bai_lan_ya4 小时前
stm32定时器中断和外部中断
stm32·单片机·嵌入式硬件
玄奕子4 小时前
GPT对话知识库——在STM32的平台下,通过SPI读取和写入Flash的步骤。
stm32·单片机·gpt·嵌入式·嵌入式驱动
夜间去看海5 小时前
基于单片机的温度和烟雾检测
单片机·嵌入式硬件·温度烟雾
星汇极客5 小时前
【星汇极客】单片机竞赛之2024睿抗机器人大赛-火线速递赛道(持续更新)
stm32·单片机·嵌入式硬件·机器人