基于stm32的串口收发讲解(hal库)#打卡不停更#(代码片段)

author author     2022-12-05     803

关键词:

(基于STM32的串口收发程序(HAL库))

介绍

串口(UART通用异步收发器,TTL)通讯是一种设备间的串行全双工通讯方式。由于UART是异步传输,没有传输同步时钟,为了保证数据的正确性,UART采用16倍数据波特率的时钟进行采样。因为它简便捷,因此大部分电子设备都支持该通讯方式工程师在调试设备时也经常使用该方式输出调试信息。 本文详细的介绍如何来编写一个串口收发程序,我们采用常用的收发逻辑,发送直接编写函数进行实现,而接收使用中断进行完成。接收中断使用接收到一个字节和一帧数据两种中断触发方式。

USART中断

USART 有多个中断请求事件。 之所以介绍这个USART中断请求,是因为很多人在初学阶段,对串口怎么判断串口中断的状态不太了解,所以我这里重点来介绍一下。 一般在我们开始和配置完串口中断后,进入串口中断处理程序的情况会有很多,我们也可以自己选择打开哪些串口中断情况。一般情况下,我们在接受时主要使用的中断事件标志是RXNE和IDLE。 RXNE是接收中断,每接收一个字节都会出发这个中断,也是我们用的最频繁的中断请求。 IDLE 是空闲中断,每接收完一帧数据,总线就会暂时空闲,就会触发这个中断。

串口状态

串口的状态可以通过状态寄存器 USART_SR 读取。USART_SR 的各位描述如下: 这里我们关注一下两个位,第 5、6 位 RXNE 和 TC。 RXNE(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以该位清零,也可以向该位写 0,直接清除。 TC(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。果设置了这个位的中断,则会产生中断。该位也有两种清零方式:

  1. 读 USART_SR,USART_DR。
  2. 直接向该位写 0。

实例

需求分析

本项目主要编写一个串口收发的实例。使用STM32F103C8T6充当MCU,在PC上使用串口调试助手充当上位机。每次PC向MCU下发一帧数据, MCU每接收一个字节数据,检查一下数据中是否有指令0x23,当接收到指令0x23的时候,MCU向上位机发送“PC”。当一帧数据接收完毕后,MCU向上位机发送“Receive a frame data”.

串口初始化

串口初始化的一般步骤可以总结为如下几个步骤:

  1. 串口时钟使能,GPIO 时钟使能。
  2. 设置引脚复用器映射:调用 GPIO_PinAFConfig 函数。
  3. GPIO 初始化设置:要设置模式为复用功能。
  4. 串口参数初始化:设置波特率,字长,奇偶校验等参数。
  5. 开启中断并且初始化 NVIC,使能中断(如果需要开启中断才需要这个步骤)。
  6. 使能串口。
#include "usart.h"
#include <stdio.h>
#include "stm32f1xx_hal.h
UART_HandleTypeDef huart3
void MX_USART3_UART_Init(void)

  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  
    Error_Handler()
	__HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);//接收中断使能
	__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);//空闲中断使能 


void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)

  GPIO_InitTypeDef GPIO_InitStruct = 0;
  if(uartHandle->Instance==USART3)
  
    __HAL_RCC_USART3_CLK_ENABLE()
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**USART3 GPIO Configuration
    PB10     ------> USART3_TX
    PB11     ------> USART3_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct)
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART3_IRQn);

我们平时需要改的其实就是串口的一些参数配置。

  • BaudRate:波特率
  • WordLength;:字长
  • StopBits:停止位
  • Parity:奇偶校验
  • Mode:收/发模式设置
  • HwFlowCtl:硬件流设置
  • OverSampling:过采样设置

串口发送

串口发送这里使用的非中断发送方式。

/*******************************************************************************
  * @函数名称	USART_Send
  * @函数说明   发送信息
  * @输入参数   _UART:串口号
			data:要发送的信息的首地址
			len: 发送的长度
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void USART_Send(USART_TypeDef *_UART,uint8_t *data,uint8_t len)

	for(int i;i<len;i++)
	
		HAL_UART_Transmit(&huart3,&data[i],1,1000);
	

主要使用的是HAL_UART_Transmit(&huart3,&Res,1,0Xffff); 这是一个阻塞的发送函数,无需重复判断串口是否发送完成。发送每个字符,直到遇空字符才停止发送。其中第一个参数是串口号,第二个参数是要发送的数据起始地址,第三个是要发送的数据长度,第四个超时时间(超过此长度仍未发送成功则阻塞完毕,停止发送,函数执行完毕)。

串口接收

这里串口接收使用的是中断的方式。 中断的类别在文章的最上边已经介绍过。我们在初始化时设定触发中断的类型。本文中设置的

__HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);//接收中断使能
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);//空闲中断使能 

代表只有接收数据和空闲中断会触发。 在stm32f1xx_it.c中有我们的串口中断处理函数。我们将这个函数进行重构。

void USART3_IRQHandler(void)

	uint8_t Res;
if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET

	HAL_UART_Receive(&huart3,&Res,1,0Xffff); 
 if(Res==0x23)	
	printf("PC");

else if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET)//空闲中断(代表这一帧数据传输完了)

	printf("Receive a frame data.");
	__HAL_UART_CLEAR_IDLEFLAG(&huart3);

这里面的几个重点,我们来一一介绍。 首先是判断标志位,我们使用HAL库中的__HAL_UART_GET_FLAG()函数,里面有两个参数,前者是串口句柄,后者是具体哪个标志位。 if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET)用来检测是否检测到有单个字节的中断。 if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET)用来检测是否有空闲中断(代表这一帧数据传输完了)。

重定向printf和scanf

还有一点需要注意的,使用 fput 和 fgetc 函数达到重定向 C 语言标准库输入输出函数必须在 MDK 的工程选项把“Use MicroLIB”勾选上, MicoroLIB 是缺省 C 库的备选库,它对标准 C 库进行了高度优化使代码更少,占用更少资源 为使用 printf、 scanf 函数需要在文件中包含 stdio.h 头文件。

/**
  * 函数功能: 重定向c库函数printf
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)

  HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xffff);
  return ch;

 
/**
  * 函数功能: 重定向c库函数getchar,scanf
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)

  uint8_t ch = 0;
  HAL_UART_Receive(&huart3, &ch, 1, 0xffff);
  return ch;


效果

  1. PC下发:11 22 33 44
  2. PC下发:12 23 34 45

基于stm32的串口收发讲解(hal库)(代码片段)

基于STM32的串口收发程序(HAL库)介绍USART中断串口状态实例需求分析串口初始化串口发送串口接收重定向printf和scanf效果后续介绍串口(UART通用异步收发器,TTL)通讯是一种设备间的串行全双工通讯方式。由... 查看详情

基于stm32的串口收发讲解(hal库)(代码片段)

基于STM32的串口收发程序(HAL库)介绍USART中断串口状态实例需求分析串口初始化串口发送串口接收重定向printf和scanf效果后续介绍串口(UART通用异步收发器,TTL)通讯是一种设备间的串行全双工通讯方式。由... 查看详情

基于stm32的串口收发讲解(标准库)(代码片段)

基于STM32的串口收发详解介绍USART中断串口状态实例需求分析串口初始化串口发送串口接收重定向printf和scanf效果后续介绍串口(UART通用异步收发器,TTL)通讯是一种设备间的串行全双工通讯方式。由于UART是异步传输&... 查看详情

stm32hal库串口使用笔记(代码片段)

简介:本文通过介绍串口收发工程以及串口相关函数,来让大家了解STM32HAL库串口的基础使用方法。一.串口收发工程讲解1.使用STM32CubeMX新建一个工程2.如下图选择自己现有的STM32开发板进行开发:3.配置时钟源如果选... 查看详情

stm32-hal库串口收发(代码片段)

串口发送重写fputc函数/*优点 直接使用printf函数,发送数据长度无限制,不需要额外的数组空间缺点 只能对应一个串口,暂时没想到解决方案*///头文件中要包含stdio.h然后就可以正常使用printf了intfputc(intch,FILE*F) HAL_UART_Transmit(&... 查看详情

基于stm32的串口收发讲解(标准库)(代码片段)

基于STM32的串口收发详解介绍USART中断串口状态实例需求分析串口初始化串口发送串口接收重定向printf和scanf效果后续介绍串口(UART通用异步收发器,TTL)通讯是一种设备间的串行全双工通讯方式。由于UART是异步传输&... 查看详情

stm32学习笔记二基于stm32f103c8t6和stm32cubemx实现uart串口通信数据收发(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发三、实战小例程基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方四、基于STM32F103C8T6最小系统板... 查看详情

基于stm32f103c8t6最小系统板hal库cubemx驱动hc-sr501红外人体传感模块(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发三、实战小例程基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方四、基于STM32F103C8T6最小系统板... 查看详情

stm32cubemx基于hal库实现简单串口通信(代码片段)

STM32CubeMX基于HAL库实现简单串口通信板子:STM32F103C8编译工具:Keil+STM32CubeMX烧录工具:FlyMcu串口调试程序:XCOM实验要求:1)设置波特率为115200,1位停止位,无校验位;2)STM32系统给上位... 查看详情

stm32学习笔记二基于stm32f103c8t6和stm32cubemx实现uart串口通信数据收发(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发文章目录系列文章目录前言一、配置CubeMX二、HAL库UART相关函数简介2.1串口发送/接收函数2.2串口中断... 查看详情

基于stm32f103c8t6最小系统板hal库cubemx驱动hc-sr501红外人体传感模块(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发三、实战小例程基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方四、基于STM32F103C8T6最小系统板... 查看详情

apm/stm32f072rb基于hal库配置usbcdc虚拟串口功能(代码片段)

APM/STM32F072RB基于HAL库配置USBCDC虚拟串口功能📢采用的自制开发板,开源PCB工程详情放在《极海APM32F072RB开发环境测试》✨本案例基于STM32CubeMX工具配置。📺使用STM32CubeMX工具配置工程改为APMF072RB型号过程如下:⛳... 查看详情

使用stm32cubemx的hal库来建立串口收发,发生了诡异的数据传输错误

...库,后来学长推荐了hal库,非常方便。但是今天试了一下串口的通信,仅仅调用了 这两个函数:HAL_UART_Receive(&huart1,(uint8_t*)data,8,100); HAL_Delay(500); HAL_UART_Transmit(&huart1,(uint8_t*)data,8,100); HAL_Delay(500);最后的输出中第一次输的头两个字... 查看详情

stm32学习笔记二基于stm32f103c8t6和stm32cubemx实现uart串口通信数据收发(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发三、实战小例程基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方四、基于STM32F103C8T6最小系统板... 查看详情

书籍连载《stm32hal库开发实战指南—基于f7》-第一章

从今天起,每天开始连载一章《STM32HAL库开发实战指南—基于F7》。欢迎各位阅读、点评、学习。第1章 如何使用本书1.1 本书的参考资料本书参考资料为:《STM32F76xxx参考手册》和《Cortex?-M7内核编程手册》,这两本是ST官... 查看详情

stm32串口接收中断——基于hal库(代码片段)

写在前面    最近需要使用一款STM32L4系列的芯片进行开发,需要学习使用HAL库。在进行串口中断使用的时候遇到了一些小麻烦,写下解决方案供大家参考。1.UART相关的头文件引用错误   由于本人直接使用MDK进行开发... 查看详情

stm32hal库stm32cubemx教程十五---fmc-sdram(代码片段)

...用本文1首先讲解什么是FMC及SDRAM,W9825G6KH芯片原理,2基于CubeMx创建工程3对HAL库FMC函数进行讲解,4例程详解所用工具:1、芯片:STM32H743II2、STM32CubeMx软件V6.4 查看详情

正点原子stm32(基于hal库)2(代码片段)

目录跑马灯实验(IO输出)STM32F1GPIO简介GPIO八种工作模式GPIO寄存器介绍通用外设驱动步骤GPIO外设配置步骤硬件设计程序设计GPIO的HAL库驱动函数GPIO输出配置步骤程序流程图课堂源码跑马灯程序解析下载验证按键输入点灯实验(IO输入)... 查看详情