STM32F1和STM32CubeMx串口中断通讯实现(字符串发送与接收)详解

串口通讯的实现

  • STM32CubeMx软件设置
  • Keil软件及代码编写
  • 串口的功能设计
  • 主函数的编写
  • 效果实现
  • STM32CubeMx软件设置

    首先选好自己的板子并打开软件设置,本实验基于STM32F103ZET6实现,打开软件后如图:

    打开外部高速晶振,然后接着配置时钟:

    将时钟频率修改为72MHz,接着设置接线方式为SW

    接下来需要使用串口中断通讯,打开我们的串口设置并打开中断

    这里波特率设置为115200,数据位为8位,无校验位,停止位为1位,通信模式设置为异步通信,以及可以接受及发送数据。

    接着打开中断,并设置抢占优先级和响应优先级,这里设置为0,0。
    至此STM32CubeMx就设置完成了。

    Keil软件及代码编写

    打开Keil以后生成以下文件:

    这里的uart.c是我自己编写的,方便后续管理,我们先来看看usart.c中的初始化函数:


    分别有两个函数,一个设置我们的串口相关功能,一个则是打开我们所需要功能的时钟、配置相应的IO口,以及打开中断。
    接下来看中断的相关处理

    Hal库的中断处理函数都会放在这个it.c文件中,然后函数内部会调用关于串口的中断公共处理函数,并且会在里面失能中断,所以添加一个while重新使能中断。
    关于函数的快速查找可以点击左边窗口下方的functions打开对应的文件就能找到我们所需的函数:

    接着通过跳转功能进入中断的公共处理函数,并找到对应的中断回调函数,即:


    这里是一个弱定义,里面是空,即用户需要使用到时可以自己进行改写,所以下一步就是来编写所需要的功能:

    串口的功能设计

    uart.h编写

    #ifndef __UART_H
    #define __UART_H
    
    #include "usart.h"
    
    #define uart_len 200
    #define hal_uart_len 1
    
    extern uint8_t g_rx[uart_len];                  //存放字符串数组
    extern uint8_t g_rx_buffer[hal_uart_len];       //HAL库用存放缓存区
    
    /* 存放数据标志位
       以回车换行符进行判断接收完毕
       15位置1表示接收到换行符,14位置1表示接收到回车
    */
    
    extern uint16_t  g_usart1_rx_sta;
    
    
    #endif
    
    

    uart.c编写

    uint8_t g_rx[uart_len];                  //存放字符串数组
    uint8_t g_rx_buffer[hal_uart_len];       //HAL库用存放缓存区
    
    uint16_t  g_usart1_rx_sta = 0;
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        if((g_usart1_rx_sta & 0x8000) == 0)         //判断标志位15位是否被置1,若为0则接受还没结束
        {
            if(g_usart1_rx_sta & 0x4000)            //判断标志位14位是否被置1
            {
                if(g_rx_buffer[0] != 0x0a)
                {
                    g_usart1_rx_sta = 0;            //若接收到回车后下一位不为换行则接收失败
                }
                else
                {
                    g_usart1_rx_sta |= 0x8000;
                }
            }
            else
            {
                if(g_rx_buffer[0] == 0x0d)          //判断缓存器中当前是否接收到回车
                {
                    g_usart1_rx_sta |= 0x4000;
                }
                else
                {
                    //数据转移
                    g_rx[g_usart1_rx_sta & 0x3fff] = g_rx_buffer[0];
                    g_usart1_rx_sta++;
                    
                    //超出数组存放上限
                    if(g_usart1_rx_sta > (uart_len-1))
                    {
                        g_usart1_rx_sta = 0;
                    }
                }
                
            }
        }
    }
    

    这里通过设定一个g_usart1_rx_sta标志位来判断接收到的数据有多长,这里设定字符串加上回车就代表发送完成,即需要判断是否收到\r\n来判断接收是否终止。\r的ascii值为0x0d,\n的ascii值为0x0a。

    主函数的编写

      /* USER CODE BEGIN 2 */
        //接收数据使能中断
        HAL_UART_Receive_IT(&huart1, (uint8_t*)g_rx_buffer, hal_uart_len);
        uint8_t len = 0;
        uint16_t time = 0;
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
          if (g_usart1_rx_sta & 0x8000)        /* 接收到了数据? */
            {
                len = g_usart1_rx_sta & 0x3fff;  /* 得到此次接收到的数据长度 */
                printf("\r\n您发送的消息为:\r\n");
    
                HAL_UART_Transmit(&huart1,(uint8_t*)g_rx, len, 1000);    /* 发送接收到的数据 */
                while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC) != SET);           /* 等待发送结束 */
                printf("\r\n\r\n");             /* 插入换行 */
                g_usart1_rx_sta = 0;
            }
            else
            {
                time++;
    
                if (time % 5000 == 0)
                {
                    printf("\r\n串口实验\r\n");
                }
    
                if (time % 200 == 0) printf("请输入数据,以回车键结束\r\n");
                HAL_Delay(10);
            }
      }
      /* USER CODE END 3 */
    

    这里是需要使用到串口中断接收,所以我们第一步是需要使能我们的串口中断接收,即下面这个函数:

    HAL_UART_Receive_IT(&huart1, (uint8_t*)g_rx_buffer, hal_uart_len);
    

    这个函数的第一个参数是句柄,也就是对应的初始化串口的结构体,可在usart.c中找到,第二个参数是接收的缓冲寄存器,即用户自己设定的寄存器,第三个则是接收长度。
    然后接收完成后,通过len参数判断接收到的长度,在通过发送函数将数据发送回去,即下面这个函数:

    HAL_UART_Transmit(&huart1,(uint8_t*)g_rx, len, 1000); 
    

    这个函数的参数跟使能中断接收差不多,多了最后一个参数为超时时间,同时这个函数为阻塞发送,即数据没发送完就会一直发送无法处理其他事情。
    同时还在这个主函数中添加了printf函数代表我们的STM32正常工作,需要用到这个printf函数我们就需要在usart.c中添加一个重定向函数:

    /* USER CODE BEGIN 1 */
    //串口打印重定向
    int fputc(int ch, FILE *f)
    {
      HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
      return ch;
    }
    /* USER CODE END 1 */
    

    添加完成后再包含stdio.h头文件即可。

    效果实现

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32F1和STM32CubeMx串口中断通讯实现(字符串发送与接收)详解

    发表评论