完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
2个回答
|
|
环形缓冲区的实现
一.思路 二.实现 /******* cyclebuffer.h ******** * author : Dong * * date : 2021年5月28日 * * mailbox : 351742341@qq.com * * version : 1 * ******************************/ #ifndef __CYCLE_BUFFER_H #define __CYCLE_BUFFER_H //includes #include #include //global define #ifdef USE_RT_THREAD_OS #define CBNULL RT_NULL #else #define CBNULL NULL #endif #define CycleBufferEmpty 0x00 #define CycleBufferFull 0x01 #define CB_OK 0 #define CB_ERROR 1 #define CB_NULL 2 #define CB_DATA_NULL 3 #define CB_FULL 4 #define CB_EMPTY 5 //object CycleBuffer define typedef uint16_t Unit_Type; typedef struct _cycle_buffer_type { Unit_Type *data; Unit_Type *head,*tail,*valid,*validtail; int flag; }CycleBuffer; //public functions CycleBuffer* CycleBufferInit(CycleBuffer* buffer,int length); void CycleBufferDestory(CycleBuffer* buffer); int CBSize(CycleBuffer *buffer); int CBUsedSize(CycleBuffer *buffer); int CBWrite(CycleBuffer *buffer, Unit_Type item); Unit_Type CBRead(CycleBuffer *buffer,int *error_type); #endif /******* cyclebuffer.c ******** * author : Dong * * date : 2021年5月28日 * * mailbox : 351742341@qq.com * * version : 1 * ******************************/ #include "cyclebuffer.h" /* *function :CycleBufferInit() *description :初始化一个循环缓冲区 *param :buffer[in] 待初始化的缓冲区对象指针,函数应该检验该指针的有效性 如该指针是有效指针则在该指针上进行操作 否则应该动态创建一个CycleBuffer对象,并返回动态创建的CycleBuffer对象指针 *param :length[in] 待初始化的缓冲区对象数据域长度 *return :已初始化的CycleBuffer对象指针 */ CycleBuffer* CycleBufferInit(CycleBuffer* buffer,int length) { //检测待初始化的CycleBuffer指针是否为空,若为空则动态申请一段空间 //再次检测申请是否成功,若失败应该终止,返回一个空指针 if(buffer == CBNULL) { buffer = (CycleBuffer*)rt_malloc(sizeof(CycleBuffer)); if(buffer == CBNULL) { return CBNULL; } } //申请size = length * byte动态空间 //注意缓冲区实际大小不等于length,而是length-1,因为data[0]不存放任何数据。 buffer->data =(Unit_Type*)rt_malloc(length * sizeof(Unit_Type)); //如果分配失败,终止,放回空指针 if(buffer->data == CBNULL) { return CBNULL; } //设置缓冲区为空 buffer->flag = CycleBufferEmpty; //设置循环缓冲区标志指针 buffer->head = buffer->data; buffer->tail = buffer->data + (length-1) * sizeof(Unit_Type); //初始化使用区域指针 buffer->valid = buffer->head; buffer->validtail = buffer->head; return buffer; } /* *function :CycleBufferDestroy() *description :销毁一个循环缓冲区 *param :buffer[in] 待销毁的循环缓冲区 *return :void */ void CycleBufferDestory(CycleBuffer* buffer) { //销毁数据域 rt_free(buffer->data); rt_free(buffer); return; } /* *function :CBWrite() *description :向循环缓冲区写一个单位数据 *param :buffer[in] 循环缓冲区对象指针 *param :item[in] unsigned char向缓冲区待写入的一个单位数据 *return :int 异常 */ int CBWrite(CycleBuffer *buffer,Unit_Type item) { int error_type = 0; //检验CycleBuffer对象指针 if(buffer == CBNULL) { return -CB_NULL; } //检验CycleBuffer 数据域指针 if(buffer->data == CBNULL) { return -CB_DATA_NULL; } //检验缓冲区是否为满 if(buffer->flag == CycleBufferFull) { //如果缓冲区满了,应该实现数据丢弃 //即丢弃最早的数据,写入最新的数据 CBRead(buffer,&error_type); //return -CB_FULL; } //CycleBuffer validtail buffer->validtail ++; *(buffer->validtail)= item; //维护flag if(buffer->validtail == buffer->valid) { buffer->flag = CycleBufferFull; //防止valid 和 validtail 指针 停留在 tail域 概率事件 if(buffer->validtail == buffer->tail) { buffer->valid = buffer->head; buffer->validtail = buffer->head; } //返回正的CB_FULL 表明缓冲区 已满 return CB_FULL; } //如果到达线性存储区域尾部,则回溯到线性存储区头部 if(buffer->validtail == buffer->tail) { buffer->validtail = buffer->head; if (buffer->validtail == buffer->valid) { buffer->flag = CycleBufferFull; //返回正的CB_FULL 表明缓冲区 已满 return CB_FULL; } } return CB_OK; } /* *function :CBRead() *description :从循环缓冲区读取一个单位数据 *param :buffer[in] 循环缓冲区对象指针 *param :error_type[in out] 错误类型 *return :unsigned char从循环缓冲区读取到的数据 */ Unit_Type CBRead(CycleBuffer *buffer,int *error_type) { Unit_Type tmp = 0; *error_type = 0; //检验CycleBuffer对象指针 if(buffer == CBNULL) { *error_type = -CB_NULL; } //检验CycleBuffer 数据域指针 if(buffer->data == CBNULL) { *error_type = -CB_DATA_NULL; } //检验缓冲区是否为空 if(buffer->flag == CycleBufferEmpty) { *error_type = -CB_EMPTY; return tmp; } //CycleBuffer valid buffer->valid++; tmp = *(buffer->valid); //维护flag if(buffer->validtail == buffer->valid) { buffer->flag = CycleBufferEmpty; //防止valid 和 validtail 指针 停留在 tail域 概率事件 if(buffer->validtail == buffer->tail) { buffer->valid = buffer->head; buffer->validtail = buffer->head; } //返回正的CB_EMPTY 表明缓冲区 已空 *error_type = CB_EMPTY; } //如果到达线性存储区域尾部,则回溯到线性存储区头部 if(buffer->valid == buffer->tail) { buffer->valid = buffer->head; if (buffer->valid == buffer->validtail) { buffer->flag = CycleBufferEmpty; *error_type = CB_EMPTY; } } //返回读取的数据 return tmp; } /* *function :CBSize() *description :循环缓冲区总空间大小 *param :buffer[in] 循环缓冲区对象指针 *return :int 循环缓冲区总的空间大小 单位 Unit_Type */ int CBSize(CycleBuffer *buffer) { return buffer->tail - buffer->head; } /* *function :CBUsedSize() *description :循环缓冲区已使用的空间大小 *param :buffer[in] 循环缓冲区对象指针 *return :int 循环缓冲区已使用的空间大小 单位 Unit_Type */ int CBUsedSize(CycleBuffer *buffer) { if(buffer->valid == buffer->validtail) { if(buffer->flag == CycleBufferEmpty) { return 0; } else { return CBSize(buffer); } } return buffer->valid < buffer->validtail ? buffer->validtail-buffer->valid : CBSize(buffer)+buffer->validtail-buffer->valid; } USART驱动 一.物理层 选取STM32F407的GPIOB PIN 10 和 GPIO PIN 11 复用为USART3 |
|
|
|
二.应用层实现 /*********** uart.h *********** * author : Dong * * date : 2021年5月28日 * * mailbox : 351742341@qq.com * * version : 1 * ******************************/ #ifndef __UART_H__ #define __UART_H__ //includes #include "board.h" //config #define USE_CYCLE_BUFFER #endif /*********** uart.c *********** * author : Dong * * date : 2021年5月28日 * * mailbox : 351742341@qq.com * * version : 1 * ******************************/ #include "uart.h" #include "cyclebuffer.h" GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; #ifdef USE_CYCLE_BUFFER #define USART3_CYCLE_BUFFER_SIZE 128 /*定义循环缓冲区*/ #ifdef USE_RT_THREAD_OS CycleBuffer *USART3_BUFFER = RT_NULL; #else CycleBuffer *USART3_BUFFER = NULL; #endif #endif #ifdef USE_RT_THREAD_OS rt_mutex_t USART3_INIT_LOCK = RT_NULL; #endif /* *function :USART3_PUTC *description :USART3 发送一个字节,不检验发送状态 *param :str[in] byte 待发送的字节 *return :void */ void USART3_PUTC(unsigned char str) { rt_enter_critical(); while((USART3->SR&1<<7)==0); USART3->DR=str; rt_exit_critical(); } /* *function :USART3_PUTS *description :USART3 发送一段字符串,不检验发送状态 *param :str[in] 待发送的数据区头指针 *return :void */ void USART3_PUTS(const char *str) { rt_enter_critical(); while(*str!=' |