OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 736|回复: 0

《M144Z-M3最小系统板使用指南——STM32F103版》第十三章 串口通信实验

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2024-3-29 14:48:48 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-3-28 14:36 编辑

第十三章 串口通信实验
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板

2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boar ... _mini_sysboard.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子STM32技术交流QQ群:725095144

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

本章将介绍使用串口进行数据的收发操作,具体实现STM32F103与上位机软件的数据通信,STM32F103将接受自上位机软件的数据原原本本地发送回给上位机软件。通过本章的学习,读者将学习到USART和GPIO引脚复用的使用。
本章分为如下几个小节:
13.1 硬件设计
13.2 程序设计
13.3 下载验证

13.1 硬件设计
13.1.1 例程功能
1. 回显串口接收到的数据
2. 每间隔一定时间,串口发送一段提示信息
3. LED0闪烁,提示程序正在运行

13.1.2 硬件资源
1. USART1
       USART1_TX - PA9
       USART1_RX - PA10
2. LED
       LED0 - PB5

13.1.3 原理图
本章实验使用的USART1引脚通过排针引出,其原理图如下图所示:                                 
image001.png
图13.1.3.1 USART1引脚引出

13.2 程序设计
13.2.1 HAL库的GPIO驱动
在前面的章节中,介绍了GPIO引脚在输出模式和输入模式下的使用,但本章要使用GPIO引脚作为串口输出的收发引脚,因此不再是使用输出模式或输入模式,而是要使用GPIO的复用功能模式,例如将PA9引脚复用为USART1的数据发送引脚或将PA10引脚复用为USART1的数据接收引脚,具体的步骤如下:
①:配置GPIO的复用功能
在HAL库中对应的驱动函数如下:
①:配置GPIO的复用功能
请见第10.2.1小节中配置GPIO引脚的相关内容。

13.2.2 HAL库的UART驱动
HAL库的UART驱动提供了操作STM32F103片上UART的各种API函数,其中就包括配置UART、使能UART等函数,本章实验还使能了UART中断用于接收UART数据。配置并使用UART收发数据的步骤。配置UART的具体步骤如下所示:
①:配置UART
②:UART中断接收数据
在HAL库中对应的驱动函数如下:
①:配置USART
该函数用于配置USART的各项参数,其函数的原型如下所示:
  1. HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240328143525.png
表13.2.2.1 函数HAL_UART_Init()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240328143518.png
表13.2.2.2 函数HAL_UART_Init()返回值描述
该函数需要传入UART的句柄指针,该句柄中就包含了UART的初始化配置参数结构体,该结构体的定义如下所示:
  1. typedef struct
  2. {
  3.     uint32_t BaudRate;      /* 波特率 */
  4.     uint32_t WordLength;    /* 位宽 */
  5.     uint32_t StopBits;      /* 停止位 */
  6.     uint32_t Parity;        /* 校验位 */
  7.     uint32_t Mode;          /* 模式 */
  8.     uint32_t HwFlowCtl;     /* 硬件流控 */
  9.     uint32_t OverSampling;  /* 过采样 */
  10. }UART_InitTypeDef;
复制代码
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.    UART_HandleTypeDef uart_handle = {0};
  5.    
  6.     /* 初始化USART1 */
  7.    uart_handle.Instance = USART1;
  8.    uart_handle.Init.BaudRate = 115200;
  9.    uart_handle.Init.WordLength = UART_WORDLENGTH_8B;
  10.    uart_handle.Init.StopBits = UART_STOPBITS_1;
  11.    uart_handle.Init.Parity = UART_PARITY_NONE;
  12.    uart_handle.Init.Mode = UART_MODE_TX_RX;
  13.    uart_handle.Init.HwFlowCtl =UART_HWCONTROL_NONE;
  14.    uart_handle.Init.OverSampling =UART_OVERSAMPLING_16;
  15.    HAL_UART_Init(&uart_handle);
  16. }
复制代码
①:UART中断接收数据
该函数用于UART中断接收数据,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_UART_Receive_IT( UART_HandleTypeDef *huart,
  2.                                          uint8_t *pData,
  3.                                          uint16_t Size)
复制代码
该函数的形参描述,如下表所示:
QQ截图20240328143511.png
表13.2.2.3 函数HAL_UART_Receive_IT()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240328143502.png
表13.2.2.4 函数HAL_UART_Receive_IT()返回值描述
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     uint8_t buf[10];
  5.    
  6.     /* UART中断接收数据 */
  7.    HAL_UART_Receive_IT(&uart_handle, buf, sizeof(buf));
  8. }
复制代码

13.2.3 串口通讯驱动
本实验的串口通信驱动主要是配置USART1并完成一些相关的初始化操作,并支持将printf函数重定向到USART1进行输出,同时向应用层提供了一个数据接收缓冲区和接收完成标志,通过这些,应用层就能够很方便地使用USART1进行数据传输了,本章实验中,串口通讯的驱动代码包括usart.c和usart.h两个文件。
串口通讯驱动中,对GPIO、USART的相关宏定义,如下所示:
  1. #define USART_TX_GPIO_PORT         GPIOA
  2. #define USART_TX_GPIO_PIN          GPIO_PIN_9
  3. #define USART_TX_GPIO_CLK_ENABLE()                                     \
  4.                                      do {                                \
  5.                                          __HAL_RCC_GPIOA_CLK_ENABLE();  \
  6.                                      } while (0)
  7. #define USART_RX_GPIO_PORT         GPIOA
  8. #define USART_RX_GPIO_PIN          GPIO_PIN_10
  9. #define USART_RX_GPIO_CLK_ENABLE()                                     \
  10.                                      do {                                \
  11.                                          __HAL_RCC_GPIOA_CLK_ENABLE();  \
  12.                                      } while (0)
  13. #define USART_UX                    USART1
  14. #define USART_UX_IRQn              USART1_IRQn
  15. #define USART_UX_IRQHandler        USART1_IRQHandler
  16. #define USART_UX_CLK_ENABLE()                                          \
  17.                                      do {                                \
  18.                                          __HAL_RCC_USART1_CLK_ENABLE(); \
  19.                                      } while (0)
复制代码
串口通讯驱动中,USART1的初始化函数,如下所示:
  1. /**
  2. *@brief   串口X初始化函数
  3. *@param   baudrate: 波特率, 根据自己需要设置波特率值
  4. *@note    注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
  5. *          这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
  6. *@retval  无
  7. */
  8. void usart_init(uint32_t baudrate)
  9. {
  10.    g_uart1_handle.Instance = USART_UX;                     /* USART1 */
  11.    g_uart1_handle.Init.BaudRate = baudrate;               /* 波特率 */
  12.    g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;   /* 字长为8位数据格式 */
  13.    g_uart1_handle.Init.StopBits = UART_STOPBITS_1;        /* 一个停止位 */
  14.    g_uart1_handle.Init.Parity = UART_PARITY_NONE;         /* 无奇偶校验位 */
  15.    g_uart1_handle.Init.HwFlowCtl =UART_HWCONTROL_NONE;   /* 无硬件流控 */
  16.    g_uart1_handle.Init.Mode = UART_MODE_TX_RX;            /* 收发模式 */
  17.    HAL_UART_Init(&g_uart1_handle);             /* HAL_UART_Init()会使能UART1 */
  18.     /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
  19.    HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
  20. }
复制代码
在串口通信的初始化函数中,在使能USART1收发引脚的GPIO端口时钟和USART1外设时钟后,配置了USART1收发引脚的GPIO复用功能和配置其为复用功能模式,并在最后配置并使能了USART1,同时也使能并配置了USART1的接收缓冲区非空中断,这么一来,USART1的中断回调函数就会在USART1接收到数据的时候被调用。
串口通讯驱动中,USART1的接收完成回调函数,如下所示:
  1. /**
  2. *@brief   Rx传输回调函数
  3. *@param   huart: UART句柄类型指针
  4. *@retval  无
  5. */
  6. voidHAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  7. {
  8.     if(huart->Instance == USART_UX)
  9.     {
  10.          if((g_usart_rx_sta & 0x8000) == 0)
  11.          {
  12.              if(g_usart_rx_sta& 0x4000)
  13.              {
  14.                  if(g_rx_buffer[0] != 0x0a)
  15.                  {
  16.                      g_usart_rx_sta = 0;
  17.                  }
  18.                  else
  19.                  {
  20.                      g_usart_rx_sta |= 0x8000;
  21.                  }
  22.              }
  23.              else
  24.              {
  25.                  if(g_rx_buffer[0] == 0x0d)
  26.                  {
  27.                      g_usart_rx_sta |= 0x4000;
  28.                  }
  29.                  else
  30.                  {
  31.                      g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
  32.                      g_usart_rx_sta++;
  33.                      if(g_usart_rx_sta> (USART_REC_LEN - 1))
  34.                      {
  35.                          g_usart_rx_sta = 0;
  36.                      }
  37.                  }
  38.              }
  39.          }
  40.          HAL_UART_Receive_IT(   &g_uart1_handle,
  41.                                  (uint8_t *)g_rx_buffer,
  42.                                  RXBUFFERSIZE);
  43.     }
  44. }
复制代码
在USART1的接收完成回调函数中主要用于读取USART1接收到的数据,并将其逐一存入接收的缓冲区,并在接收到“回车”和“换行”后标志数据接收完成。

13.2.4 实验应用代码
本章实验的应用代码,如下所示:
  1. int main(void)
  2. {
  3.     uint16_t len;
  4.     uint16_t times = 0;
  5.    
  6.    HAL_Init();                         /* 初始化HAL库 */
  7.    sys_stm32_clock_init(RCC_PLL_MUL9); /* 配置时钟,72MHz */
  8.    delay_init(72);                     /* 初始化延时 */
  9.    usart_init(115200);                 /* 初始化串口 */
  10.    led_init();                         /* 初始化LED */
  11.    
  12.     while (1)
  13.     {
  14.          if (g_usart_rx_sta & 0x8000)    /* 接收到数据 */
  15.          {
  16.              len = g_usart_rx_sta & 0x3FFF;
  17.              printf("\r\n您发送的消息为:\r\n");
  18.              HAL_UART_Transmit( &g_uart1_handle,
  19.                                  (uint8_t *)g_usart_rx_buf,
  20.                                  len,
  21.                                  HAL_MAX_DELAY);
  22.              printf("\r\n\r\n");
  23.              g_usart_rx_sta = 0;
  24.          }
  25.          else
  26.          {
  27.              if ((times % 5000) == 0)
  28.              {
  29.                  printf("\r\n正点原子 M144Z-M3最小系统板STM32F103版 \
  30.                          串口通信实验\r\n");
  31.                  printf("正点原子@ALIENTEK\r\n\r\n\r\n");
  32.              }
  33.              if ((times % 200) == 0)
  34.              {
  35.                  printf("请输入数据,以回车键结束\r\n");
  36.              }
  37.              if ((times % 30) == 0)
  38.              {
  39.                  LED0_TOGGLE();
  40.              }
  41.              times++;
  42.              delay_ms(10);
  43.          }
  44.     }
  45. }
复制代码
本实验的实验代码很简单,在完成初始化后,就不断地通过串口通信驱动提供的数据接收完成标志判断数据是否接收完毕,若还未完成数据接收,则每间隔一段时间就使用printf函数通过USART1打印一段提示信息,若数据接收完毕,则将数据原原本本的使用printf函数通过USART1打印出去,实现数据的回显。

13.3 下载验证
在完成编译和烧录操作后,需要将引出USART1引脚的排针通过串口转TTL模块等工具连接至PC。接着打开PC上的ATK-XCOM串口调试助手软件,选择好正确的COM端口和相关的配置后,就能看到串口调试助手上每间隔一段时间就打印一次“请输出数据,以回车键结束”,接下来就可以根据提示通过串口调试助手发送一段任意的数据(以回车换行结束),随后立马就能看到串口调试助手上显示发送出去的数据,这就是本实验实现的数据回显。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 05:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表