【stm32外设】封装在hal库上的串口接收
串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式。
这里使用的是基于cubemx生成的代码上,使用的是空闲中断机制(非DMA)来接收数据**。**
cubemx配置操作为
bsp_usart.c
#include "./usart/bsp_usart.h"
#include <string.h>
/* 缓存串口接收数据的结构体 */
typedef struct stru_usart
{
unsigned char buf[USART_BUF_SIZE];
unsigned char flag;
unsigned int len;
} stru_usart_t;
#if USART1_EN
static stru_usart_t usart_1; /* 缓存串口1接收到的数据 */
#endif
#if USART2_EN
static stru_usart_t usart_2; /* 缓存串口2接收到的数据 */
#endif
#if USART3_EN
static stru_usart_t usart_3; /* 缓存串口3接收到的数据 */
#endif
#if USART4_EN
static stru_usart_t usart_4; /* 缓存串口4接收到的数据 */
#endif
#if USART5_EN
static stru_usart_t usart_5; /* 缓存串口5接收到的数据 */
#endif
/* bsp_usart_init:串口接收初始化函数
* huart 想要初始化的串口的句柄
* huart_type 想要初始化的串口编号,BSP_USART
* return 成功返回0,失败返回-1 */
int bsp_usart_init
(
UART_HandleTypeDef *huart,
unsigned char huart_type
)
{
switch (huart_type)
{
/* 串口1 */
#if USART1_EN
case BSP_USART_1:
/* 开启串口接收中断 */
HAL_UART_Receive_IT(huart, usart_1.buf, USART_BUF_SIZE);
/* 使能空闲中断 */
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
/* 清除第一次空闲中断标志,方便后续接收数据 */
__HAL_UART_CLEAR_IDLEFLAG(huart);
return 0;
#endif
/* 串口2 */
#if USART2_EN
case BSP_USART_2:
HAL_UART_Receive_IT(huart, usart_2.buf, USART_BUF_SIZE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(huart);
return 0;
#endif
/* 串口3 */
#if USART3_EN
case BSP_USART_3:
HAL_UART_Receive_IT(huart, usart_3.buf, USART_BUF_SIZE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(huart);
return 0;
#endif
/* 串口4 */
#if USART4_EN
case BSP_USART_4:
HAL_UART_Receive_IT(huart, usart_4.buf, USART_BUF_SIZE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(huart);
return 0;
#endif
/* 串口5 */
#if USART5_EN
case BSP_USART_5:
HAL_UART_Receive_IT(huart, usart_5.buf, USART_BUF_SIZE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(huart);
return 0;
#endif
}
return -1;
}
/* bsp_usart_handler:串口接收的中断处理函数
* huart 串口的句柄
* huart_type 串口编号,BSP_USART
* return 成功返回0,失败返回-1 */
int bsp_usart_handler
(
UART_HandleTypeDef *huart,
unsigned char huart_type
)
{
switch (huart_type)
{
#if USART1_EN
case BSP_USART_1:
/* 判断是否为空闲中断 */
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
{
usart_1.flag = 1;
/* 计算获取总共接收到的buf的长度 */
usart_1.len = USART_BUF_SIZE - (*huart).RxXferCount;
/* 清除空闲中断标志,方便后续接收数据 */
__HAL_UART_CLEAR_IDLEFLAG(huart);
/* 停止串口接收中断 */
HAL_UART_AbortReceive_IT(huart);
/* 重新开启串口接收中断 */
HAL_UART_Receive_IT(huart, usart_1.buf, USART_BUF_SIZE);
return 0;
}
#endif
#if USART2_EN
case BSP_USART_2:
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
{
usart_2.flag = 1;
usart_2.len = USART_BUF_SIZE - (*huart).RxXferCount;
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_AbortReceive_IT(huart);
HAL_UART_Receive_IT(huart, usart_2.buf, USART_BUF_SIZE);
return 0;
}
#endif
#if USART3_EN
case BSP_USART_3:
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
{
usart_3.flag = 1;
usart_3.len = USART_BUF_SIZE - (*huart).RxXferCount;
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_AbortReceive_IT(huart);
HAL_UART_Receive_IT(huart, usart_3.buf, USART_BUF_SIZE);
return 0;
}
#endif
#if USART4_EN
case BSP_USART_4:
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
{
usart_4.flag = 1;
usart_4.len = USART_BUF_SIZE - (*huart).RxXferCount;
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_AbortReceive_IT(huart);
HAL_UART_Receive_IT(huart, usart_4.buf, USART_BUF_SIZE);
return 0;
}
#endif
#if USART5_EN
case BSP_USART_5:
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
{
usart_5.flag = 1;
usart_5.len = USART_BUF_SIZE - (*huart).RxXferCount;
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_AbortReceive_IT(huart);
HAL_UART_Receive_IT(huart, usart_5.buf, USART_BUF_SIZE);
return 0;
}
#endif
}
return -1;
}
/* bsp_usart_get:获取串口接收到的数据的函数
* buf 获取到的数据复制到buf里
* huart_type 串口编号,BSP_USART
* return 接收到的数据长度,失败返回-1 */
int bsp_usart_get
(
unsigned char buf[],
unsigned char huart_type
)
{
int len = -1;
switch (huart_type)
{
#if USART1_EN
case BSP_USART_1:
if (usart_1.flag == 1) /* 判断串口是否有接收到数据 */
{
strncpy((char*)buf, (const char*)usart_1.buf, usart_1.len);
len = usart_1.len;
memset(&usart_1, 0, sizeof(stru_usart_t));
}
break;
#endif
#if USART2_EN
case BSP_USART_2:
if (usart_2.flag == 1) /* 判断串口是否有接收到数据 */
{
strncpy((char*)buf, (const char*)usart_2.buf, usart_2.len);
len = usart_2.len;
memset(&usart_2, 0, sizeof(stru_usart_t));
}
break;
#endif
#if USART3_EN
case BSP_USART_3:
if (usart_3.flag == 1) /* 判断串口是否有接收到数据 */
{
strncpy((char*)buf, (const char*)usart_3.buf, usart_3.len);
len = usart_3.len;
memset(&usart_3, 0, sizeof(stru_usart_t));
}
break;
#endif
#if USART4_EN
case BSP_USART_4:
if (usart_4.flag == 1) /* 判断串口是否有接收到数据 */
{
strncpy((char*)buf, (const char*)usart_4.buf, usart_4.len);
len = usart_4.len;
memset(&usart_4, 0, sizeof(stru_usart_t));
}
break;
#endif
#if USART5_EN
case BSP_USART_5:
if (usart_5.flag == 1) /* 判断串口是否有接收到数据 */
{
strncpy((char*)buf, (const char*)usart_5.buf, usart_5.len);
len = usart_5.len;
memset(&usart_5, 0, sizeof(stru_usart_t));
}
break;
#endif
}
return len;
}
bsp_usart.h
/**
* author:临木木
* 适用于stm32裸机的usart接收驱动(非DMA)
* 主程序启用前运行bsp_usart_init()函数初始化串口配置
* bsp_usart_handler() 需要放到#include "stm32f1xx_it.c"文件的USARTx_IRQHandler()函数里
*/
#ifndef __BSP_USART_H__
#define __BSP_USART_H__
#include "usart.h"
#define USART_BUF_SIZE 256
/* 启用哪个置1即可 */
#define USART1_EN 1
#define USART2_EN 1
#define USART3_EN 1
#define USART4_EN 0
#define USART5_EN 0
/* huart_type */
enum BSP_USART
{
BSP_USART_1,
BSP_USART_2,
BSP_USART_3,
BSP_USART_4,
BSP_USART_5
};
int bsp_usart_init
(
UART_HandleTypeDef *huart,
unsigned char huart_type
);
int bsp_usart_handler
(
UART_HandleTypeDef *huart,
unsigned char huart_type
);
int bsp_usart_get
(
unsigned char buf[],
unsigned char huart_type
);
#endif
使用示例:
// 初始化
bsp_usart_init(&huart2, BSP_USART_2);
// 接收数据
while (1)
{
static unsigned char usart2_buf[256];
static int usart2_len = 0;
usart2_len = bsp_usart_get(usart2_buf, BSP_USART_2);
if (usart2_len != -1)
{
HAL_UART_Transmit(&huart2, usart2_buf, usart2_len, 1000);
}
}
参考: