历史上的今天
返回首页

历史上的今天

今天是:2025年08月05日(星期二)

正在发生

2019年08月05日 | HAL库-STM32F4 UART-IT

2019-08-05 来源:eefocus

注:参考ST公司HAL库附带UART-IT例程。 参考资料:ST-《STM32F4xx中文参考手册》、野火-《零死角玩转STM-F429》


主要数据类型:


UART_HandleTypeDef UartHandle;

主要HAL函数:

初始化函数:

HAL_StatusTypeDef HAL_UART_Init ( UART_HandleTypeDef * huart );

void HAL_UART_MspInit ( UART_HandleTypeDef *huart ) ;

回调函数:

void HAL_UART_TxCpltCallback( UART_HandleTypeDef * UartHandle );

void HAL_UART_RxCpltCallback( UART_HandleTypeDef * UartHandle );


void HAL_UART_ErrorCallback( UART_HandleTypeDef *UartHandle )


操作函数:

HAL_StatusTypeDef HAL_UART_Transmit_IT( UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size );

HAL_StatusTypeDef HAL_UART_Receive_IT( UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size );

中断响应函数:

void USARTx_IRQHandler();



步骤:



1.进行UART外设配置:

UART_HandleTypeDef UartHandle; //全局或在主函数中定义

  UartHandle.Instance          = USARTx; //选择所需端口,例程中将USART1作为UART使用

  

  //以下为示例

UartHandle.Init.BaudRate     = 9600; //波特率设置

UartHandle.Init.WordLength   = UART_WORDLENGTH_8B; //数据长度设置

  UartHandle.Init.StopBits     = UART_STOPBITS_1; //停止位设置

  UartHandle.Init.Parity       = UART_PARITY_NONE; //奇偶校验设置

  UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE; //流控制设置 (RTS以及CTS)

  UartHandle.Init.Mode         = UART_MODE_TX_RX; //模式设置 例程中同时用到收发功能

  UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

 

 

  //使用初始化函数进行配置

  HAL_UART_Init(&UartHandle); //若配置成功,该函数返回值 HAL_OK


       UART_HandleTypeDef 结构体内的成员有许多,但是使用HAL库进行配置则只需要用户设置其中的 Init 成员,其余的由初始化库函数以及操作库函数自行配置完成。

注意,在 HAL_UART_Init 函数结束时则使能了对应UART外设(相应时钟还未使能)



2.进行GPIO、NVIC、相应时钟配置

    在HAL_UART_Init函数中,有语句


if(huart->State == HAL_UART_STATE_RESET)

{  

      /* Allocate lock resource and initialize it */

      huart->Lock = HAL_UNLOCKED;

      /* Init the low level hardware */

      HAL_UART_MspInit(huart);

}


    即若传入的 UART_HandleTypeDef 类型结构体的 State 成员为 HAL_UART_STATE_RESET 状态,则对其解锁限制,然后调用一个WEAK定义的HAL函数

void HAL_UART_MspInit ( UART_HandleTypeDef * huart );

    一般用户可以在外部自行重新定义该函数,用来初始化板载上GPIO的UART复用,以及相应时钟配置、NVIC配置。在例程中便是如此


/**

  * @brief UART MSP Initialization 

  *        This function configures the hardware resources used in this example: 

  *           - Peripheral's clock enable

  *           - Peripheral's GPIO Configuration  

  *           - NVIC configuration for UART interrupt request enable

  * @param huart: UART handle pointer

  * @retval None

  */

void HAL_UART_MspInit(UART_HandleTypeDef *huart)

{  

  GPIO_InitTypeDef  GPIO_InitStruct;

  

  /*##-1- Enable peripherals and GPIO Clocks #################################*/

  /* Enable GPIO TX/RX clock */

  USARTx_TX_GPIO_CLK_ENABLE(); //使能相应使用的Tx引脚GPIO口时钟

  USARTx_RX_GPIO_CLK_ENABLE(); //使能相应使用的Rx引脚GPIO口时钟

  /* Enable USART1 clock */

  USARTx_CLK_ENABLE(); //使能相应UARTUSART时钟

  

  /*##-2- Configure peripheral GPIO ##########################################*/  

  /* UART TX GPIO pin configuration  */

  GPIO_InitStruct.Pin       = USARTx_TX_PIN; //可使用的引脚需要参考手册

  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;

  GPIO_InitStruct.Pull      = GPIO_NOPULL;

  GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;

  GPIO_InitStruct.Alternate = USARTx_TX_AF;

  

  HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);

    

  /* UART RX GPIO pin configuration  */

 

 

  GPIO_InitStruct.Pin = USARTx_RX_PIN; //可使用的引脚需要参考手册

  GPIO_InitStruct.Alternate = USARTx_RX_AF;

    

  HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);

    

  /*##-3- Configure the NVIC for UART ########################################*/

  /* NVIC for USART1 */

  HAL_NVIC_SetPriority(USARTx_IRQn, 0, 1); //配置NVIC优先级

  HAL_NVIC_EnableIRQ(USARTx_IRQn); //使能使用的UARTUSART中断

}


注意:

1.每个 USARTUART 可使用来作为Tx、Rx的引脚是各不相同的,这点需要具体参考手册进行配置

  2.所使用的 USARTUART 时钟以及对应中断需要使能

  3.若程序中使用到了 SysTick,建议将 SysTick 的中断优先级提在USARTUART之前

" The the SysTick interrupt must have higher priority (numerically lower) than the peripheral interrupt. Otherwise the caller ISR process will be blocked. "

  4.如果想要使用 HAL_UART_MspInit 函数来调用板载外设初始化语句,那么应当确保参数的 Status 值



3.收发函数 

    这里是用到的IT方式,故只举例IT方式的库函数。

    HAL_StatusTypeDef HAL_UART_Transmit_IT  ( UART_HandleTypeDef *  huart,uint8_t *  pData,uint16_t  Size ) 

    HAL_StatusTypeDef HAL_UART_Receive_IT   ( UART_HandleTypeDef *  huart,uint8_t *  pData,uint16_t  Size )



    HAL_UART_Transmit_IT 函数为发送函数。在其中自动将奇偶校验错误、帧错误、噪音错误、上溢错误以及数据寄存器( DR )为空 中断使能。

    调用该函数后则将把 pData 所指向的数组中的 Size 个数据发送出去。应当在调用该函数后利用一个循环等待发送完成。可通过判断作为参数传入该函数的 UART_HandleTypeDef 类型结构体的 Status 成员是否为 HAL_UART_STATE_READY 来判断是否发送完成(该成员在刚被该函数调用时被设置为 HAL_UART_STATE_BUSY_TX_RX 或 HAL_UART_STATE_BUSY_TX,在程序运行至 UART_EndTransmit_IT 并发送成功后被设置为 HAL_UART_STATE_READY )

    HAL_UART_Receive_IT  函数为接收函数。在其中自动将奇偶校验错误、帧错误、噪音错误、上溢错误以及数据寄存器( DR )为空 中断使能。

    调用该函数后则将把从端口中接收的 Size 个数据存放到 pData 所指向的数组去。应当在调用该函数后利用一个循环等待接收完成。可通过判断作为参数传入该函数的 UART_HandleTypeDef 类型结构体的 Status 成员是否为 HAL_UART_STATE_READY 来判断是否接收完成(该成员在刚被该函数调用时被设置为 HAL_UART_STATE_BUSY_TX_RX 或 HAL_UART_STATE_BUSY_TX,在程序运行至 UART_Receive_IT 并接收成功后被设置为 HAL_UART_STATE_READY )

PS:DMA方式中相应函数用到了函数指针知识。

    

4.对应中断响应函数以及回调函数

    在这里,主要用到的中断响应函数有 

SysTick_Handler() //Systick计时到点中断

USARTx_IRQHandler() //USART中断 因为我们使用的是USART1,所以是USART中断

    回调函数有

HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle) //发送完成回调函数

HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) //接收完成回调函数

HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle) //错误回调函数



    其中,USARTx_IRQHandler 中断响应函数在 USART 发送、接收、以及错误等时候会响应。使用HAL库,我们可以这样编写该中断响应函数

/* UART handler declared in other file */

extern UART_HandleTypeDef UartHandle;

.

.

.

void USARTx_IRQHandler(void)

{

  HAL_UART_IRQHandler(& UartHandle);

}


    这里,该中断响应函数里面调用了库函数 HAL_UART_IRQHandler 函数,并将我们之前定义的 UART_HandleTypeDef 类型的结构体 UartHandle 的地址作为参数传入。

    在 HAL_UART_IRQHandler 函数里,主要进行了清除错误标志位、记录错误码 (HAL库中定义的 UART Error Code)以及判断是否进入接收( UART_Receive_IT(& UartHandle) )、发送( UART_Transmit_IT(& UartHandle) )、发送结束( UART_EndTransmit_IT(& UartHandle) )以及错误回调函数 (HAL_UART_ErrorCallback(& UartHandle) 函数默认为空,WEAK定义。)。



--------------------------------------------------------------------------------------

    UART Error Code为一系列宏定义


#define  HAL_UART_ERROR_NONE    ((uint32_t)0x00000000) //无

#define  HAL_UART_ERROR_PE    ((uint32_t)0x00000001) //奇偶校验错误

#define  HAL_UART_ERROR_NE    ((uint32_t)0x00000002) //噪声错误

#define  HAL_UART_ERROR_FE    ((uint32_t)0x00000004) //帧错误

#define  HAL_UART_ERROR_ORE    ((uint32_t)0x00000008) //上溢错误

#define  HAL_UART_ERROR_DMA    ((uint32_t)0x00000010) //DMA传输错误


    static HAL_StatusTypeDef UART_Receive_IT  ( UART_HandleTypeDef *  huart ) //接收数据,如果当前端口不忙,接收成功返回 HAL_OK ,否则返回 HAL_BUSY。并且在接受完成后关闭由 HAL_UART_Receive_IT 开启的一系列中断,调用 HAL_UART_RxCpltCallback 函数。默认为空,WEAK定义。


    static HAL_StatusTypeDef UART_Transmit_IT  ( UART_HandleTypeDef *  huart ) //发送数据,如果当前端口不忙,发送成功返回 HAL_OK ,否则返回 HAL_BUSY。


    static HAL_StatusTypeDef UART_EndTransmit_IT  ( UART_HandleTypeDef *  huart ) //结束传输置传入结构体 State 成员为非阻塞状态。并且在完成后关闭由 HAL_UART_Transmit_IT 开启的一系列中断。调用 HAL_UART_TxCpltCallback 函数。默认为空,WEAK定义。



--------------------------------------------------------------------------------------


    以上的都是由 HAL_UART_IRQHandler 函数自动调用配置。


推荐阅读

史海拾趣

Gould Ami公司的发展小趣事
检查水泵电机是否损坏,轴承是否磨损。如有必要,可拆卸水泵进行检修或更换损坏部件。
Arima Lasers Corp公司的发展小趣事

Arima Lasers Corp深知人才是企业发展的核心驱动力。因此,公司高度重视人才培养和团队建设。通过制定完善的培训计划和激励机制,公司吸引了一批批优秀的研发人才和管理人才。这些人才为公司的发展注入了源源不断的动力,推动了公司在技术、市场和管理等各个方面的全面提升。

Excel Cell Electronic Co Ltd公司的发展小趣事

为了拓展海外市场,ECE公司制定了国际化战略。公司积极参与国际电子展会,与国际知名企业建立合作关系,不断提升品牌知名度和国际影响力。同时,ECE公司在海外设立分支机构,加强与国际市场的联系和沟通,进一步拓展市场份额。这些努力使ECE公司的产品成功进入欧洲、北美等发达地区市场,实现了全球化布局。

全鹏(CHAMPION)公司的发展小趣事

为了提升国际市场竞争力,全鹏公司一直致力于提高产品质量和管理水平。在2014年,全鹏电子科技有限公司成立,并成功通过了ISO9001国际质量管理体系、ISO14001环境管理体系认证和汽车与医疗器材体系IATF/16949认证。这些认证不仅证明了全鹏公司在质量管理方面的实力,也为其在国际市场上赢得了更多的信任和机会。

Exar [Exar Corporation]公司的发展小趣事

Exar公司自1971年在加利福尼亚州成立以来,最初以生产高性能、高可靠性的线性集成电路而著名。然而,随着技术的进步和市场的变化,Exar逐渐意识到通信领域的巨大潜力。因此,在1980年代初,公司开始专注于串行通信和数据存储解决方案,包括UARTs(通用异步收发器)和存储器ICs。这一转变不仅扩大了Exar的市场覆盖范围,也为其后续的发展奠定了坚实的基础。

Global Connector Technology公司的发展小趣事
选用的断相保护继电器可能不适用于特定的电动机或电源系统。

问答坊 | AI 解惑

求助强人!!有做过复合频率信号频率计的帮个忙!!

本帖最后由 paulhyde 于 2014-9-15 09:19 编辑 一、任务 测量两个正弦信号的叠加信号,其中,x1是主信号,幅值为 V(偏置为0V),频率为:20-20kHz;x2是次要信号,幅值为主信号的1/4-1/6,频率为:20-20kHz;二、要求 1.基本要求 (1)利用两个 ...…

查看全部问答>

CPES-IBM未来通信电源功率架构

CPES-IBM未来通信电源功率架构…

查看全部问答>

五一快到了!发段汇编程序的问题给大家爽爽!

哈哈!我骗大家进来的,没什么爽的 问题是这样的:在PXA270上我跑这段程序:入口地址选为0X0(即NORFLASH的地址) xlli_GPIOREGS_PA_BASE EQU 0x40e00000 xlli_GAFR0_L_offset   EQU 0x00000054 xlli_GPDR0_offset     ...…

查看全部问答>

小车控制算法研究 高手大牛 来说说思路

车图 跑道 现在  要控制车子速度 通过一个舵机控制车头转动方向 转动的方向由前面的红外传感器检测到跑道的识别码得到 但是检测的识别码只可能尽量的和实际吻合但仍会有几度的误差 有时甚至会更多 程序会不停的扫描道路得到识 ...…

查看全部问答>

程序效率的问题

我使用.Net写的一个程序,里面有很多自定义控件,和一些用户控件,程序启动很慢,至少一分钟,希望各位给一些意见 先谢谢大家了…

查看全部问答>

低价转让友善之臂QQ2440V3开发板+LCD3.5液晶屏

具体请看taobao上的介绍 http://auction1.taobao.com/auction/item_detail-0db2-5a0abc7b0e70e1f7ae53ffad3582dfc4.jhtml 配件清单: 1) S3C2440核心板一片,配置64MB NAND FLASH和64MB SDRAM 2) S3C2440开发板底板一片 3) 直连九针串口线一条 ...…

查看全部问答>

'CHtmlView' : base class undefined

我在evc下pocketPC模拟器,在一个窗口上要显示网页内容,使用了CHtmlCtrl类 http://dev.yesky.com/128/2272128_1.shtml 这个是国外某达人写的。 我在stdafx.h中已经加了#include \"afxhtml.h\",但是编译后提示我 \'CHtmlView\' : base class u ...…

查看全部问答>

类CPdd16550中m_dwWaterMark是用来干什么的?

类CPdd16550中m_dwWaterMark是用来干什么的? 是波特率的mark呢还是安全相关的mark? 有劳各位!…

查看全部问答>

万利板子上的片子后缀是A

                                 这个版本的片子是不是就不能ISP下载操作!…

查看全部问答>

F149内部AD的电压问题

我今天用一个探测火源的模块去接F149的内部AD,我用3.3V给火焰传感器模块供电,输出脚悬空的时候我测输出脚是0到3V之间在变化(就是当没有火源或者火源超过探测范围的时候是3V),但我接上F149的AD的输入脚之后本来的3V输出就立即衰减为1.7V了。然 ...…

查看全部问答>