之前一直用的固件库跑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链接~

STM32串口中断接收HAL库超详解析相关推荐

  1. STM32串口中断接收实验

    STM32串口中断接收实验的详细说明 准备 代码实现 总结 准备 材料:STM32F407ZGT6最小系统板,串口1通过跳线帽连接到了CH340上. 需求:从电脑向板子的串口1发送一个字符串(以回车和 ...

  2. STM32 HAL库 串口DMA(收发)和STM32串口中断接收(接收时间管理机制)+ESP8266 wifi模组通信问题

    一.HAL库 串口 DMA+ESP8266模组通信问题 用STM32 HAL库串口的DMA发送和空闲中断接收处理数据,单片机发送AT指令给ESP8266 wifi模组问题:单片机连续几次给wifi模组 ...

  3. STM32串口中断接收方式详细比较

    本例程通过PC机的串口调试助手将数据发送至STM32,STM32通过SP3232芯片采用中断接收方式完成,然后接收数据后将所接收的数据又发送至PC机. 实例一: void USART1_IRQHand ...

  4. STM32串口中断接收标记USART_RX_STA 学习

    对于串口中断函数USART_RX_STA接收标记位解析,费话不多说了,直接上代码. #define USART1_REC_LEN 200 u8 USART1_RX_BUF[USART1_REC_LEN ...

  5. STM32串口中断接收帧数据并返回给上位机总结(配合MAX3483)

    一.前言 这是我的第一篇CSDN,记录一些代码总结,一方面与大家分享交流,另一方面方便以后再次使用能够快速回忆,再就是提高自身写作水平.如有错误之处,欢迎各位大佬批评指正. 二.所涉及的芯片 1.ST ...

  6. STM32 —— 串口数据接收

    STM32 -- 串口接收数据 我们已经在前面的博客中讲过了串口通信中发送数据和中断的一些基本原理,这里主要介绍串口接收数据的相关内容 定长字符串的接收 当接收单字节时,我们就可以使用最简单的接收方式 ...

  7. STM32串口的使用(原理、结构体、库函数、串口发送字符(串)、重定向printf串口发送、串口中断接收控制灯)

    参考:串口的结构体 重定向printf串口发送stm32等博文 作者:点灯小哥 发布时间: 2021-03-06 21:46:33 网址:https://blog.csdn.net/weixin_46 ...

  8. STM32使用串口中断接收HWT101的数据

    因研究生阶段项目需求,需要采用HWT101给单片机提供角度信息. HWT101是维特智能公司下的一款角度传感器,它可以通过计算角速度测量绕Z轴旋转的水平方向的偏航角,具有高精度.几乎无漂移.不受磁场干 ...

  9. stm32直流电机PID控制hal库(Cubemx)

    stm32直流电机PID控制hal库(Cubemx),一步步手把手教你怎么配置cubemx怎么写代码. 未对pid就行深入解析,不过相信您通过配置和写代码以后大概可以知道pid的主要作用. 文章目录 ...

最新文章

  1. EasyUI中树的基本操作
  2. 经典卷积网络进阶--ResNet详解
  3. 给Android程序员的一些面试建议,附带学习经验
  4. Python实现进度条和时间预估的示例代码
  5. 学mysql需要学python吗_python 学习 第六篇 mysql
  6. mysql Inoodb 内核
  7. 用OpenSSL写一个简单的Server/Client程序:证书与私钥
  8. Python Lambda 的简单用法
  9. 如何linux网页修改回80端口,linux下如何修改iptables开启80端口
  10. PHP Mysql-简介
  11. mongodb 启动 WARNING: soft rlimits too low, transparent_hugepage/enabled is 'always'. never
  12. 拓端tecdat|R语言ggmap空间可视化机动车碰撞–街道地图热力图
  13. 基于vue的个人博客
  14. 多个元素过渡---过渡模式
  15. android 圆角 水波纹_Android实现水波纹点击效果
  16. 学生信息管理系统 C++实现
  17. js判断android手机浏览器,【笔记】js判断移动端系统及浏览器
  18. 用批处理命令批量ping一个网段的IP
  19. 个人向的前端的坑坑洼洼的记录(1)
  20. conhosts 占用CPU

热门文章

  1. 考前一个月突击,PMP证书之旅
  2. freertos 怎么做超时处理_新公司开办费会计处理怎么做?如何进行税务处理?
  3. 身份证正则表达式 完美支持闰年
  4. 5G 接入网架构总结
  5. 生鲜超市会员连锁管理系统的应用(下)
  6. 防欺凌IP网络语音对讲系统特点有哪些?
  7. 从qemu-virtio到vhost-user
  8. WS2812灯珠(四)---实现全彩呼吸灯效果
  9. 信息学计算机奥林匹克竞赛题,全国青少年信息学(计算机)奥林匹克竞赛初中组复赛试题及答案分析.doc...
  10. int的极大值,无穷大