IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32串口中断接收HAL库超详解析 -> 正文阅读

[嵌入式]STM32串口中断接收HAL库超详解析

之前一直用的固件库跑c8t6和zet6,现在有幸接触到stm32H743用到HAL库,学习嘛都是踩坑,csdn,然后...理解底层库的代码

本人有幸遇到了H7的串口中断接收只进去一次的Bug,于是马上csdn,才发现网上全是在回调函数里写接收处理的逻辑,而我不一样,可能我比你们帅我就要把接收逻辑写在中断服务函数里面(狗头),其实是因为最先接触的板子是103的c8t6所有例程都是在服务函数里处理的,所有养成了习惯,做H7的工程时就直接移植了;但找了2天我也没在网上没有找到将逻辑写在服务函数里面的,于是乎,花费一天时间看HAL库的串口驱动程序,终于!调通了,话不多说,

上!代!码!

串口初始化和固件库的配置逻辑大体一样:

?
void UART2_Config(void)
{
?? ?GPIO_InitTypeDef GPIO_InitStruct;

?? ?RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
?? ??? ??? ?
?? ?UART2_RX_GPIO_CLK_ENABLE();
?? ?UART2_TX_GPIO_CLK_ENABLE();
?? ?
?? ?/* 配置串口2时钟源*/
?? ?RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
?? ?RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
?? ?HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
?? ?/* 使能 UART2 时钟 */
?? ?UART2_CLK_ENABLE();

?? ?/**USART2 GPIO Configuration ? ?
? ? PA2 ? ? ------> USART2_TX
? ? PA3 ? ?------> USART2_RX?
?? ?*/
?? ?/* 配置Tx引脚为复用功能 ?*/
?? ?GPIO_InitStruct.Pin = UART2_TX_PIN;
?? ?GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
?? ?GPIO_InitStruct.Pull = GPIO_PULLUP;
?? ?GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
?? ?GPIO_InitStruct.Alternate = UART2_TX_AF;
?? ?HAL_GPIO_Init(UART2_TX_GPIO_PORT, &GPIO_InitStruct);
?? ?
?? ?/* 配置Rx引脚为复用功能 */
?? ?GPIO_InitStruct.Pin = UART2_RX_PIN;
?? ?GPIO_InitStruct.Alternate = UART2_RX_AF;
?? ?HAL_GPIO_Init(UART2_RX_GPIO_PORT, &GPIO_InitStruct);?
?? ?
?? ?/* 配置串USART2 模式 */
?? ?Uart2_Handle.Instance = UART2;
?? ?Uart2_Handle.Init.BaudRate = 115200;
?? ?Uart2_Handle.Init.WordLength = UART_WORDLENGTH_8B;
?? ?Uart2_Handle.Init.StopBits = UART_STOPBITS_1;
?? ?Uart2_Handle.Init.Parity = UART_PARITY_NONE;
?? ?Uart2_Handle.Init.Mode = UART_MODE_TX_RX;

?? ?HAL_UART_Init(&Uart2_Handle);

?? ?/*串口2中断初始化 */
? ? HAL_NVIC_SetPriority(UART2_IRQ, 0, 3);
? ? HAL_NVIC_EnableIRQ(UART2_IRQ);
? ? /*配置串口接收中断 */
? ? __HAL_UART_ENABLE_IT(&Uart2_Handle,UART_IT_RXNE);?
}

/**
? * @brief ?UART2 GPIO 配置,工作模式配置。115200 8-N-1
? */ ?

需要注意调用 __HAL_UART_ENABLE_IT(&Uart2_Handle,UART_IT_RXNE)函数使能中断。

接下来是中断服务函数的编写:


unsigned char SHU1[42]={0}; ?//接收缓存
unsigned char ces[1];
unsigned char MODE=0;?
u8toointt pos1,pos2,pos3,pos4,pos5,pos6;?? ?
float posBi[7]={0,0,0,0,0,0,0};//机械臂角度

void UART2_IRQHandler(void)
{
?? ?static unsigned char conunt=0; // 接收记录
?? ?static unsigned char i = 0; ?? ?//记录数据个数
?? ?static unsigned char j = 0;?
?? ?uint32_t timeout=0;
? ? uint32_t maxDelay=0x1FFFF;

?? ?//调用HAL_UART_Receive_IT函数进行接收可再次开启中断
?? ?HAL_UART_IRQHandler(&Uart2_Handle);?? ?//调用HAL库中断处理公用函数
?? ?timeout=0;
? ? while (HAL_UART_GetState(&Uart2_Handle)!=HAL_UART_STATE_READY)//等待就绪
?? ?{
? ? ? ? timeout++;超时处理
? ? ? ? if(timeout>maxDelay) break;?? ??? ?
?? ?}
? ? ?
?? ?timeout=0;
?? ?while(HAL_UART_Receive_IT(&Uart2_Handle,(uint8_t *)ces, 1)!=HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
?? ?{
? ? ? ? timeout++; //超时处理
? ? ? ? if(timeout>maxDelay) break;?? ?
?? ?}
//处理接收到的一个字节
?? ??? ?switch(conunt)
?? ??? ?{
?? ??? ??? ?case 0:
?? ??? ??? ??? ?if(ces[0] == 0xFF) conunt++;
?? ??? ??? ??? ?else conunt=0; ? ?
?? ??? ??? ??? ?break;
?? ??? ??? ?case 1:
?? ??? ??? ??? ?if(ces[0] == 0xFF) conunt ++; //数据帧头?? ??? ?
?? ??? ??? ??? ?else conunt = 0;
?? ??? ??? ??? ?break;
?? ??? ??? ?case 2://角度包
?? ??? ??? ??? ?SHU1[i] = ces[0];
?? ??? ??? ??? ?i++;
?? ??? ??? ??? ?if(i==6)//接收完成了开始验证
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?if(SHU1[5]==0xFE)//判断数据帧尾?
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?switch(SHU1[0])
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ? ? ?case 0x01:
?? ??? ? ? ? ? ? ? ?for(j=0;j<=3;j++) //pos1角度接收?
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pos1.Receive_Val[j]=SHU1[j+1];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ? ? posBi[1]=pos1.Act_val; ??
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ?case 0x02:
?? ??? ? ? ? ? ? ? ?for(j=0;j<=3;j++) //pos2角度接收?
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pos2.Receive_Val[j]=SHU1[j+1];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ? ?posBi[2]=pos2.Act_val; ??
?? ??? ??? ??? ??? ??? ??? ?break; ? ??
?? ??? ??? ??? ??? ??? ??? ?case 0x03:
?? ??? ? ? ? ? ? ? ?for(j=0;j<=3;j++) //pos3角度接收?
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pos3.Receive_Val[j]=SHU1[j+1];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ? ? posBi[3]=pos3.Act_val; ??
?? ??? ??? ??? ??? ??? ??? ?break; ? ??
?? ??? ??? ??? ??? ??? ??? ?case 0x04:
?? ??? ? ? ? ? ? ? ?for(j=0;j<=3;j++) //pos4角度接收?
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pos4.Receive_Val[j]=SHU1[j+1];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ? ? posBi[4]=pos4.Act_val; ??
?? ??? ??? ??? ??? ??? ??? ?break; ? ??
?? ??? ??? ??? ??? ??? ??? ?case 0x05:
?? ??? ? ? ? ? ? ? ?for(j=0;j<=3;j++) //pos5角度接收?
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pos5.Receive_Val[j]=SHU1[j+1];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ? ? posBi[5]=pos5.Act_val; ??
?? ??? ??? ??? ??? ??? ??? ?break; ? ??
?? ??? ??? ??? ??? ??? ??? ?case 0x06:
?? ??? ? ? ? ? ? ? ?for(j=0;j<=3;j++) //pos6角度接收?
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pos6.Receive_Val[j]=SHU1[j+1];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ? ? posBi[6]=pos6.Act_val; ??
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ?case 0x07://模式控制
?? ??? ??? ??? ??? ??? ??? ??? ? ?MODE=SHU1[1]-0x30; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?? ??? ??? ??? ??? ??? ?} ?? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?conunt = 0;
?? ??? ??? ??? ??? ?i = 0;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?break;
?? ??? ?}?? ?

大家可以看见,本帅哥的处理逻辑是一个字节一个字节地进行,这里的逻辑是用来接收上位机发来的6个角度的,在上位机先将角度(小数)放在共用体的float 类型成员变量中,然后发送角度的 unsigned char 类型成员变量

共用体定义如下:

typedef union
{
?? ?unsigned char Receive_Val[3];
?? ?float Act_val;
}u8toointt;

一个小数4个字节,所以对应4个字符型变量储存,然后32这边也定义一个共用体,用unsigned char 类型成员变量去接收,解出他的float 类型成员变量,便是我想要的角度了,怎么样,这一波我帅吧?

突然发现跑题了,来看看我们是怎么解决中断只进去一次的问题的:

官方给的中断接收的逻辑是写在回调函数里的,为什么写在回调函数里面呢?

看这篇文章:(14条消息) 那些我们一起踩过的STM32HAL库的串口坑_我又不会射雕的博客-CSDN博客

大概意思就是当有中断发送,硬件自动触发然后调用一系列函数,调用到?UART_Receive_IT()函数后,便会关闭中断!!!也就是串口看起来就只能进入一次中断!

有的小可爱可能会问我为什么我能一直进中断呢?我试过,当上位机发送很快,且每次发送的字节数较少时(大概1个),我怎么配置他都能进中断!可能UART_Receive_IT()函数关闭中断的条件是中断触发的间隔时间吧,这点我没细看~

当然有小可爱可能会说我像官方例程那样写,就什么问题都没有,我说小可爱,你可真可爱,没问题你来看我这篇文章干嘛,让我火吗???如果是,那给我点赞吧,不谢!我很帅!

回归正题:

注意看我的UART2_IRQHandler(void)函数里面接收函数用的HAL_UART_Receive_IT(&Uart2_Handle,(uint8_t *)ces, 1)!=HAL_OK

还有一种接收函数是HAL_UART_Receive(&huart2,&Res,1,1000);

它们两个处理名字差了三个字符外有什么区别呢?

关键点来了:

一起来看这篇文章:(14条消息) STM32采用HAL库HAL_UART_Receive_IT()多次开启的问题_暖暖_的_纠结的博客-CSDN博客_hal_uart_receive_it

无情的文章搬运小天才(滑稽)~

没看懂?解释一下我的理解:

HAL_UART_Receive函数为非阻塞式接收,HAL_UART_Receive_IT()为阻塞式接收,说人话就是调用HAL_UART_Receive_IT()函数,一旦中断来了就能接收(前提是中断使能了),而HAL_UART_Receive则不一样,用在接收的地方卵用没有,简直消磨帅哥的时间~哼~

所以我们使用HAL_UART_Receive_IT()函数,如果我们需要判断接收超时怎么办?我去官方例程copy了一下自己看上面 (^-^)

这样写以后,帅哥再也不用担心H7串口进不去中断了,完美避开回调函数的写法,帅哥可高兴了,马上去食堂买一个水煮玉米奖励自己~~~

然后你肯定想要移植,我这个工程肯定不会完全给你,但是可以给你这个串口接收的文件,欢迎期待我的github链接~

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:33:24  更:2021-11-20 18:34:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:44:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码