• STM32 HAL库使用中断实现串口接收不定长数据


      以前用DMA实现接收不定长数据,DMA的方法接收串口助手的数据,全部没问题,不过如果接收模块返回的数据,而这些数据如果包含回车换行的话就会停止接收,例如接收:AT OK ,就只能接收到AT ,导致没有接收完成,具体原因还没搞懂,有了解的,希望可以告知一下,DMA不定长接收方法传输门:https://www.cnblogs.com/xingboy/p/9714907.html

      好了,不多说了,现在进入正文。首先建立一个STM32Cumebx的工程,打开串口中断,完成配置,具体的配置流程就不细说了,没什么难度就只是打开串口跟中断而已。

      生成工程代码后,先定义好一些变量:

    //串口4中断接收定义
    #define MAX_RECV_LEN 1024         //设定可以接收的最大字节
    uint8_t msg_buff[MAX_RECV_LEN] = {0}; //接收缓存区
    uint8_t * msg = msg_buff;    //定义一个指针指向接收缓存区
    int flag = 0;        //接收完成标志
    int len_u4=0;  //数据长度记录

      接着重写串口接收回调函数

    /*重写串口接收回调函数*/
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
    {
         uint8_t ret = HAL_OK;
        msg++;
            len_u4++;//数据长度计数
        if( msg == msg_buff + MAX_RECV_LEN)
        {
            msg = msg_buff;
        }
             do  
        {  
            ret = HAL_UART_Receive_IT(UartHandle,(uint8_t *)msg,1);            
        }while(ret != HAL_OK);
            if(*(msg-1) == '
    ')   //接收以
    为结尾字符,则表示接收完成
        {
            flag  = 1;
        }
    }

      最后在main函数里面编写接收后的逻辑,注意要在while(1){ }前打开串口接收中断

    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration----------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();

     MX_DMA_Init();

      MX_USART3_UART_Init();

      MX_UART4_Init();
      /* USER CODE BEGIN 2 */
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
        //自己添加代码部分:while前打开串口中断接收
        HAL_UART_Receive_IT(&huart4, (uint8_t *)msg, 1); //开启第一次中断
      while (1)
      {
      /* USER CODE END WHILE *//* USER CODE BEGIN 3 */
    //======自己添加代码部分=========        
                if (flag == 1)
        {
                printf("msg_buff = %s ;len = %d
    ",msg_buff,len_u4);
           HAL_Delay(100); //加延时,保证接收到数据过长的时候,等待数据存入缓存区发送 HAL_UART_Transmit(
    &huart3,msg_buff, len_u4,100); //将串口4接收到的数据通过串口3传出 memset(msg_buff, 0, sizeof(msg_buff)); //清空缓存区 // 指向接收缓存的头部 msg = msg_buff; (&huart4)->pRxBuffPtr = msg; flag = 0; len_u4=0;//每次数据长度清0 } HAL_Delay(10); } //============================== /* USER CODE END 3 */ }

      运行结果如下,效果正确

      

      谈谈串口RS232跟RS485:这两个串口除了逻辑电平不同外,还有传输距离也不同,如果对速度要求不高,传输距离要比较远的就用RS485比较好,虽然RS485是个半双工,但是抑制共模干扰能力比较强,不过这些只是对于硬件层面的,对于软件层面来说他们的本质都是串口,在STM32Cubemx中,都是只是配置为串口,按照串口的编程来处理即可。

  • 相关阅读:
    PrintStream标准字节输出流
    DataInputStream数据字节专属输入流
    java.io.DateOutputStream:数据专属字节输出流
    BufferedWriter带有缓冲区的输出流 及 OutputStreamWriter转换流
    BufferedReader带有缓冲区的输入流 及 InputStreamReader转换流
    FileWriter输出文本流
    FileReader输入文本流
    使用FileInputStream 和 FileOutputStream 进行copy流 和 使用FileReader 和 FileWriter 进行 copy流案例:
    FileOutputStream输出字符流
    window docker的安装
  • 原文地址:https://www.cnblogs.com/xingboy/p/10154475.html
Copyright © 2020-2023  润新知