单片机型号: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(); } }
struct uart { uint8_t *rear; //在中断函数中更改 uint8_t *front; //在主循环中更改 };
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); }
/********************************************************************** 函数: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; }
#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) { } } /********************************************************************** 函数: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; } int8_t uart_send(uint8_t *fmt, uint8_t len) { while(len) { printf("%c",*fmt); fmt++; len--; } return 0; } #ifdef UART_DEBUG int fputc(int ch, FILE *f) { USART1->TDR = ch; while(!(USART1->ISR & USART_ISR_TXE)); return(ch); } #endif /** * @brief Tx Transfer completed callback * @param UartHandle: UART handle. * @note This example shows a simple way to report end of IT Tx transfer, and * you can add your own implementation. * @retval None */ void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart) { uint8_t ret = HAL_OK; UartReady = SET; #if 1 uart_snd.front++; //更新rear指针 if(uart_snd.front >= (aTxBuffer + BUFFSIZE)) uart_snd.front = aTxBuffer; if(uart_snd.front != uart_snd.rear) { //如果队首指针和队尾指针不同表明缓冲区中有数据还未发送 do { ret = HAL_UART_Transmit_IT(&UartHandle,uart_snd.front,1);//请求发送下一个数据 }while(ret != HAL_OK); } #endif } /** * @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); } /******************************************************************************/ /* STM32L0xx Peripherals Interrupt Handlers */ /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ /* available peripheral interrupt handler's name please refer to the startup */ /* file (startup_stm32l0xx.s). */ /******************************************************************************/ /** * @brief This function handles UART interrupt request. * @param None * @retval None * @Note This function is redefined in "main.h" and related to DMA stream * used for USART data transmission */ void USARTx_IRQHandler(void) { HAL_UART_IRQHandler(& UartHandle); }