STM32 串口接收流程-串口接收中断

串口接收

串口接收流程

  1. 编程USARTx_CR1的M位来定义字长。
  2. 编程USARTx_CR2的STOP位来定义停止位位数。
  3. 编程USARTx_BRR寄存器确定波特率。
  4. 使能USARTx_CR1的UE位使能USARTx。
  5. 如果进行多缓冲通信,配置USARTx_CR3的DMA使能(DMAT)。
  6. 使能USARTx_CR1的RE位为1使能接收器。
  7. 如果要使能接收中断(接收到数据后产生中断),使能USARTx_CR1的RXNEIE位为1。

当串口接收到数据时

  1. USARTx_SR(ISR)的RXNE位置1。表明移位寄存器内容已经传输到RDR(DR)寄存器。已经接收到数据并且等待读取。
  2. 如果开启了接收数据中断(USARTx_CR1寄存器的RXNEIE位为1),则会产生中断。(程序上会执行中断服务函数)
  3. 如果开启了其他中断(帧错误等),相应标志位会置1。
  4. 读取USARTx_RDR(DR)寄存器的值,该操作会自动将RXNE位清零,等待下次接收后置位。

串口接收流程(HAL库)

配置过程:

接收配置步骤①~⑥和发送流程一样,调用HAL_UART_Init函数HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);

步骤⑦开启接收中断:HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef*huart, uint8_t *pData, uint16_t Size);

接收数据过程:

步骤①获取状态标志位通过标识符实现:

   __HAL_UART_GET_FLAG            //判断状态标志位__HAL_UART_GET_IT_SOURCE   //判断中断标志位

步骤②~③中断服务函数:

void USARTx_IRQHandler(void) ;//(x=1~3,6)
void UARTx_IRQHandler(void) ;//(x=4,5,7,8)

在启动文件startup_stm32fxxx.s中查找。
步骤④读取接收数据:
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

串口接收中断程序配置过程(HAL库)

  1. 初始化串口相关参数,使能串口:HAL_UART_Init();
  2. 串口相关IO口配置,复用配置:
    在HAL_UART_MspInit中调用HAL_GPIO_Init函数。
  3. 串口接收中断优先级配置和使能:
    HAL_NVIC_EnableIRQ();
    HAL_NVIC_SetPriority();
  4. 使能串口接收中断:HAL_UART_Receive_IT();
  5. 编写中断服务函数:USARTx_IRQHandler

经过上面步骤,我们就可以写完整的串口接收实验。我们就可以在中断服务函数中编写中断处理过程。
HAL库提供了详细的中断处理函数HAL_UART_IRQHandler,我们在中断服务函数中会调用此函数处理中断。

在这里插入图片描述

在void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)函数里可以找到:UART_Receive_IT(huart);然后找到他的定义static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart),里面可以找到HAL_UART_RxCpltCallback(huart);他是一个接收完成处理回调函数,void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart),用户可以自己编写。

在USART_HandleTypeDef中有如下变量:RxXferSize是接收的数量,RxXferCount是剩余的数据个数,pRxBuffPtr指向数据存储位置的地址。比如,一开始要接收10个数据,pRxBuffPtr指向一个起始位置,初始时RxXferSize=10,RxXferCount=10,每接收一次,RxXferCount的值就减去1,而且pRxBuffPtr指针往下移,直到RxXferCount减为0 。

  uint8_t                       *pRxBuffPtr;      /*!< Pointer to USART Rx transfer Buffer */uint16_t                      RxXferSize;       /*!< USART Rx Transfer size              */uint16_t                      RxXferCount;      /*!< USART Rx Transfer Counter           */
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{uint16_t* tmp;uint16_t uhMask = huart->Mask;/* Check that a Rx process is ongoing */if(huart->RxState == HAL_UART_STATE_BUSY_RX){if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)){tmp = (uint16_t*) huart->pRxBuffPtr ;*tmp = (uint16_t)(huart->Instance->RDR & uhMask);huart->pRxBuffPtr +=2;}else{*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);}if(--huart->RxXferCount == 0){/* Disable the UART Parity Error Interrupt and RXNE interrupt*/CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);/* Rx process is completed, restore huart->RxState to Ready */huart->RxState = HAL_UART_STATE_READY;HAL_UART_RxCpltCallback(huart);return HAL_OK;}return HAL_OK;}else{/* Clear RXNE interrupt flag */__HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);return HAL_BUSY;}
}

串口接收中断流程

在这里插入图片描述

串口中断服务函数执行流程

串口中断服务函数中调用HAL库串口中断通用处理函数:HAL_UART_IRQHandler(); 该函数会对中断来源进行分析,调用相应函数。
对于不同的中断类型,我们只需要编写最终的中断处理函数:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);

串口接收实验

电脑通过串口助手往串口1发送字符,串口1通过中断方式接受字符,每接受一个字符就同时通过串口1返回给电脑。

  1. 初始化串口相关参数,使能串口:HAL_UART_Init();
  2. 串口相关IO口配置,复用配置:
    在HAL_UART_MspInit中调用HAL_GPIO_Init函数。
  3. 串口接收中断优先级配置和使能:
    HAL_NVIC_EnableIRQ();
    HAL_NVIC_SetPriority();
  4. 使能串口接收中断:HAL_UART_Receive_IT();
  5. 编写中断服务函数:USARTx_IRQHandler

根据如上步骤,其中1、2步骤和串口发送设置差不多,第三步,HAL_NVIC_SetPriority(USART1_IRQn,3,3);抢占和响应优先级均设置为3.这是因为main中的HAL_Init();有一个设置是 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

#include "sys.h"
#include "delay.h"
#include "usart.h" 
u8 rdata[1];//因为是每接收一个就发出去,所以设置为1
UART_HandleTypeDef usart1_handler;
//初始化串口相关参数,使能串口
void uart1_init(void)
{usart1_handler.Instance = USART1;usart1_handler.Init.BaudRate = 115200;usart1_handler.Init.WordLength = UART_WORDLENGTH_8B;usart1_handler.Init.StopBits = UART_STOPBITS_1;usart1_handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;usart1_handler.Init.Mode = UART_MODE_TX_RX;usart1_handler.Init.Parity = UART_PARITY_NONE;HAL_UART_Init(&usart1_handler);
}
//串口相关IO口配置,复用配置
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{GPIO_InitTypeDef GPIO_Initure;if(huart->Instance==USART1){__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟GPIO_Initure.Pin=GPIO_PIN_9;			//PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出GPIO_Initure.Pull=GPIO_PULLUP;			//上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH;		//高速GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9GPIO_Initure.Pin=GPIO_PIN_10;			//PA10HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10//串口接收中断优先级配置和使能HAL_NVIC_SetPriority(USART1_IRQn,3,3);//设置中断优先级HAL_NVIC_EnableIRQ(USART1_IRQn);//使能中断通道}
}
//编写中断服务函数
void USART1_IRQHandler()
{HAL_UART_IRQHandler(&usart1_handler);//由于调用一次中断,进入中断回调函数后,中断就结束了,所以还要开启中断HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata));//使能接收中断
}
//编写接收完成中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{u8 rec;if(huart->Instance==USART1){//rec = *((huart->pRxBuffPtr)-1);rec = rdata[0];//保存接收到的数据HAL_UART_Transmit(&usart1_handler,&rec,1,1000);}
}
int main(void)
{Cache_Enable();                 //打开L1-CacheHAL_Init();				        //初始化HAL库Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz delay_init(216);uart1_init();HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata));//使能接收中断while(1){}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/560277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32-外部中断配置-外部中断实验

STM32-外部中断原理与配置 IO口外部中断原理概述 STM32控制器支持的外部中断/事件请求 中断线M3M4M7EXTI线0~15:对应外部IO口的输入中断。√√√EXTI线16&#xff1a;连接到PVD输出。√√√EXTI线17&#xff1a;连接到RTC闹钟事件。√√√EXTI线18&#xff1a;连接到USB OTG…

STM32-独立看门狗原理-实验

独立看门狗原理概述 为什么要看门狗&#xff1a; 在由单片机构成的微型计算机系统中&#xff0c;由于单片机的工作常常会受到来自外界电磁场的干扰&#xff0c;造成程序的跑飞&#xff0c;而陷入死循环&#xff0c;程序的正常运行被打断&#xff0c;由单片机控制的系统无法继…

STM32-窗口看门狗-工作过程-配置-实验

窗口看门狗 窗口看门狗概述 之所以称为窗口就是因为其喂狗时间是一个有上下限的范围内(窗口&#xff09;&#xff0c;你可以通过设定相关寄存器&#xff0c;设定其上限时间&#xff08;下限固定&#xff09;。喂狗的时间不能过早也不能过晚。 而独立看门狗限制喂狗时间在0-x内…

音频和视频的基础知识

目录PCM-脉冲编码调制录音的原理记录声音-音频数字化音频数字化-PCM采样采样采样率采样定理量化位深度编码声道&#xff08;Channel&#xff09;比特率信噪比编码&#xff08;Encode&#xff09;解码&#xff08;Decode&#xff09;常见的音频编码和文件格式无损Monkeys AudioF…

神经网络算法-论证单层感知器的局限性

神经网络算法-论证单层感知器的局限性 今天课上学习了一个思路 将真值表转换到平面直角坐标系中 来论证线性可分还是不可分&#xff0c;挺有意思记录一下。 简单感知器模型实际上仍然是MP模型的结构&#xff0c;但是它通过采用监督学习来逐步增强模式划分的能力&#xff0c;达…

python 通过pip安装库 pycharm里面使用第三方库

安装所需的模块&#xff08;python&#xff09; pip 是 Python 包管理工具&#xff0c;该工具提供了对Python 包的查找、下载、安装、卸载的功能。 首先命令行输入pip3 --version查看是否有pip C:\Users\jym>pip3 --version pip 19.2.3 from d:\program files\python38\l…

python 实现TCP socket通信和 HTTP服务器、服务器和客户端通信python实例

python 实现TCP socket通信和 HTTP服务器、服务器和客户端通信实例socket是什么&#xff1f;服务器和客户端通信的流程python 实现TCP socket通信例子关于Host和PORT的设置socket函数socket编程思路基于TCP socket的HTTP服务器分析HTTP服务器代码服务器的response文本客户端的r…

判断ROS版本号-ubuntu20.04安装ROS_noetic-修改镜像源

判断ROS版本号-ROS安装-修改镜像源 linux版本:ubuntu20.04 ROS版本:noetic判断ROS版本号安装ROS改镜像源判断ROS版本号 机器人用的是树莓派、stm32、ros。 首先要配置网络&#xff0c;把机器人上的sd卡插到树莓派开发板上&#xff0c;然后配置连接的热点。 接下来&#xff0…

ROS基本概念 文件系统 创建ROS软件包 ROS中的一些命令

ROS基本概念 文件系统 创建ROS软件包 ROS中的一些命令ROS是什么ROS文件系统文件系统工具&#xff1a;rospack、roscd、rosls创建ROS 软件包catkin是什么创建和构建一个catkin工作空间&#xff1a;catkin软件包的结构catkin工作空间中存放软件包的结构创建catkin软件包-catkin_c…

ubuntu 中 ROS 一些报错的解决

1. Unable to load type jymubuntu:~/catkin_ws$ rosservice args /add_two_ints ERROR: Unable to load type [beginner_tutorials/AddTwoInts]. Have you typed make in [beginner_tutorials]?由于当前使用的终端的工作环境没有更新导致无法找到自定义的消息。使用下面的命…

ROS 创建msg和srv 编写发布者和订阅者节点 编写服务端和客户端节点(python版本)

ROS 创建msg和srv 编写发布者和订阅者节点 编写服务端和客户端节点-python版本rosedmsg和srv创建msg使用rosmsg创建srv使用rossrv重新make一下软件包编写发布者节点发布者节点代码解析编写订阅者节点订阅者节点代码解析构建节点运行发布者和订阅者节点编写服务节点编写客户端节…

从空间中理解线性代数

线性代数-从空间中理解总结向量线性组合空间的基 Basis张成的空间 Span线性相关和线性无关向量空间的一组基变换线性变换数值描述线性变换复合变换行列式矩阵的用途线性方程组逆矩阵列空间零空间秩非方阵基变换基变换矩阵特征向量 特征值特征基关于坐标总结 空间中不共线的两个…

python 视频和图片转换 视频压缩 图片降低分辨率 图像处理

python 做视频后期单个视频转图片所有图片转视频视频压缩 - ffmpeg图片降低分辨率图像处理这是最近无聊的想法&#xff0c;对视频进行处理&#xff0c;其实也就是对图片的处理。 对视频进行后期处理&#xff0c;思路就是&#xff0c;视频转图片&#xff0c;然后对图片进行处理…

矩阵论复习-过渡矩阵、生成子空间、表示矩阵、度量矩阵、酉空间、内积

一小部分矩阵论的整理复习&#xff0c;这个由于公式输入的太麻烦了&#xff0c;所以就弄了一点。后面直接看着书复习的。 矩阵论复习线性空间基与维数基变换公式、过渡矩阵、坐标变换公式线性子空间齐次方程组的解空间特征子空间生成子空间交空间和空间维数定理直和线性映射线性…

使用Anaconda3安装pytorch、paddle环境并在pycharm里面进行环境测试

安装完Anaconda后&#xff0c;也配好了框架的环境&#xff0c;接下来就需要在pycharm里面写代码了。 Anaconda里面的一些命令 1.新建环境&#xff0c;pytorch 是自己命的名&#xff08;新建虚拟环境&#xff09;conda create -n pytorch python3.82.看conda 环境中&#xff0…

Anaconda配置的环境里面增加第三方库的方法

用Anaconda3配置了paddle框架的环境&#xff0c;但是环境里面没有项目代码用到的一些包&#xff0c;比如matplotlib。 在Anaconda的Powershall里面输入如下内容可以增加一些包&#xff1a; 有三句话&#xff0c;第一句是看在conda 环境中&#xff0c;创建的所有环境。 第二句话…

python numpy常用操作、Numpy 多维数组、矩阵相乘、矩阵乘以向量

python numpy常用操作 Numpy基本操作 # 导入numpy import numpy as np # 生成numpy数组 x np.array([1.0, 2.0, 3.0]) print(x) # [1. 2. 3.] print(type(x)) # <class numpy.ndarray> # Numpy的算术运算 x np.array([1.0, 2.0, 3.0]) y np.array([2.0, 4.0, 6.0]…

【数据结构】——期末复习题题库(1)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

感知机实现与、或、与非门和异或门

机器学习-感知机【perceptron】what is 感知机单层感知机运用实例多层感知机what is 感知机 感知机接收多个输入信号&#xff0c;输出一个信号。 接收两个信号的感知机&#xff0c;如下图&#xff1a; x1与x2是输入信号&#xff1b;y是输出信号&#xff1b; w1与w2是权重。圆…

神经网络的激活函数、并通过python实现激活函数

神经网络的激活函数、并通过python实现what is 激活函数激活函数的python实现python实现阶跃函数python实现sigmoid函数python实现ReLU函数激活函数的特点what is 激活函数 感知机的网络结构如下&#xff1a; 左图中&#xff0c;偏置b没有被画出来&#xff0c;如果要表示出b&…