11-CubeMx+Keil+Proteus仿真STM32 - 串口单字节通信

本文例子参考《STM32单片机开发实例——基于Proteus虚拟仿真与HAL/LL库》
源代码:https://github.com/LanLinnet/STM32F103R6

项目要求

实现通过串口助手发送单字节数据,单片机收到数据后,交换高4位与低4位,将新的数据通过串口发回串口助手。例如,串口助手发送数据“AB”,单片机返回数据“BA”。

硬件设计

  1. 第一节的基础上,在Proteus中添加电路如下图所示。其中我们添加了:串口组件COMPIM,用于连接计算机虚拟串口;

    一个虚拟仪器VIRTUAL TERMINAL,用来查看单片机收到的串口数据。

    由于要实现串口通信,我们要将其波特率、字长、校验方式、停止位等都设置一下,具体参数如下图所示,相关内容的解释会在下文中进行。
    COMPIM设置

    VIRTUAL TERMINAL设置

    现实中,STM32单片机串口通信采用TTL电平,高电平+3.3V代表逻辑“1”,低电平0V代表逻辑“0”。而RS232标准规定-15V~-3V代表逻辑“1”,+3V~15V代表逻辑“0”,虽然与单片机串口通信逻辑一致,但是逻辑电平不匹配,需要进行电平转换。通常我们使用MAX232芯片设计电平转换电路。不过此处我们使用Proteus进行仿真,可以省略这一步骤(COMPIM带有电平转换功能)。

  2. 串口通信简介:计算机系统内部,计算机与外设之间若要进行数据交换,则必须使用通信技术。
    1)通信的基本方式有并行通信和串行通信两种:并行通信数据传送速率快,但需要耗费较多的数据线;串行通信只需要一对数据线,但传输速率较慢。
    2)异步通信与同步通信:在异步通信中,数据通常以字节为最小单位组成数据帧传送,数据帧按照固定波特率通过发送端逐帧发送,接收端则逐帧接收。异步通信发送端与接收端采用不同的时钟信号,一般来说,只要发送端和接收端的波特率误差相差不超过1%就可以顺利通信。同步通信与异步通信相比对双方时钟要求更高。
    3)数据传输模式:单工模式、半双工模式、全双工模式。
    本次项目中,我们采用串行异步通信方式。

  3. 由于我们采用仿真的方式进行,还需要下载两个软件进行串口的模拟和串口的调试。
    Visual Serial Port Driver(简称VSPD),可在官网中进行下载。

    串口调试助手,我在论坛中下载(首次可能需要注册),也可自行寻找下载。

  4. 打开VSPD,点击“Add Pair”添加一对虚拟串口,这里添加的是COM3COM4,二者互相收发数据。

    添加后可以在计算机的“设备管理器”中查看到虚拟串口如下,这里我们将单片机的串口设置为COM3,串口调试助手的串口设置为COM4。

  5. 打开CubeMX,建立工程。点击“Connectivity”列表中的“USART”进行串口配置。将Mode设置为Asynchronous(异步),波特率设为19200Bits/s,字长设为8Bits,校验设为None,停止位设为1,数据传送设为Receive and Transmit(接收与发送)。设置完成后,会看到右侧的PA9和PA10引脚被自动设置为USART1_TXUSART1_RX,即USART1的发送端和接收端。

    随后,再点击“NVIC Settings”,选中“USART global interrupt”,使能“Enabled”串口1的中断功能。

  6. 点击“Generator Code”生成Keil工程。

软件编写

  1. 本次我们需要实现串口助手发送单字节数据,单片机收到数据后交换高低4位,将新的数据通过串口发回串口助手,需要用到串口相关函数其API文档如下:
    HAL_UART_Receive_IT 串口中断接收设定函数,该函数再每次接收前都需要调用一次

    HAL_UART_Transmit 串口数据发送函数

    HAL_UART_RxCpltCallback 串口接收完毕回调函数

  2. 点击“Open Project”在Keil中打开工程,双击“main.c”文件。

  3. 首先我们需要在main.c文件中设置两个全局变量,一个用于代表接收完毕的标志位,一个用于存放接收数据的数组。

    /* USER CODE BEGIN PV */
    uint8_t rf = 0;  //接收完毕标志位
    uint8_t dat[1] = {0xab};  //用于存放接收数据的数组
    /* USER CODE END PV */
    

    然后,在main函数中中插入代码如下,打开串口1接收中断

    /* USER CODE BEGIN 2 */
    //打开串口1接收中断,接收数据存入dat数组,数组长度为1
    HAL_UART_Receive_IT(&huart1, dat, 1);
    /* USER CODE END 2 */
    

    随后,在/* USER CODE BEGIN 4 *//* USER CODE END 4 */中插入接收完毕回调函数代码如下

    /* USER CODE BEGIN 4 */
    //接收完毕回调函数
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
      if(huart==&huart1)  //如果串口接收中断完毕
      {
        rf = 1;  //接收完毕,标志位置1
      }
    }
    /* USER CODE END 4 */
    

    最后,在while(1)中插入代码如下,进行高低4位的交换

    /* USER CODE BEGIN WHILE */
    while (1)
    {
      uint8_t x;  //中间变量x
      if(rf==1)   //若接收完成
      {
        rf = 0;        //将标志位清0
        x = dat[0];    //将接收的数据存入中间变量x
        dat[0]=(x<<4)|(x>>4);  //高低4位互换
        HAL_UART_Transmit(&huart1, dat, 1, 1);	//由串口1发送存储在dat数组中的数据包,数组长度为1,超时1ms
        HAL_UART_Receive_IT(&huart1, dat, 1);	//接收前每次都需调用该函数
      }
    /* USER CODE END WHILE */
    
    /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
    

联合调试

  1. 点击运行,生成HEX文件。

  2. 在Proteus中加载相应HEX文件,点击运行。

  3. 打开串口调试助手“XCOM”,选择COM4,设置相应的波特率、停止位、数据位、奇偶校验等,勾选“16进制显示”和“16进制发送”,点击“打开串口”。在发送框输入“AB”,点击“发送”。在Proteus中我们可以看到“VIRTUAL TERMINAL”接收到数据“AB”。同时再观察串口调试助手“XCOM”,可以看到接收窗口收到高低4位互换的数据“BA”。

注意

如果你发送“AB”1个字节,接收到的却有多个字节:


因为0x0D、0x0A代表的分别是回车符号和换行符号,请查看是否在串口调试助手“XCOM”中勾选了“发送新行”,取消勾选即可。

posted @ 2022-05-16 09:54  Sheepeach  阅读(5496)  评论(1编辑  收藏  举报