使用涉及4个文件,
UART_Port.c UART_Port.h
CircularQueue.h CircularQueue.c
最新框架代码
2022年10月25日更新:https://github.com/aron566/Serial_Port.git
使用方法
1、在配置串口中使能DMA传输 ,全局中断
2、在串口初始化完成后调用Uart_Port_Init();
3、在串口中断服务函数中调用USER_UART_IRQHandler(UART_HandleTypeDef *huart);
4、获取数据接口,请查看CircularQueue.h提供的缓冲区提取数据接口
5、注意事项:malloc无法申请内存的需调整堆栈大小,或者调整缓冲区大小
源码
串口接口文件
PS:默认使用串口1作为调试回环打印接口
需调整宏定义DEBUG_UART
USE_LOOPBACK
#ifdef __cplusplus
extern "C" {
#endif
#include "UART_Port.h"
#define USE_LOOPBACK 1
#define DEBUG_UART &huart1
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart6;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern DMA_HandleTypeDef hdma_usart3_tx;
extern DMA_HandleTypeDef hdma_usart4_rx;
extern DMA_HandleTypeDef hdma_usart4_tx;
extern DMA_HandleTypeDef hdma_usart5_rx;
extern DMA_HandleTypeDef hdma_usart5_tx;
extern DMA_HandleTypeDef hdma_usart6_rx;
extern DMA_HandleTypeDef hdma_usart6_tx;
static uint8_t get_uart_index(USART_TypeDef *Instance);
static Uart_Dev_info_t *Create_Uart_Dev(Uart_num_t uart_num ,UART_HandleTypeDef *huart ,DMA_HandleTypeDef *hdma_rx ,uint16_t rx_temp_size ,uint32_t rxsize ,int work_mode ,osSemaphoreId *pRX_Sem);
Uart_Dev_info_t *Uart_pDevice[UART_MAX_NUM+1];
void Uart_Port_Init(void)
{
Uart_pDevice[UART_NUM_1] = Create_Uart_Dev(UART_NUM_1 ,&huart1 ,&hdma_usart1_rx ,128 ,128 ,0 ,NULL);
Uart_pDevice[UART_NUM_2] = Create_Uart_Dev(UART_NUM_2 ,&huart2 ,&hdma_usart2_rx ,128 ,128 ,0 ,NULL);
}
static Uart_Dev_info_t *Create_Uart_Dev(Uart_num_t uart_num ,UART_HandleTypeDef *huart ,DMA_HandleTypeDef *hdma_rx ,uint16_t rx_temp_size ,uint32_t rxsize ,int work_mode ,osSemaphoreId *pRX_Sem)
{
Uart_Dev_info_t *pUart_Dev = (Uart_Dev_info_t *)malloc(sizeof(Uart_Dev_info_t));
pUart_Dev->phuart = huart;
pUart_Dev->phdma_rx = hdma_rx;
pUart_Dev->cb = cb_create(rxsize);
pUart_Dev->MAX_RX_Temp = rx_temp_size;
pUart_Dev->RX_Buff_Temp = (uint8_t *)malloc(sizeof(uint8_t)*rx_temp_size);
if(NULL == pUart_Dev->RX_Buff_Temp)
{
return NULL;
}
pUart_Dev->Is_Half_Duplex = work_mode;
pUart_Dev->pRX_Sem = pRX_Sem;
__HAL_UART_ENABLE_IT(huart,UART_IT_IDLE);
HAL_UART_Receive_DMA(huart, pUart_Dev->RX_Buff_Temp, pUart_Dev->MAX_RX_Temp);
return pUart_Dev;
}
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint8_t index = get_uart_index(huart->Instance);
if(index != 0)
{
if((__HAL_UART_GET_FLAG(Uart_pDevice[index]->phuart ,UART_FLAG_IDLE) != RESET))
{
HAL_UART_DMAStop(Uart_pDevice[index]->phuart);
__HAL_UART_CLEAR_IDLEFLAG(Uart_pDevice[index]->phuart);
uint32_t data_length = Uart_pDevice[index]->MAX_RX_Temp - __HAL_DMA_GET_COUNTER(Uart_pDevice[index]->phdma_rx);
CQ_putData(Uart_pDevice[index]->cb ,Uart_pDevice[index]->RX_Buff_Temp ,(uint32_t)data_length);
#if USE_LOOPBACK
HAL_UART_Transmit(DEBUG_UART, (uint8_t *)Uart_pDevice[index]->RX_Buff_Temp,(uint16_t)data_length,0xFFFF);
#endif
memset(Uart_pDevice[index]->RX_Buff_Temp ,0 ,data_length);
data_length = 0;
__HAL_UART_ENABLE_IT(Uart_pDevice[index]->phuart ,UART_IT_IDLE);
HAL_UART_Receive_DMA(Uart_pDevice[index]->phuart ,Uart_pDevice[index]->RX_Buff_Temp, Uart_pDevice[index]->MAX_RX_Temp);
}
}
}
static uint8_t get_uart_index(USART_TypeDef *Instance)
{
uint8_t index = 0;
for(;index < UART_MAX_NUM+1;index++)
{
if(Uart_pDevice[index]->phuart->Instance == Instance)
{
return index;
}
}
return 0;
}
#if (USE_NEW_REDIRECT == 0)
#include "stdio.h"
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(DEBUG_UART, (uint8_t *)&ch, 1, 10);
return ch;
}
int fgetc(FILE * f)
{
uint8_t ch = 0;
while(HAL_UART_Receive(DEBUG_UART,&ch, 1, 0xffff)!=HAL_OK);
return ch;
}
#else
#include "stdio.h"
int __io_putchar(int ch)
{
HAL_UART_Transmit(DEBUG_UART ,()uint8_t)&ch ,1 ,0xFFFF);
return ch;
}
int __write(int file, char *ptr, int len)
{
int DataIdx;
for(DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar(*ptr++);
}
return len;
}
#endif
#ifdef __cplusplus
}
#endif
UART_Port.h
文件
#ifndef UART_PORT_H
#define UART_PORT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "cmsis_os.h"
#include "CircularQueue.h"
#define UART_MAX_NUM 6
typedef enum
{
UART_NUM_0 = 0,
UART_NUM_1,
UART_NUM_2,
UART_NUM_3,
UART_NUM_4,
UART_NUM_5,
UART_NUM_6,
}Uart_num_t;
typedef struct
{
UART_HandleTypeDef *phuart;
DMA_HandleTypeDef *phdma_rx;
CQ_handleTypeDef *cb;
uint8_t *RX_Buff_Temp;
uint16_t MAX_RX_Temp;
int Is_Half_Duplex;
osSemaphoreId *pRX_Sem;
}Uart_Dev_info_t;
void Uart_Port_Init(void);
void USER_UART_IRQHandler(UART_HandleTypeDef *huart);
#ifdef __cplusplus
}
#endif
#endif
环形缓冲区接口文件
CircularQueue.c
文件
#ifdef __cplusplus
extern "C" {
#endif
#include "CircularQueue.h"
#if USE_LINUX_SYSTEM
#include <sys/types.h>
#endif
#define TRUE true
#define FALSE false
bool CQ_init(CQ_handleTypeDef *CircularQueue ,uint8_t *memAdd, uint16_t len)
{
CircularQueue->size = len;
if (!IS_POWER_OF_2(CircularQueue->size))
return FALSE;
if(memAdd == NULL)
{
return FALSE;
}
CircularQueue->dataBufer = memAdd;
memset(CircularQueue->dataBufer, 0, len);
CircularQueue->entrance = CircularQueue->exit = 0;
return TRUE;
}
bool CQ_isEmpty(CQ_handleTypeDef *CircularQueue)
{
if (CircularQueue->entrance == CircularQueue->exit)
return TRUE;
else
return FALSE;
}
bool CQ_isFull(CQ_handleTypeDef *CircularQueue)
{
if ((CircularQueue->entrance - CircularQueue->exit) == CircularQueue->size)
return TRUE;
else
return FALSE;
}
uint32_t CQ_getLength(CQ_handleTypeDef*CircularQueue)
{
return (CircularQueue->entrance - CircularQueue->exit);
}
void CQ_emptyData(CQ_handleTypeDef*CircularQueue)
{
CircularQueue->entrance = CircularQueue->exit = 0;
memset(CircularQueue->dataBufer, 0, CircularQueue->size);
}
uint32_t CQ_getData(CQ_handleTypeDef *CircularQueue, uint8_t *targetBuf, uint32_t len)
{
uint32_t size = 0;
len = GET_MIN(len, CircularQueue->entrance - CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->exit & (CircularQueue->size - 1)));
memcpy(targetBuf, CircularQueue->dataBufer + (CircularQueue->exit & (CircularQueue->size - 1)), size);
memcpy(targetBuf + size, CircularQueue->dataBufer, len - size);
CircularQueue->exit += len;
return len;
}
uint32_t CQ_putData(CQ_handleTypeDef *CircularQueue, uint8_t * sourceBuf, uint32_t len)
{
uint32_t size = 0;
len = GET_MIN(len, CircularQueue->size - CircularQueue->entrance + CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->entrance & (CircularQueue->size - 1)));
memcpy(CircularQueue->dataBufer + (CircularQueue->entrance & (CircularQueue->size - 1)), sourceBuf, size);
memcpy(CircularQueue->dataBufer, sourceBuf + size, len - size);
CircularQueue->entrance += len;
return len;
}
uint32_t DQ_putData(CQ_handleTypeDef *CircularQueue, uint8_t * sourceBuf, uint32_t len)
{
uint32_t size = 0;
uint32_t lenth = 1;
uint32_t pack_len = len;
len = GET_MIN(len+lenth, CircularQueue->size - CircularQueue->entrance + CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->entrance & (CircularQueue->size - 1)));
memcpy(CircularQueue->dataBufer + (CircularQueue->entrance & (CircularQueue->size - 1)), &pack_len, lenth);
memcpy(CircularQueue->dataBufer + (CircularQueue->entrance & (CircularQueue->size - 1))+lenth, sourceBuf, size-lenth);
memcpy(CircularQueue->dataBufer, sourceBuf + size - lenth, len - size);
CircularQueue->entrance += len;
return len;
}
uint32_t DQ_getData(CQ_handleTypeDef *CircularQueue, uint8_t *targetBuf)
{
uint32_t size = 0;
uint32_t len = 0;
uint8_t package_len[1];
CQ_getData(CircularQueue, (uint8_t *)package_len, 1);
len = package_len[0];
len = GET_MIN(len, CircularQueue->entrance - CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->exit & (CircularQueue->size - 1)));
memcpy(targetBuf, CircularQueue->dataBufer + (CircularQueue->exit & (CircularQueue->size - 1)), size);
memcpy(targetBuf + size, CircularQueue->dataBufer, len - size);
CircularQueue->exit += len;
return len;
}
uint32_t CQ_ManualGetData(CQ_handleTypeDef *CircularQueue, uint8_t *targetBuf, uint32_t len)
{
uint32_t size = 0;
len = GET_MIN(len, CircularQueue->entrance - CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->exit & (CircularQueue->size - 1)));
memcpy(targetBuf, CircularQueue->dataBufer + (CircularQueue->exit & (CircularQueue->size - 1)), size);
memcpy(targetBuf + size, CircularQueue->dataBufer, len - size);
return len;
}
uint8_t CQ_ManualGet_Offset_Data(uint32_t index ,CQ_handleTypeDef *CircularQueue)
{
uint32_t read_offset = ((CircularQueue->exit + index) & (CircularQueue->size - 1));
uint8_t data = *((uint8_t*)CircularQueue->dataBufer + read_offset);
return data;
}
void CQ_ManualOffsetInc(CQ_handleTypeDef *CircularQueue, uint32_t len)
{
CircularQueue->exit += len ;
}
CQ_handleTypeDef *cb_create(uint32_t buffsize)
{
if (!IS_POWER_OF_2(buffsize))
return NULL;
CQ_handleTypeDef *cb = (CQ_handleTypeDef *)malloc(sizeof(CQ_handleTypeDef));
if(NULL == cb)
{
return NULL;
}
buffsize = (buffsize <= 2048 ? buffsize : 2048);
cb->size = buffsize;
cb->exit = 0;
cb->entrance = 0;
cb->dataBufer = (uint8_t *)malloc(sizeof(uint8_t)*cb->size);
if(NULL == cb->dataBufer)
{
return NULL;
}
return cb;
}
bool CQ_16_init(CQ_handleTypeDef *CircularQueue ,uint16_t *memAdd,uint16_t len)
{
CircularQueue->size = len;
if (!IS_POWER_OF_2(CircularQueue->size))
return FALSE;
if(memAdd == NULL)
{
return FALSE;
}
CircularQueue->data16Bufer = memAdd;
memset(CircularQueue->data16Bufer, 0, len*2);
CircularQueue->entrance = CircularQueue->exit = 0;
return TRUE;
}
CQ_handleTypeDef *cb_16create(uint32_t buffsize)
{
if (!IS_POWER_OF_2(buffsize))
return NULL;
CQ_handleTypeDef *cb = (CQ_handleTypeDef *)malloc(sizeof(CQ_handleTypeDef));
if(NULL == cb)
{
return NULL;
}
buffsize = (buffsize <= 2048 ? buffsize : 2048);
cb->size = buffsize;
cb->exit = 0;
cb->entrance = 0;
cb->data16Bufer = (uint16_t *)malloc(sizeof(uint16_t)*cb->size);
if(NULL == cb->data16Bufer)
{
return NULL;
}
return cb;
}
uint32_t CQ_16getData(CQ_handleTypeDef *CircularQueue, uint16_t *targetBuf, uint32_t len)
{
uint32_t size = 0;
uint32_t len_temp = 0;
uint32_t size_temp = 0;
len = GET_MIN(len, CircularQueue->entrance - CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->exit & (CircularQueue->size - 1)));
len_temp = 2*len;
size_temp = 2*size;
memcpy(targetBuf, CircularQueue->data16Bufer + (CircularQueue->exit & (CircularQueue->size - 1)), size_temp);
memcpy(targetBuf + size, CircularQueue->data16Bufer, len_temp - size_temp);
CircularQueue->exit += len;
return len;
}
uint32_t CQ_16putData(CQ_handleTypeDef *CircularQueue, uint16_t * sourceBuf, uint32_t len)
{
uint32_t size = 0;
uint32_t len_temp = 0;
uint32_t size_temp = 0;
len = GET_MIN(len, CircularQueue->size - CircularQueue->entrance + CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->entrance & (CircularQueue->size - 1)));
len_temp = 2*len;
size_temp = 2*size;
memcpy(CircularQueue->data16Bufer + (CircularQueue->entrance & (CircularQueue->size - 1)), sourceBuf, size_temp);
memcpy(CircularQueue->data16Bufer, sourceBuf + size, len_temp - size_temp);
CircularQueue->entrance += len;
return len;
}
bool CQ_32_init(CQ_handleTypeDef *CircularQueue ,uint32_t *memAdd ,uint16_t len)
{
CircularQueue->size = len;
if (!IS_POWER_OF_2(CircularQueue->size))
return FALSE;
if(memAdd == NULL)
{
return FALSE;
}
CircularQueue->data32Bufer = memAdd;
memset(CircularQueue->data32Bufer, 0, len*4);
CircularQueue->entrance = CircularQueue->exit = 0;
return TRUE;
}
CQ_handleTypeDef *cb_32create(uint32_t buffsize)
{
if (!IS_POWER_OF_2(buffsize))
return NULL;
CQ_handleTypeDef *cb = (CQ_handleTypeDef *)malloc(sizeof(CQ_handleTypeDef));
if(NULL == cb)
{
return NULL;
}
buffsize = (buffsize <= 2048 ? buffsize : 2048);
cb->size = buffsize;
cb->exit = 0;
cb->entrance = 0;
cb->data32Bufer = (uint32_t *)malloc(sizeof(uint32_t)*cb->size);
if(NULL == cb->data32Bufer)
{
return NULL;
}
return cb;
}
uint32_t CQ_32putData(CQ_handleTypeDef *CircularQueue ,uint32_t * sourceBuf ,uint32_t len)
{
uint32_t size = 0;
uint32_t len_temp = 0;
uint32_t size_temp = 0;
len = GET_MIN(len, CircularQueue->size - CircularQueue->entrance + CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->entrance & (CircularQueue->size - 1)));
len_temp = 4*len;
size_temp = 4*size;
memcpy(CircularQueue->data32Bufer + (CircularQueue->entrance & (CircularQueue->size - 1)), sourceBuf, size_temp);
memcpy(CircularQueue->data32Bufer, sourceBuf + size, len_temp - size_temp);
CircularQueue->entrance += len;
return len;
}
uint32_t CQ_32getData(CQ_handleTypeDef *CircularQueue ,uint32_t *targetBuf ,uint32_t len)
{
uint32_t size = 0;
uint32_t len_temp = 0;
uint32_t size_temp = 0;
len = GET_MIN(len, CircularQueue->entrance - CircularQueue->exit);
size = GET_MIN(len, CircularQueue->size - (CircularQueue->exit & (CircularQueue->size - 1)));
len_temp = 4*len;
size_temp = 4*size;
memcpy(targetBuf, CircularQueue->data32Bufer + (CircularQueue->exit & (CircularQueue->size - 1)), size_temp);
memcpy(targetBuf + size, CircularQueue->data32Bufer, len_temp - size_temp);
CircularQueue->exit += len;
return len;
}
#ifdef __cplusplus
}
#endif
CircularQueue.h
文件
#ifndef CIRCULARQUEUE_H_
#define CIRCULARQUEUE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
uint8_t *dataBufer;
uint16_t *data16Bufer;
uint32_t *data32Bufer;
uint32_t size;
uint32_t entrance;
uint32_t exit;
}CQ_handleTypeDef;
#define GET_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define IS_POWER_OF_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
bool CQ_isEmpty(CQ_handleTypeDef *CircularQueue);
bool CQ_isFull(CQ_handleTypeDef *CircularQueue);
void CQ_emptyData(CQ_handleTypeDef*CircularQueue);
uint32_t CQ_getLength(CQ_handleTypeDef *CircularQueue);
void CQ_ManualOffsetInc(CQ_handleTypeDef *CircularQueue, uint32_t len);
bool CQ_init(CQ_handleTypeDef *CircularQueue ,uint8_t *memAdd,uint16_t len);
CQ_handleTypeDef *cb_create(uint32_t buffsize);
uint32_t CQ_getData(CQ_handleTypeDef *CircularQueue, uint8_t *targetBuf, uint32_t len);
uint32_t CQ_putData(CQ_handleTypeDef *CircularQueue, uint8_t *sourceBuf, uint32_t len);
uint32_t DQ_putData(CQ_handleTypeDef *CircularQueue, uint8_t *sourceBuf, uint32_t len);
uint32_t DQ_getData(CQ_handleTypeDef *CircularQueue, uint8_t *targetBuf);
uint32_t CQ_ManualGetData(CQ_handleTypeDef *CircularQueue, uint8_t *targetBuf, uint32_t len);
uint8_t CQ_ManualGet_Offset_Data(uint32_t index ,CQ_handleTypeDef *CircularQueue);
bool CQ_16_init(CQ_handleTypeDef *CircularQueue ,uint16_t *memAdd,uint16_t len);
CQ_handleTypeDef *cb_16create(uint32_t buffsize);
uint32_t CQ_16putData(CQ_handleTypeDef *CircularQueue, uint16_t * sourceBuf, uint32_t len);
uint32_t CQ_16getData(CQ_handleTypeDef *CircularQueue, uint16_t *targetBuf, uint32_t len);
bool CQ_32_init(CQ_handleTypeDef *CircularQueue ,uint32_t *memAdd,uint16_t len);
CQ_handleTypeDef *cb_32create(uint32_t buffsize);
uint32_t CQ_32putData(CQ_handleTypeDef *CircularQueue, uint32_t * sourceBuf, uint32_t len);
uint32_t CQ_32getData(CQ_handleTypeDef *CircularQueue, uint32_t *targetBuf, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif
移植图示
1、加入接口代码文件至工程
2、确定自己的平台库文件
3、加入串口中断服务接口处理方法
4、main.c初始化代码加入
5、测试结果
参考博客:https://blog.csdn.net/jiejiemcu/article/details/82743945
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)