stm32h7 串口idle_【STM32H7教程】第30章 STM32H7的USART应用之八个串口FIFO实现

本章节详细介绍了STM32H743XIH6微控制器的8个串口FIFO驱动设计,包括硬件配置、串口初始化、中断服务程序及FIFO框架。讲解了如何利用串口FIFO实现RS232通信,并提供了初始化代码和实验例程,适用于ESP8266、GPS、RS485、GPRS等应用场景。
摘要由CSDN通过智能技术生成

第30章       STM32H7的USART应用之八个串口FIFO实现

本章节为大家讲解STM327的8个串口的FIFO驱动实现,后面的ESP8266,GPS,RS485,GPRS等试验都是建立在这个驱动的基础上实现。

除了串口FIFO的驱动实现,RS232通信也通过本章节做个讲解。

30.1 初学者重要提示

30.2 硬件设计

30.3 串口驱动设计

30.4 串口FIFO板级支持包(bsp_uart_fifo.c)

30.5 串口FIFO驱动移植和使用

30.6 实验例程设计框架

30.7 实验例程说明(MDK)

30.8 实验例程说明(IAR)

30.9 总结

30.1 初学者重要提示

学习本章节前,务必优先学习第29章。

串口FIFO的实现跟前面章节按键FIFO的机制是一样的。

本章节比较重要,因为后面的ESP8266,GPS,RS485,GPRS等试验都是建立在这个驱动的基础上实现。

大家自己做的板子,测试串口收发是乱码的话,重点看stm32h7xx_hal_conf.h文件中的HSE_VALUE的大小跟板子上实际晶振大小是否一致,然后再看PLL配置。

CH340/CH341的USB转串口Windows驱动程序的安装包,支持32/64位 Windows 10/8.1/8/7。http://www.armbbs.cn/forum.php?mod=viewthread&tid=32826 。

30.2 硬件设计

STM32H743XIH6最多可以支持8个独立的串口。其中串口4和串口5和SDIO的GPIO是共用的,也就是说,如果要用到SD卡,那么串口4和串口5将不能使用。串口7和SPI3共用,串口8和RGB硬件接口共用。串口功能可以分配到不同的GPIO。我们常用的引脚分配如下:

串口USART1  TX = PA9,   RX = PA10

串口USART2  TX = PA2,   RX = PA3

串口USART3  TX = PB10,  RX = PB11

串口UART4   TX = PC10,  RX = PC11 (和SDIO共用)

串口UART5   TX = PC12,  RX = PD2  (和SDIO共用)

串口USART6  TX = PG14,  RX = PC7

串口UART7   TX = PB4,   RX = PB3  (和SPI1/3共用)

串口UART8   TX = PJ8,   RX =PJ9   (和RGB硬件接口共用)

STM32-V7开发板使用了4个串口设备。

串口1用于RS232接口,很多例子的pritnf结果就是输出到串口1

串口2用于GPS

串口3用于RS485接口

串口6 用于TTL串口插座,板子上有GPRS插座和串口WIFI插座。

下面是RS232的原理图:

36483f8c92d6d1c8def5fbf6290c292c.png

关于232的PHY芯片SP3232E要注意以下几个问题:

SP3232E的作用是TTL电平转RS232电平。

电阻R130的作用是避免CPU复位期间,TX为高阻时串口线上出现异常数据。

检测SP3232E的好坏可以采用回环的方式,即短接T1OUT和R1IN,对应到DB9插座上就是短接引脚2和引脚3。

c3e8583420b32fb92a80f6393d4c615a.png

实际效果如下:

36e5d8a9d7422a0fabe1cd81b06a2cd4.png

通过这种方式,可以在应用程序中通过串口发送几个字符,查看是否可以正确接收来判断232 PHY芯片是否有问题。

由于这里是TTL转RS232,如果电脑端自带DB9串口,可以找根交叉线直接接上。如果电脑端没有,就需要用RS232转USB的串口线。这里要注意是RS232转USB,不是TTL转USB。像我们用的CH340就是RS232转USB芯片。

检测串口线的好坏跟板子上的232 PHY一样,将电脑端的串口助手打开,串口线接到电脑端并短接串口线的2脚和3脚,然后使用串口助手进行自收发测试即可。

30.3 串口FIFO驱动设计

30.3.1 串口FIFO框架

为了方便大家理解,先来看下串口FIFO的实现框图:

5467a18c32619fc65bec1bc9e4452899.png

第1阶段,初始化:

通过函数bsp_InitUart初始化串口结构体,串口硬件参数。

第2阶段,串口中断服务程序:

接收中断是一直开启的。

做了发送空中断和发送完成中断的消息处理。

第3阶段,串口数据的收发:

串口发送函数会开启发送空中断。

串口接收中断接收到函数后,可以使用函数comGetChar获取数据。

30.3.2 串口FIFO之相关的变量定义

串口驱动的核心文件为:bsp_uart_fifo.c, bsp_uart_fifo.h。

这里面包括有串口硬件的配置函数、中断处理函数,以及串口的读写接口函数。还有ptinft函数的实现。

每个串口都有2个FIFO缓冲区,一个是用于发送数据的TX_FIFO,一个用于保存接收数据的RX_FIFO。

我们来看下这个FIFO的定义,在bsp_uart_fifo.h文件。

/*定义串口波特率和FIFO缓冲区大小,分为发送缓冲区和接收缓冲区, 支持全双工*/

#if UART1_FIFO_EN == 1

#define UART1_BAUD 115200

#define UART1_TX_BUF_SIZE 1*1024

#define UART1_RX_BUF_SIZE 1*1024

#endif

/*串口设备结构体*/typedefstruct{

USART_TypeDef*uart; /*STM32内部串口设备指针*/uint8_t*pTxBuf; /*发送缓冲区*/uint8_t*pRxBuf; /*接收缓冲区*/uint16_t usTxBufSize;/*发送缓冲区大小*/uint16_t usRxBufSize;/*接收缓冲区大小*/__IO uint16_t usTxWrite;/*发送缓冲区写指针*/__IO uint16_t usTxRead;/*发送缓冲区读指针*/__IO uint16_t usTxCount;/*等待发送的数据个数*/__IO uint16_t usRxWrite;/*接收缓冲区写指针*/__IO uint16_t usRxRead;/*接收缓冲区读指针*/__IO uint16_t usRxCount;/*还未读取的新数据个数*/

void (*SendBefor)(void); /*开始发送之前的回调函数指针(主要用于RS485切换到发送模式)*/

void (*SendOver)(void); /*发送完毕的回调函数指针(主要用于RS485将发送模式切换为接收模式)*/

void (*ReciveNew)(uint8_t _byte); /*串口收到数据的回调函数指针*/uint8_t Sending;/*正在发送中*/}UART_T;

bsp_uart_fifo.c文件定义变量。我们以串口1为例,其他的串口都是一样的代码。

/*定义每个串口结构体变量*/

#if UART1_FIFO_EN == 1

staticUART_T g_tUart1;static uint8_t g_TxBuf1[UART1_TX_BUF_SIZE]; /*发送缓冲区*/

static uint8_t g_RxBuf1[UART1_RX_BUF_SIZE]; /*接收缓冲区*/

#endif

关于FIFO的机制,我们在按键FIFO驱动已经做过详细的介绍,这个地方就不赘述了。每个串口有两个FIFO缓冲区,每个FIFO对应一个写指针和一个读指针。这个结构中还有三个回调函数。回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

30.3.3 串口FIFO初始化

串口的初始化代码如下;

/**********************************************************************************************************

* 函 数 名: bsp_InitUart

* 功能说明: 初始化串口硬件,并对全局变量赋初值.

* 形 参: 无

* 返 回 值: 无

**********************************************************************************************************/

void bsp_InitUart(void)

{

UartVarInit();/*必须先初始化全局变量,再配置硬件*/InitHardUart();/*配置串口的硬件参数(波特率等)*/RS485_InitTXE();/*配置RS485芯片的发送使能硬件,配置为推挽输出*/}

下面将初始化代码实现的功能依次为大家做个说明。

函数UartVarInit

这个函数实现的功能比较好理解,主要是串口设备结构体变量的初始化,代码如下:

/**********************************************************************************************************

* 函 数 名: UartVarInit

* 功能说明: 初始化串口相关的变量

* 形 参: 无

* 返 回 值: 无

**********************************************************************************************************/

static void UartVarInit(void)

{#if UART1_FIFO_EN == 1g_tUart1.uart= USART1; /*STM32 串口设备*/g_tUart1.pTxBuf= g_TxBuf1; /*发送缓冲区指针*/g_tUart1.pRxBuf= g_RxBuf1; /*接收缓冲区指针*/g_tUart1.usTxBufSize= UART1_TX_BUF_SIZE; /*发送缓冲区大小*/g_tUart1.usRxBufSize= UART1_RX_BUF_SIZE; /*接收缓冲区大小*/g_tUart1.usTxWrite= 0; /*发送FIFO写索引*/g_tUart1.usTxRead= 0; /*发送FIFO读索引*/g_tUart1.usRxWrite= 0; /*接收FIFO写索引*/g_tUart1.usRxRead= 0; /*接收FIFO读索引*/g_tUart1.usRxCount= 0; /*接收到的新数据个数*/g_tUart1.usTxCount= 0; /*待发送的数据个数*/g_tUart1.SendBefor= 0; /*发送数据前的回调函数*/g_tUart1.SendOver= 0; /*发送完毕后的回调函数*/g_tUart1.ReciveNew= 0; /*接收到新数据后的回调函数*/g_tUart1.Sending= 0; /*正在发送中标志*/

#endif

/*串口2-8的初始化省略未写*/}

函数InitHardUart

此函数主要用于串口的GPIO,中断和相关参数的配置。

1. /*串口1的GPIO PA9, PA10 RS323 DB9接口*/

2. #define USART1_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()

3.4. #define USART1_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()

5. #define USART1_TX_GPIO_PORT GPIOA

6. #define USART1_TX_PIN GPIO_PIN_9

7. #define USART1_TX_AF GPIO_AF7_USART1

8.9. #define USART1_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()

10. #define USART1_RX_GPIO_PORT GPIOA

11. #define USART1_RX_PIN GPIO_PIN_10

12. #define USART1_RX_AF GPIO_AF7_USART1

13.14. /*串口2-8的引脚和时钟宏定义未写*/

15.16. /*17. ******************************************************************************************************

18. * 函 数 名: InitHardUart

19. * 功能说明: 配置串口的硬件参数(波特率,数据位,停止位,起始位,校验位,中断使能)适合于STM32-H7开

20. * 发板

21. * 形 参: 无

22. * 返 回 值: 无

23. ******************************************************************************************************

24.*/

25. static void InitHardUart(void)26. {27. GPIO_InitTypeDef GPIO_InitStruct;28. RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;29.30. /*31. 下面这个配置可以注释掉,预留下来是为了方便以后选择其它时钟使用

32. 默认情况下,USART1和USART6选择的PCLK2,时钟100MHz。

33. USART2,USART3,UART4,UART5,UART6,UART7和UART8选择的时钟是PLCK1,时钟100MHz。

34.*/

35. RCC_PeriphClkInit.PeriphClockSelection =RCC_PERIPHCLK_USART16;36. RCC_PeriphClkInit.Usart16ClockSelection =RCC_USART16CLKSOURCE_D2PCLK2;37. HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);38.39. #if UART1_FIFO_EN == 1 /* 串口1 */

40. /*使能 GPIO TX/RX 时钟*/

41. USART1_TX_GPIO_CLK_ENABLE();42. USART1_RX_GPIO_CLK_ENABLE();43.44. /*使能 USARTx 时钟*/

45. USART1_CLK_ENABLE();46.47. /*配置TX引脚*/

48. GPIO_InitStruct.Pin =USART1_TX_PIN;49. GPIO_InitStruct.Mode =GPIO_MODE_AF_PP;50. GPIO_InitStruct.Pull =GPIO_PULLUP;51. GPIO_InitStruct.Speed =GPIO_SPEED_FREQ_VERY_HIGH;52. GPIO_InitStruct.Alternate =USART1_TX_AF;53. HAL_GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStruct);54.55. /*配置RX引脚*/

56. GPIO_InitStruct.Pin =USART1_RX_PIN;57. GPIO_InitStruct.Alternate =USART1_RX_AF;58. HAL_GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStruct);59.60. /*配置NVIC the NVIC for UART*/

61. HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);62. HAL_NVIC_EnableIRQ(USART1_IRQn);63.64. /*配置波特率、奇偶校验*/

65. bsp_SetUartParam(USART1, UART1_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);66.67. SET_BIT(USART1->ICR, USART_ICR_TCCF); /*清除TC发送完成标志*/

68. SET_BIT(USART1->RQR, USART_RQR_RXFRQ); /*清除RXNE接收标志*/

69. //USART_CR1_PEIE | USART_CR1_RXNEIE

70. SET_BIT(USART1->CR1, USART_CR1_RXNEIE); /*使能PE. RX接受中断*/

71. #endif

72. /*串口2-8的初始化省略未写*/

73. }

第2-12行,以宏定义的方式设置串口1-8的GPIO时钟、引脚和串口时钟,方便修改。

第35-37行ÿ

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值