基于stm32f103任意发送字符串-中级


实验目的

本文主要是实现串口助手发送任意字符串,在屏幕上接收到相同的字符串。

实验环境

  1. 软件: stm32cubemx ,keilMDK,Configure Virtual Serial Port Driver,串口助手
  2. 硬件:stm32f103开发版
  3. 资料:stm32f103中文参考手册

实验现象

实验现象

实验步骤

硬件引脚

如图表1-1所示,为stm32f103vet6芯片USART中TX,RX的引脚。本文使用ABP2总线中的USART1串口实现串口接收发送任意字符串。

引脚 ABP2总线 ABP1总线
USART1 USART2 USART3 UART4 UART5
TX PA9 PA2 PB10 PC10 PC12
RX PA10 PA3 PB11 PC11 PD2

软件设计

UASRT初始化

UASRT初始化就不介绍了,可以在本博客基于stm32cubemx实现串口接收与发送-基础进行学习。

回显任意字符串

1.基础

接收发送任意字符串中,本文使用的是中断函数。在基础篇中,可以知道,当进入中断函数时,函数调用的是HAL_UART_IRQHandler(&huart1); 这个函数,并且最终在HAL_UART_RxCpltCallback(huart);这个回调函数中进行编写,实现一些功能。由于这些函数都是HAL库中的函数,在接收发送过程中固定的字符个数,无法接收发送任意字符个数。那我们该如何实现接收发送任意个数的字符。
首先我们可以看参考手册中数据寄存器(USART_DR)一次接收发送时是什么样的。如图1-2所示:
图1-2数据寄存器(USART_DR)
从图中可以看出数据寄存器每次只能接收和发送9位,而一个字符为8位,因此串口每次接收和发送一个字符。那我们该如何实现接收和发送无限制字符串。其实可以这样。每当接收一个字符我们就把这个字符发送出去,这样就可以接收和发送任意字符串。在中断服务函数中,我们可以不用调用HAL_UART_IRQHandler函数,而是直接编写自己的中断函数。下面就是我写的中断函数内容:

void USART1_IRQHandler(void)
{
  uint8_t ch;
 if (__HAL_UART_GET_FLAG( &huart1, UART_FLAG_RXNE ) != RESET)//获取接收中断事件标志
  {
    ch=( uint16_t)READ_REG(huart1.Instance->DR);//接收字符
    WRITE_REG ( huart1.Instance->DR,ch);//发送字符
  }
}

为什么要这样写,我们可以和51单片机相比较,当51单片机接收一个字符是,RI=1,和__HAL_UART_GET_FLAG( &UartHandle, UART_FLAG_RXNE ) != RESET相当于一个意思。在51单片机中ch=SBUF,表示将接收到的字符放入ch里,类似于我们这ch=( uint16_t)READ_REG(UartHandle.Instance->DR)这个语句。那么WRITE_REG ( UartHandle.Instance->DR,ch);也就是发送字符。
这里问题来了,为什么在51单片机中,RI要软件清零,而这里不需要。这里我们就需要看芯片的参考手册了。如图1-3所示,在参考手册状态寄存器(USART_SR)中可以找到这个。
图1-3RXNE
这里我们可以读到对USART_DR的读操作可以将该位清零。因此可以不需要和51单片机中RI需要软件清零。
当然,在初始化中要打开接收中断使能,否在串口中断无法进入。

 __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//接收中断使能

这样就实现了串口任意接收和发送字符串了。

2. 提升

上面的代码中就是单纯的接收和发送任意字符串。如果我们需要发送一个字符串来控制单片机的某个东西,而且单片机还要发送一串字符,表示已经执行的我们所需要控制的的东西,那我们该怎么办。其实学我们专业都见过这样一个东西,计算机中dos,当我们写入某个指令,按回车就能反馈看的东西。在这里我们也可以用这个方式来实现这个功能。
步骤如下:

  1. 接收字符

  2. 判断字符是否为’\n’

  3. 为字符’\n’flag标志置1,关闭串口中断进行发送字符

  4. flag置0,打开接收中断使能
    将stm32f1xx_it.c文件中USART1_IRQHandler(void)放入main.c文件下,在中断函数中代码如下:

    void USART1_IRQHandler(void)
    {
    //HAL_UART_IRQHandler(&huart1);
    uint8_t ch ;
    if(__HAL_UART_GET_FLAG( &huart1, UART_FLAG_RXNE ) != RESET)
    {
      ch=( uint16_t)READ_REG(huart1.Instance->DR);
      USART_RX_BUF[USART_RX_STA&0X3FFF]=ch;//接收到的字符保存在 USART_RX_BUF 数组中
      if(USART_RX_BUF[USART_RX_STA] == 0X0A && USART_RX_BUF[USART_RX_STA-1] == 0X0D)//判断是否为'\n'
        {
          flag = 1;  //置1
          __HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE);//关闭接收中断
        }
      USART_RX_STA++; //计数接收到的字符的个数
    }
    }

    USART_RX_BUF数组和USART_RX_STA为全局变量,上面代码中我们将接收到的字符放入USART_RX_BUF数组中,一旦检测到数组中有’\n’时,flag置1,关闭中断。
    然后在main.c 里while(1)中加入下面代码:

    while (1)
    {
    /* USER CODE END WHILE */
     if(flag) //如果flag为1
         {
             flag = 0;//flag为0
             HAL_UART_Transmit(&huart1,USART_RX_BUF,USART_RX_STA,1000);发送字符,查询方式
             for(uint16_t i = 0; i<USART_RX_STA; i++) //清空数组
             {
                 USART_RX_BUF[i] = 0;
             }
             USART_RX_STA = 0; 计数为0
             __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//打开接收中断
         }
    /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
    }

    在这段代码中表示当flag=1时,将接收到的字符发送出去,然后清空数组,计数为0最后在打开中断。当然,也可以在里面判断接收的字符串,然后发送自己想看的字符串。

    代码的位置

    代码的位置在main.c文件中,如图1-4,图1-5,图1-6所示:
    图1-4全区变量
    图1-5串口中断函数
    图1-6发送配置


文章作者: 潘苏皖
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 潘苏皖 !
评论
 上一篇
基于Matlab中数据拟合实现红外传感器值与距离的关系 基于Matlab中数据拟合实现红外传感器值与距离的关系
什么是数据拟合 数据拟合又称曲线拟合,俗称拉曲线,是一种把现有数据透过数学方法来代入一条数式的表示方式。科学和工程问题可以通过诸如采样、实验等方法获得若干离散的数据,根据这些数据,我们往往希望得到一个连续的函数(也就是曲线)或者更加密集的离
2020-04-22
下一篇 
基于stm32cubemx实现串口接收与发送-基础 基于stm32cubemx实现串口接收与发送-基础
串口是什么 串行接口简称串口,也称 串行通信接口或 串行通讯接口(通常指 COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface) 是指数据一位一位地顺序传送,其特点是 通信线路简单,只要一对传输线就可以实
2020-04-12
  目录