历史上的今天

今天是:2024年08月26日(星期一)

正在发生

2019年08月26日 | 【STM32H7教程】第30章 STM32H7的USART应用之八个串口FIFO实现

发布者:as233632621 来源: eefocus关键字:STM32H7  USART应用  串口  FIFO 手机看文章 扫描二维码
随时随地手机看文章

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://forum.armfly.com/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的原理图:


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


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

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

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


实际效果如下:

通过这种方式,可以在应用程序中通过串口发送几个字符,查看是否可以正确接收来判断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的实现框图:


 

  第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

 

/* 串口设备结构体 */

typedef struct

{

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

static UART_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 == 1

g_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行,这里的配置可以注释掉,预留下来仅仅是为了方便以后选择其它时钟使用。默认情况下,USART1和USART6选择的PCLK2,时钟100MHz。USART2,USART3,UART4,UART5,UART6,UART7和UART8选择的时钟是PLCK1,时钟100MHz。

  第61-62行,配置串口中断优先级并使能串口中断,用户可以根据实际工程修改优先级大小。

  第65行,配置串口的基本参数,具体配置在函数里面有注释。

/*

*********************************************************************************************************

* 函 数 名: bsp_SetUartParam

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

* 形    参: Instance   USART_TypeDef类型结构体

*             BaudRate   波特率

*             Parity     校验类型,奇校验或者偶校验

*             Mode       发送和接收模式使能

* 返 回 值: 无

*********************************************************************************************************

*/

void bsp_SetUartParam(USART_TypeDef *Instance,  uint32_t BaudRate, uint32_t Parity, uint32_t Mode)

{

UART_HandleTypeDef UartHandle;

/*##-1- 配置串口硬件参数 ######################################*/

/* 异步串口模式 (UART Mode) */

/* 配置如下:

  - 字长    = 8 位

  - 停止位  = 1 个停止位

  - 校验    = 参数Parity

  - 波特率  = 参数BaudRate

  - 硬件流控制关闭 (RTS and CTS signals) */

 

UartHandle.Instance        = Instance;

 

UartHandle.Init.BaudRate   = BaudRate;

UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

UartHandle.Init.StopBits   = UART_STOPBITS_1;

UartHandle.Init.Parity     = Parity;

UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;

UartHandle.Init.Mode       = Mode;

UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

[1] [2] [3] [4] [5]
关键字:STM32H7  USART应用  串口  FIFO 引用地址:【STM32H7教程】第30章 STM32H7的USART应用之八个串口FIFO实现

上一篇:【STM32H7教程】第31章 STM32H7的USART应用之RS485
下一篇:【STM32H7教程】第29章 STM32H7的USART串口基础知识和HAL库API

推荐阅读

近年来,随着人们消费能力的提升和消费方式的改变,我国电商和快递行业进入高速发展增长期。与此同时,伴随着的是人口红利下降,快递企业不得不面临人工成本高、招工难的现状,这同时也加大了配送的难度。对于快递企业来说,如何解决用工难以及快速解决“最后一公里”末端配送,让快递更快一步到达消费者手中成为痛点问题。 无人机作为物流配送黑科技,和...
全球领先的测试和测量设备管理公司Electro Rent (益莱储) 宣布,继续增加5G测试设备的投资3000万美元,以过去一年3倍的投资扩充其整个5G测试设备库存,以满足设备制造商和移动网络运营商不断增长的需求。 5G新标准相对于其前身的三个关键优势:更快的速率、更低的时延、更广的连接。这些特点都在扩大5G的适用性,从而为制造商打开新的市场机会。例如汽...
根据印度《经济时报》的最新报告,三星正加紧将其生产线的相当大一部分转移到印度。 据知情人士透露,三星已经向印度政府披露了有关生产关联激励(PLI)的计划,并预计未来五年内在印度生产总价值超 400 亿美元的手机,在印度制造的单价在 200 美元以上的大部分手机都将出口。一名消息人士透露:”三星很可能会根据生产关联激励计划,将多条智能手机的...
广告摘要声明广告撰文 | 歌者在2021年小米年度演讲上,一只名为CyberDog(中文名“铁蛋”)四足仿生机器狗引起了广泛关注,有人甚至欢呼“中国年轻人的第一只机器狗,终于来了”。目前,小米正在社区内招募众测,首批开放400个名额以9999元的付费价格购买体验工程探索版铁蛋;截止8月19日已经有超2万人提交了申请。借助小米的品牌影响力和广泛的用户群,...

史海拾趣

问答坊 | AI 解惑

信息纽扣DS1991在单片机系统中的应用

Dallas公司的iButton产品是一系列1-wire总线新型器件。DS1991是一种加密存储器型信息纽扣,封装于直径为16mm的不锈钢外壳中,体积小巧,便于携带、保存,防尘、防腐蚀,可以在恶劣的应用环境中实现带密码保护的数据传送。本文介绍DS1 ...…

查看全部问答∨

ARM_S3C2440的Camera摄像头问题

我的视频源是CABS,分辨率为720*288,通过SAA7113进行转换,然后接到S3C2440的Camera接口上,液晶屏的分辨率为800*480,经过调试后可以在液晶上全屏显示,但是有点小问题,就是液晶的最下面一行总是显示蓝色,并且带有闪烁现象。 各参数设置如下: # ...…

查看全部问答∨

谁有tasking C166啊,给兄弟一个,急需啊,多谢!

谁有tasking C166啊,给兄弟一个,急需啊,多谢! luckytigerwood@yahoo.com.cn…

查看全部问答∨

吃内存的问题!

在OnTimer中实现如下代码: CString sTm; CTime time; time = CTime::GetCurrentTime(); sTm.Format(_T("%d年%d月%d日 %02d:%02d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute()); m_ctrlTime.SetWindo ...…

查看全部问答∨

求TC35外围电路连接图及收发短信源代码 !!

求TC35外围电路连接图及收发短信源代码 !! 各位大虾帮帮忙吧,刚接触这东西,急需这些来熟悉熟悉,买了个TC35模块,想自己焊个板子玩下。 如果有的话,麻烦发我邮箱forjobforlife@163.com 谢谢了~…

查看全部问答∨

我给大家特别推荐的两款产品,非常棒!!!

1. c8051f 单片机(c2 ,jtag)和at89s5x单片机(isp)二合一串口编程下载线,支持3伏(c8051f 单片机),5伏(at89s5x单片机)电源, 目前通过实际验证可编程下载的芯片:c8051f310、c8051f320、c8051f330D、c8051f340、c8051f350、c8051f360、c805 ...…

查看全部问答∨

wince(VS2005,c#) 控件透明怎么实现

wince(VS2005,C#)控件透明怎么实现 我很菜,请说详细点…

查看全部问答∨

中断读书笔记(希望大家看了能给补充一下)

刚开完视屏教程,来整理一下自己对51单片机中断的理解,从网上找来一些了资料加以整理,希望能够给更多和我一样的初学者带来便利。 [ 本帖最后由 safe360 于 2011-3-15 09:53 编辑 ]…

查看全部问答∨

今天把iar4.42的程序移植到iar5.2,多了个提示

                                 如附图所示,认识上面的英语但是不知道意思,谁来解释一下<img src="https://bbs.eeworld.com.cn/upfiles/img/2 ...…

查看全部问答∨

开发了一个新的项目贸然使用了STM8

08年开发了一个新的项目贸然使用了STM8,由于全是新的方案和技术,采用了STM8作为MCU器件,虽然当时包括供应商、代理商等的FAE服务及时,但是,大家对这可芯片应用的都不是太熟悉,理论的东西大家都懂会操作。但是遇到了一些问题都很茫然,后 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved