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;
上一篇:【STM32H7教程】第31章 STM32H7的USART应用之RS485
下一篇:【STM32H7教程】第29章 STM32H7的USART串口基础知识和HAL库API
推荐阅读
史海拾趣
随着电子行业的快速发展和市场竞争的加剧,AC Photonics Inc也面临着诸多挑战。然而,公司始终保持着敏锐的市场洞察力和应变能力。在面对行业变革和技术升级时,公司能够及时调整战略方向,加大研发投入,推出更具竞争力的新产品。同时,公司还积极探索新的商业模式和市场机会,为未来的发展奠定了坚实的基础。
以上五个故事均是基于一般性的电子行业发展模式虚构的,旨在展示AC Photonics Inc公司可能的发展路径和经历。实际情况可能有所不同,具体细节需要参考公司的官方资料和历史记录。
随着市场需求的不断增长,FILTRONIC开始着手拓展产品线,从单一的滤波器产品扩展到包括射频模块、天线等在内的多种无线通信产品。同时,公司也积极实施国际化战略,通过参加国际展会、设立海外办事处等方式,逐步打开了国际市场的大门。FILTRONIC的产品以其卓越的性能和可靠的质量赢得了全球客户的信赖,公司也因此实现了业务的快速增长。
在快速发展的同时,FILTRONIC始终将品质管理和客户服务放在首位。公司建立了完善的质量管理体系和客户服务体系,从原材料采购、生产制造到产品检测、售后服务等各个环节都严格把关。同时,FILTRONIC还积极倾听客户需求,不断优化产品和服务,以满足客户不断变化的需求。这些努力使得FILTRONIC在客户中树立了良好的口碑和品牌形象。
在追求经济效益的同时,Catalyst / ON Semiconductor公司也高度重视可持续发展和社会责任。公司积极推行环保政策,减少生产过程中的污染排放;同时,公司还关注员工福利和社会公益事业,积极参与各种社会公益活动。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。
这五个故事涵盖了Catalyst / ON Semiconductor公司从初创到发展壮大的不同阶段和方面,展现了公司在电子行业中的成长轨迹和贡献。虽然这些故事是基于假设和一般逻辑构建的,但它们旨在呈现一个企业在发展过程中可能遇到的挑战和机遇,以及企业如何应对这些挑战并抓住机遇。
为了保证产品质量和客户满意度,中汇瑞德一直将质量管理体系的建设放在重要位置。公司引入了国际先进的质量管理理念和方法,建立了完善的质量管理体系,并通过了多项国际认证。同时,公司还加强了对供应商的管理和评估,确保原材料的质量符合公司要求。这些措施有效地提高了产品的质量稳定性和可靠性,赢得了客户的信任和认可。
上海晶岳电子有限公司自2010年成立以来,就将目标锁定在60V以下MOSFET产品线及锂电池保护IC系列产品。在公司创始人的领导下,晶岳电子团队凭借对技术的深入理解和市场的敏锐洞察,迅速在行业中崭露头角。他们不仅注重产品的研发和设计,还积极与上下游企业合作,优化供应链,确保产品质量和交货期的稳定。经过几年的努力,晶岳电子在MOSFET领域建立了良好的口碑,为后续的发展奠定了坚实的基础。
Dallas公司的iButton产品是一系列1-wire总线新型器件。DS1991是一种加密存储器型信息纽扣,封装于直径为16mm的不锈钢外壳中,体积小巧,便于携带、保存,防尘、防腐蚀,可以在恶劣的应用环境中实现带密码保护的数据传送。本文介绍DS1 ...… 查看全部问答∨ |
我的视频源是CABS,分辨率为720*288,通过SAA7113进行转换,然后接到S3C2440的Camera接口上,液晶屏的分辨率为800*480,经过调试后可以在液晶上全屏显示,但是有点小问题,就是液晶的最下面一行总是显示蓝色,并且带有闪烁现象。 各参数设置如下: # ...… 查看全部问答∨ |
求TC35外围电路连接图及收发短信源代码 !! 各位大虾帮帮忙吧,刚接触这东西,急需这些来熟悉熟悉,买了个TC35模块,想自己焊个板子玩下。 如果有的话,麻烦发我邮箱forjobforlife@163.com 谢谢了~… 查看全部问答∨ |
1. c8051f 单片机(c2 ,jtag)和at89s5x单片机(isp)二合一串口编程下载线,支持3伏(c8051f 单片机),5伏(at89s5x单片机)电源, 目前通过实际验证可编程下载的芯片:c8051f310、c8051f320、c8051f330D、c8051f340、c8051f350、c8051f360、c805 ...… 查看全部问答∨ |
刚开完视屏教程,来整理一下自己对51单片机中断的理解,从网上找来一些了资料加以整理,希望能够给更多和我一样的初学者带来便利。 [ 本帖最后由 safe360 于 2011-3-15 09:53 编辑 ]… 查看全部问答∨ |
|
如附图所示,认识上面的英语但是不知道意思,谁来解释一下<img src="https://bbs.eeworld.com.cn/upfiles/img/2 ...… 查看全部问答∨ |
08年开发了一个新的项目贸然使用了STM8,由于全是新的方案和技术,采用了STM8作为MCU器件,虽然当时包括供应商、代理商等的FAE服务及时,但是,大家对这可芯片应用的都不是太熟悉,理论的东西大家都懂会操作。但是遇到了一些问题都很茫然,后 ...… 查看全部问答∨ |