历史上的今天
返回首页

历史上的今天

今天是:2025年05月30日(星期五)

正在发生

2019年05月30日 | STM32L0xx_HAL_Driver库的使用——UART

2019-05-30 来源:eefocus

单片机型号:STM32L051C8T6


开发环境MDK5.12


库版本:STM32L0xx_HAL_Driver V1.1.0


主机环境:Windows XP


之前一直使用的STM32F030C8T6单片机来做开发,因需求更改更换了一个新型号STM32L051C8T6,主要是用到了其低功耗特性,本以为直接把代码拷贝一下就可以使用了,结果是太天真了,STM32F030C8T6使用的库是STM32F0_StdPeriph_Lib而STM32L051C8T6使用的库是STM32L0xx_HAL_Driver两者的差别还是很大的,而且官方也推荐使用后者,没办法,重新学习一下吧。。。参考其例程磕磕绊绊的勉强可以写一个工程了,这里写一下有关UART的调试。


参考的程序是STM32L053R8-Nucleo例程中的UART_TwoBoards_ComIT工程,采用中断方式来进行两个单片机之间的通信。STM32L0xx_HAL_Driver库的分层更加明显,板极初始化代码如下



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();

  USARTx_RX_GPIO_CLK_ENABLE();

  /* Enable USART1 clock */

  USARTx_CLK_ENABLE(); 

  

  /*##-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_HIGH;

  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);

  HAL_NVIC_EnableIRQ(USARTx_IRQn);

}

 

/**

  * @brief UART MSP De-Initialization 

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

  *          - Disable the Peripheral's clock

  *          - Revert GPIO and NVIC configuration to their default state

  * @param huart: UART handle pointer

  * @retval None

  */

void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)

{

  /*##-1- Reset peripherals ##################################################*/

  USARTx_FORCE_RESET();

  USARTx_RELEASE_RESET();

 

  /*##-2- Disable peripherals and GPIO Clocks #################################*/

  /* Configure UART Tx as alternate function  */

  HAL_GPIO_DeInit(USARTx_TX_GPIO_PORT, USARTx_TX_PIN);

  /* Configure UART Rx as alternate function  */

  HAL_GPIO_DeInit(USARTx_RX_GPIO_PORT, USARTx_RX_PIN);

  

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

  HAL_NVIC_DisableIRQ(USARTx_IRQn);

}


这两个函数没什么可说的跟开发板对应修改即可,这样使得串口初始化更加的简洁只需要进行逻辑上的初始化即可


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

函数:uart_init()

函数作用:串口初始化

参数:

uint32_t BaudRate=========================串口波特率

返回值:无

上一版本:无

当前版本:1.0

作者:

最后修改时间:2015-04-02

说明: 

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

void uart_init(uint32_t BaudRate)

{

    

    UartHandle.Instance        = USARTx;

    UartHandle.Init.BaudRate   = BaudRate;

    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

    UartHandle.Init.StopBits   = UART_STOPBITS_1;

    UartHandle.Init.Parity     = UART_PARITY_NONE;

    UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;

    UartHandle.Init.Mode       = UART_MODE_TX_RX;

    

    if(HAL_UART_Init(&UartHandle) != HAL_OK)

    {

        Error_Handler();

    }

__HAL_UART_ENABLE(&UartHandle);

 

NVIC_SetPriority(USARTx_IRQn,0);

NVIC_EnableIRQ(USARTx_IRQn);

uart_rev.front = aRxBuffer;

uart_rev.rear = aRxBuffer; //两个指针指向相同的地址空间

if(HAL_UART_Receive_IT(&UartHandle,(uint8_t*)aRxBuffer,1) != HAL_OK)

{

Error_Handler();

}

}


这里为串口的接收开辟了500个字节的缓冲区aRxBuffer使用首尾指针来进行数据的接收和存取,即单缓冲机制。


struct uart

{

uint8_t *rear; //在中断函数中更改

uint8_t *front; //在主循环中更改

};


由于STM32L0xx_Hal_Driver库的使用串口底层分为了3种:查询方式、中断方式、DMA方式,都是使用HAL函数来实现,因此我们使用中断方式接收不能自动开启,必须使用函数HAL_UART_Receive_IT来打开接收中断,这里我们每接收一个字节就进入中断。STM32L0xx_Hal_Driver库的使用使得中断函数也十分简洁一句话搞定,采用回调函数机制来处理中断


void USARTx_IRQHandler(void)

{

  HAL_UART_IRQHandler(& UartHandle);

}

在HAL_UART_IRQHandler()中会自动调用串口接收中断的回调函数


/**

  * @brief  Rx Transfer completed callback

  * @param  UartHandle: UART handle

  * @note   This example shows a simple way to report end of IT Rx transfer, and 

  *         you can add your own implementation.

  * @retval None

  */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)

{

uint8_t ret = HAL_OK;

/* Set transmission flag: trasfer complete*/

uart_rev.rear++; //更新rear指针

if(uart_rev.rear >= (aRxBuffer + BUFFSIZE))

uart_rev.rear = aRxBuffer;

do

{

ret = HAL_UART_Receive_IT(UartHandle,uart_rev.rear,1);

}while(ret != HAL_OK);

}


每次把接收到的数据存入rear所指向的地址空间,存入数据只更新rear指针,同时开启请求下一个数据的到来。在主函数中调用uart_read函数来取出数据


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

函数:uart_read()

函数作用:从接收缓冲区中读取数据

参数:

uint8_t *fmt--------------------------------接收到的数据

uint16_t time_out---------------------------超时时间

返回值:0:读取到数据-1:没有读取到数据

上一版本:无

当前版本:1.0

作者:

最后修改时间:2015-04-08

说明: 

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

int8_t uart_read(uint8_t *fmt, uint16_t time_out)

{

while(time_out)

{

if(uart_rev.front != uart_rev.rear)

{

//如果队首指针和队尾指针不同表明缓冲区中有数据还未收取

*fmt=*uart_rev.front;

uart_rev.front++;

 

if (uart_rev.front >= (aRxBuffer+BUFFSIZE))

uart_rev.front = aRxBuffer;

 

return 0;

}

time_out--;

}

return (int8_t)-1;

}


取数据只更新front指针,这里有个不足的地方是如果一直不取数据或者取数据速度较慢而接收的数据很多会造成数据覆盖即出现数据丢失的情况,不过一般很少会有这种情发生(对于我来说是在主循环中不停地进行读取操作,所以没事啦),整个文件如下


#include "UART.h"

#include "stm32l0xx_hal_def.h"

#include "utils.h"

 

UART_HandleTypeDef UartHandle;

uint8_t aRxBuffer[BUFFSIZE];

struct uart uart_rev;

 

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();

  USARTx_RX_GPIO_CLK_ENABLE();

  /* Enable USART1 clock */

  USARTx_CLK_ENABLE(); 

  

  /*##-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_HIGH;

  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);

  HAL_NVIC_EnableIRQ(USARTx_IRQn);

}

 

/**

  * @brief UART MSP De-Initialization 

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

  *          - Disable the Peripheral's clock

  *          - Revert GPIO and NVIC configuration to their default state

  * @param huart: UART handle pointer

  * @retval None

  */

void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)

{

  /*##-1- Reset peripherals ##################################################*/

  USARTx_FORCE_RESET();

  USARTx_RELEASE_RESET();

 

  /*##-2- Disable peripherals and GPIO Clocks #################################*/

  /* Configure UART Tx as alternate function  */

  HAL_GPIO_DeInit(USARTx_TX_GPIO_PORT, USARTx_TX_PIN);

  /* Configure UART Rx as alternate function  */

  HAL_GPIO_DeInit(USARTx_RX_GPIO_PORT, USARTx_RX_PIN);

  

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

  HAL_NVIC_DisableIRQ(USARTx_IRQn);

}

 

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

函数:uart_init()

函数作用:串口初始化

参数:

uint32_t BaudRate=========================串口波特率

返回值:无

上一版本:无

当前版本:1.0

作者:

最后修改时间:2015-04-02

说明: 

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

void uart_init(uint32_t BaudRate)

{

    

    UartHandle.Instance        = USARTx;

    UartHandle.Init.BaudRate   = BaudRate;

    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

    UartHandle.Init.StopBits   = UART_STOPBITS_1;

    UartHandle.Init.Parity     = UART_PARITY_NONE;

    UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;

    UartHandle.Init.Mode       = UART_MODE_TX_RX;

    

    if(HAL_UART_Init(&UartHandle) != HAL_OK)

    {

        Error_Handler();

    }

__HAL_UART_ENABLE(&UartHandle);

 

NVIC_SetPriority(USARTx_IRQn,0);

NVIC_EnableIRQ(USARTx_IRQn);

uart_rev.front = aRxBuffer;

uart_rev.rear = aRxBuffer; //两个指针指向相同的地址空间

if(HAL_UART_Receive_IT(&UartHandle,(uint8_t*)aRxBuffer,1) != HAL_OK)

{

Error_Handler();

}

}

void Error_Handler(void)

{

    while(1)

    {

        

推荐阅读

史海拾趣

Bellnix Co Ltd公司的发展小趣事

随着产品线的不断丰富,Bellnix开始积极拓展市场。公司通过与各大电子厂商建立合作关系,将产品应用于手机、电脑、家电等多个领域。同时,Bellnix还加强品牌建设,通过参加国际电子展会、举办技术研讨会等方式,提升品牌知名度和影响力。这些举措有效地推动了公司的市场拓展,为公司的持续发展奠定了坚实基础。

Custom Mmic Design Services Inc公司的发展小趣事

随着市场竞争的加剧,CMDS意识到仅仅依靠技术创新是不够的,还需要提供差异化的服务。于是,公司推出了定制化MMIC设计服务,根据客户的具体需求和应用场景,量身定制解决方案。这种服务模式不仅提高了客户满意度,也增强了CMDS的市场竞争力。通过不断优化服务流程和提高设计质量,CMDS逐渐在定制化服务市场上树立了良好的口碑。

Alps Alpine Co Ltd公司的发展小趣事

近年来,随着电子行业的快速发展和市场竞争的加剧,CMDS也面临着诸多挑战。例如,原材料价格波动、人工成本上升、环保要求提高等都给公司的生产和经营带来了压力。然而,CMDS凭借其强大的技术实力和市场竞争力,积极应对这些挑战。通过优化生产流程、提高生产效率、加强成本管理等措施,CMDS不仅成功克服了这些困难,还实现了稳健的发展。同时,公司还注重环境保护和社会责任,积极推动可持续发展战略的实施。

Belden Wire and Cable公司的发展小趣事

随着业务的不断扩展,Belden公司于1910年搬迁至芝加哥更大的区域,并在产品线上增加了橡胶绝缘电线。这一举措不仅扩大了公司的生产规模,也进一步丰富了产品种类,满足了市场的多样化需求。随后,百通工程师于1927年发明的软橡胶塞技术,进一步推动了公司的技术创新和业务拓展。

Conditioning Semiconductor Devices Corp公司的发展小趣事

Conditioning Semiconductor Devices Corp(简称CSDC)起初是一家小型半导体公司,专注于研发低功耗的芯片技术。随着智能设备的普及,市场对节能型半导体的需求激增。CSDC通过不断的研发投入,成功开发了一种全新的低功耗技术,显著降低了设备的能耗,迅速在市场上获得认可,从而实现了业务的快速增长。

Atmel (Microchip)公司的发展小趣事

2016年,Atmel被美国芯片制造商Microchip以35.6亿美元收购。这一收购事件标志着Atmel发展史上的一个重要转折点。在被收购后,Atmel成为了Microchip的一部分,继续发挥其在微控制器领域的优势,同时也获得了Microchip在技术支持、市场渠道等方面的强大支持。这使得Atmel能够更快地推出新产品、拓展新市场,进一步巩固其市场地位。

问答坊 | AI 解惑

安防监控、监控工程(深圳市鑫达莱科技有限公司网络监控部)

深圳市鑫达莱科技有限公司网络工程部是由在台湾著名的CCTV 厂商杰士安(JSA-CCTV)电子股份和鑫达莱公司注资支持下而成立的智能化系统集成公司, 是一家专业提供视频监控系统、防盗报警系统、停车场系统、网络工程等智能化系统集成为一体的高科技企业 ...…

查看全部问答>

选摄像头不要只看像素多少

昨天在电脑城碰到一个朋友在买摄像头,第一句话便是“这个摄像头是多少万像素的?”。相信绝大多数朋友选购摄像头时问得最多的一句话就是这个吧。也正因为如此,有一些厂商和商家抓住消费者的这个心里,在摄像头像素这方面大做文章!     ...…

查看全部问答>

LPC1000系列使用教程及例程

FROM周立功不仅对lpc1114有很大帮助  对lpc1343也有很好的借鉴价值 膜拜一下 伟大的周工 【TinyM0配套教程】    * 【TinyM0配套教程】接口技术与可靠性设计(I2C器件应用方案)    * 【TinyM0配套教程】LPC1 ...…

查看全部问答>

编制内核问题请教

哪位遇见过这样的问题?怎么解决啊?帮帮忙吧! CeNlsCmp:   Total for all locales: 77588 bytes CeNlsCmp: Writing out calendars CeNlsCmp:     Calendar 1: 28 bytes CeNlsCmp:   Total for all c ...…

查看全部问答>

关于堆栈溢出请教

//端口2中断// #pragma vector=PORT2_VECTOR __interrupt void waterflow() { if((P2IFG&BIT1)==BIT1)//插卡进入信号中断 { SET_GIE; P2IE&=~BIT1; P2IFG&=~BIT1;//清除中断标志 .... P2IE|=BIT1; LPM3 ...…

查看全部问答>

求志同道合の人士!

今天查资料,偶然进论坛晃悠了一下,觉得坛里搞电子软硬件的XDJM还不少我一直以来均有自己搞产品的想法,也积累了不少的市场需求和产品创意,但苦于没有可以将产品理念付诸于实物的团队。有感而发了,一是新人报到,二是想看看坛里有没有志同道合的 ...…

查看全部问答>

UARTwrite和UARTCharPut的区别

如题,想问下UARTwrite(const char *pcBuf,unsigned long ulLen)和UARTCharPut (unsigned long ulBase, unsigned char ucData) 的区别…

查看全部问答>

TI电源使用小提示—开发板抢购_2

用过TI的DC-DC,有一点小经验。 TPS5XXXX,忘了哪个具体型号了。   外围电路有电感和电容,   在做某项试验时,发现电源输出纹波过大,导致dsp和fpga不能正常工作。 经过反复试验排查,发现是由于低温时电感的感抗值发生了变化,当 ...…

查看全部问答>

STM32F10x读写AT45DB041 SPI Flash

STM32F10x读写AT45DB041 SPI Flash  忙了大半天,STM32读写AT45DB041 终于调通了,  这里是测试的MDK工程文件AT45DB041读写正常V1.0.rar    AT45DB041是ATMEL公司的新型FLASH芯片。该芯片具有容量大、读写速度快、外围电 ...…

查看全部问答>

请人做板,100M AD板,前有简单信号调理,后通过FMC标准家口输出

开发板已调通,请人做板 -AD采用TI芯片,有开发板参考设计,3路100M AD -前有简单信号调理,包括保护,输入量程选择,已经做了一块简单的 -后面AD输出直接送到FMC标准口输出(开发板上有,LVDS) -时钟采用TI的另外一个芯片,有开发板参考设计 ...…

查看全部问答>