zoukankan      html  css  js  c++  java
  • STM32 HAL库 UART 串口读写功能笔记

    https://www.cnblogs.com/Mysterious/p/4804188.html

    STM32L0 HAL库 UART 串口读写功能

    串口发送功能:

    uint8_t TxData[10]= "01234abcde";
    HAL_UART_Transmit(&huart2,TxData,10,0xffff);//把TxData的内容通过uart2发送出去,长度是10,timeout的时间是最大值0xffff

    串口接收功能1:

    uint8_t value='F';
    HAL_UART_Receive(&huart2,(uint8_t *)&value,1,1000);//在这个语句停留1000ms内等待接收1个字节数据,把数据存放在value中

    串口接收功能2:

    HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,1);//程序不会在这个语句停留,直接会按照中断方式把接收数据存放在value中,但是这个语句只能使能一次串口中断。所以要在中断服务函数或者回调函数中重新使能

    串口接收功能3:

    if(HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,1) != HAL_OK){    //这一句写在main函数的while(1)上面。用于启动程序启动一次中断接收
            HAL_UART_Transmit(&huart2, (uint8_t *)&"ERROR
    ",7,10);    
            while(1);
    } 
    复制代码
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
    {
        HAL_UART_Transmit(&huart2, (uint8_t *)&"
    into HAL_UART_RxCpltCallback
    ",32,0xffff);    //验证进入这个函数了
        HAL_UART_Transmit(&huart2,(uint8_t *)&value,1,0xffff);      //把接收到的数据通过串口发送出去        
        HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,1);        //重新打开串口中断
    }
    复制代码

    串口DMA发送

    DMA的TX要这样设置

        uint8_t txData[] = {"HelloWorld
    "};
        HAL_UART_Transmit_DMA(&huart2,txData,sizeof(txData));//可以通过DMA把数据发出去

     DMA接收

    if(HAL_UART_Receive_DMA(&huart2, (uint8_t *)rxData, sizeof(rxData)-1) != HAL_OK)//main函数while(1)前,启动一次DMA接收
        {
            Error_Handler();
        }

     串口回调函数:

    复制代码
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){
        
        uint8_t temp[] = {"
    in Callback
    "};
        HAL_UART_Transmit_DMA(&huart2,temp,sizeof(temp)-1);//可以通过DMA把数据发出去
        
        HAL_UART_Receive_DMA(&huart2, (uint8_t *)rxData, sizeof(rxData)-1);    //重新使能接收    
    }
    复制代码

     main函数while(1)中不断输出rxData值

    HAL_UART_Transmit_DMA(&huart2,rxData,sizeof(rxData)-1);//可以通过DMA把数据发出去

    https://www.cnblogs.com/UnfriendlyARM/p/10321838.html

    STM32串口接收中断——基于HAL库

    写在前面  

      最近需要使用一款STM32L4系列的芯片进行开发,需要学习使用HAL库。在进行串口中断使用的时候遇到了一些小麻烦,写下解决方案供大家参考。

    1.UART相关的头文件引用错误

       由于本人直接使用MDK进行开发,没有使用CubeMX,所以一些初始化需要手动进行。在引用UART相关的头文件时,记得将"stm32l4xx_hal_conf.h"文件中的相关宏定义取消注释,如下图:

    2.如何接收字符串(多次进入中断)

      接收字符串主要有两种方法,一种是对中断函数进行改造,另一种是对接收回调函数进行改造。
      在阐述这两种方法之前,需要介绍函数“HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)”。该函数的作用是用户自定义一个缓冲区(即参数pData),接受一定数量(由参数Size决定)的字符存入缓冲区中。同时,参数Size还决定着进入回调函数的频率,即每接收Size个字符,就进入一次回调函数。需要注意的是,Size只决定进入回调函数的频率,而不能影响进入接收中断的频率,无论Size是多少,每接收完成一个字符都会进入一次接收中断。

    方法1:改造回调函数

      ①首先在主函数中进入主循环前的位置调用一次 HAL_UART_Receive_IT函数,定义一个字符数组getBuffer[]作为缓冲区,参数Size设定为10。即每接收10个字符,就进入一次回调函数。

      ②注册中断函数   

    1  void USART1_IRQHandler(void)
    2  {
    3    HAL_UART_IRQHandler(&UartHandle); //该函数会清空中断标志,取消中断使能,并间接调用回调函数
    4  }

      ③在文件“stm32l4xx_hal_uart.h”中,我们可以看到串口接收回调函数的定义。使用“_weak”关键字定义的函数,其具有如下特性: 一般情况下和一般函数相同。但是当有一个同名函数但是不带__weak被定义时,所有对这个函数的调用都是指向后者(不带__weak那个)。也就是说,ST官方提供的这个回调函数需要我们自己进行改写。  

    复制代码
     1    /**
     2     * @brief Rx Transfer completed callback.
     3     * @param huart UART handle.
     4     * @retval None
     5     */
     6   __weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
     7   {
     8     /* Prevent unused argument(s) compilation warning */
     9     UNUSED(huart);
    10       
    11     /* NOTE : This function should not be modified, when the callback is needed,
    12               the HAL_UART_RxCpltCallback can be implemented in the user file.
    13      */
    14   }
    复制代码

      我们在主函数所在的文件中对回调函数进行改写:  

    复制代码
    1   uint8_t myBuffer[] = "I have gotten your message: "; //用户提示信息
    2   uint8_t Enter[] = "
    "; //回车换行
    3   uint8_t getBuffer[100]; //用户自定义的缓冲区
    4   void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
    5   {
    6    while(HAL_UART_Transmit(UartHandle, (uint8_t*)myBuffer, COUNTOF(myBuffer), 5000)!= HAL_OK); //发送字符串,用户提示信息
    7    while(HAL_UART_Transmit(UartHandle, (uint8_t*)getBuffer, 10, 5000)!= HAL_OK); //发送用户自定义缓冲区中的数据
    8    while(HAL_UART_Transmit(UartHandle, (uint8_t*)Enter, COUNTOF(Enter), 5000)!= HAL_OK); //发送回车换行
    9   }
    复制代码

      以上代码的作用是把用户发送给单片机数据再返回给用户。运行效果如下图:

     
      我们可以看到,用户向单片机发送了10个字符,单片机向串口助手返回了这10个数据。但是以上程序只能实现一次,当我们再次向单片机发送数据时,单片机却不再返回数据。这是因为我们在中断函数中取消了中断使能,所以导致了进入一次中断后,中断被关闭,无法再次进入中断的现象。为了实现多次数据返回,我们要在中断处理函数中添加一行代码: 
    1  void USART1_IRQHandler(void)
    2  {
    3    HAL_UART_IRQHandler(&UartHandle); //该函数会清空中断标志,取消中断使能,并间接调用回调函数
    4    HAL_UART_Receive_IT(&UartHandle, (uint8_t *)&value,1);  //添加的一行代码
    5  }

      这样就可以实现多次数据返回了,新的执行结果如下图:

     

      可见,函数HAL_UART_Receive_IT还有中断使能的作用。这一功能的实现我们可以在HAL_UART_Receive_IT函数中找到。

     方法2:改造中断处理函数

      ①首先在主函数中进入主循环前的位置调用一次 HAL_UART_Receive_IT函数,定义一个字符value作为缓冲区,参数Size设定为1。即每接收1个字符,就进入一次回调函数。使得进入回调函数的频率与进入中断处理函数的频率相同。这样,我们就可以直接在中断函数中对接收的数据进行处理了。

      ②注册中断函数    

    复制代码
     1   uint8_t myBuffer[] = "I have gotten your message: ";
     2   uint8_t getBuffer[10];
     3   uint8_t Enter[] = "
    ";
     4   void USARTx_IRQHandler(void)
     5   {
     6    HAL_UART_IRQHandler(&UartHandle); //该函数会清空中断标志,取消中断使能,并间接调用回调函数
     7    
     8    getBuffer[countOfGetBuffer++] = value; 
     9    if(countOfGetBuffer == 10)
    10    {
    11     while(HAL_UART_Transmit(&UartHandle, (uint8_t*)myBuffer, COUNTOF(myBuffer), 5000)!= HAL_OK);
    12     while(HAL_UART_Transmit(&UartHandle, (uint8_t*)getBuffer, countOfGetBuffer, 5000)!= HAL_OK);
    13     while(HAL_UART_Transmit(&UartHandle, (uint8_t*)Enter, COUNTOF(Enter), 5000)!= HAL_OK);
    14     countOfGetBuffer = 0;
    15    }
    16    HAL_UART_Receive_IT(&UartHandle, (uint8_t *)&value,1);  //由于接收中断是每接收一个字符便进入一次,所以这一行代码必须添加,否则只能接收一个字符,而无法接收整个字符串
    17   }
    复制代码

      以上代码的作用是接收每个来自用户的字符,并依次存入用户自定义的缓冲区中,数量达到10个后,将缓冲区中的所有数据返回给用户,同时清空计数,准备接下来10个字符的接收。运行效果如下图:

     

    写在最后

      看完本文,大家可能对回调函数和中断处理函数的关系产生了疑问。其实是这样的,单片机每完成接收一个字符,就会进入一次中断处理函数,而在中断处理函数中,我们又调用了函数“void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)”,该函数会间接调用回调函数,也就是说回调函数是由中断处理函数间接调用的。而函数“HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)”决定了中断处理函数调用回调函数的频率,若Size为1,则每进入一次中断处理函数都会调用一次回调函数;若Size为10,则每第十次进入中断处理函数时,才会调用回调函数。方法2使用了标准库中断处理数据的思想。

  • 相关阅读:
    UITabBarController资料
    lintcode157 判断字符串是否没有重复字符
    设置TabBarItem选中时的图片及文字颜色
    扩展UIColor类
    设置UINavigationController相同标题
    iOS打开手机QQ与指定用户聊天界面
    UIWindow
    Google Test资料
    Xcode集成Google Test
    文章索引
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/11487378.html
Copyright © 2011-2022 走看看