STM32串口环形缓冲区实现

2023-05-16

stm32串口环形缓冲区

一、ringbuff.h

#ifndef _RING_BUFFER_H_
#define _RING_BUFFER_H_

enum
{
	RING_FALSE,
	RING_TRUE,
};

enum
{
	RING_ERR,
	RING_OK,
};

typedef struct ringBuff{
    unsigned int head;     //队列的头部            
    unsigned int tail;     //队列的尾部          
    unsigned int size;     //队列的大小         
    unsigned char *buffer; //数据缓冲区指针
}RingBuff_t, *pRingBuff_t;

void RingBuff_Init(RingBuff_t *pRingBuff, unsigned char *pBuff, unsigned int buf_size);
int RingBuff_ReadNByte (RingBuff_t *pRingBuff, unsigned char *pData, int size);
int RingBuff_WriteNByte(RingBuff_t *pRingBuff, unsigned char *pData, int size);
int RingBuff_GetLen(RingBuff_t *pRingBuff);
unsigned char RingBuff_GetHeadItem(RingBuff_t *pRingBuff);
unsigned char RingBuff_GetIndexItem(RingBuff_t *pRingBuff, int index);

#endif

二、ringbuff.c

#include "ring_buffer.h"
#include "main.h"
#include "stdio.h"

//环形缓冲区初始化
void RingBuff_Init(RingBuff_t *pRingBuff, unsigned char *pBuff, unsigned int buf_size)
{
	if(NULL == pRingBuff || NULL == pBuff)
		return;
	
	pRingBuff->head = 0;
	pRingBuff->tail = 0;
	pRingBuff->size = buf_size;
	pRingBuff->buffer = pBuff;
}

//判断环形缓冲区是否为空
int RingBuff_isEmpty(RingBuff_t *pRingBuff) 
{
	if(NULL == pRingBuff)
		return RING_FALSE;
	
	if(pRingBuff->head == pRingBuff->tail)
	{
		return RING_TRUE;
	}
	return RING_FALSE;
}

//判断环形缓冲区是否为满
static int RingBuff_isFull(RingBuff_t *pRingBuff)
{
	if(NULL == pRingBuff)
		return RING_FALSE;

	if((pRingBuff->tail+1)%pRingBuff->size == pRingBuff->head)
	{
		return RING_TRUE;
	}
	return RING_FALSE;
}

//从环形缓冲区取出一个字节
int RingBuff_ReadOneByte(RingBuff_t *pRingBuff, unsigned char *pData)
{
	if(NULL == pRingBuff || NULL == pData)
		return RING_ERR;

	//判空
	if(RING_TRUE == RingBuff_isEmpty(pRingBuff))
	{
		//printf("ring buffer is empty!\r\n");
		return RING_ERR;
	}

	*pData = pRingBuff->buffer[pRingBuff->head];
	pRingBuff->head = (pRingBuff->head+1)%pRingBuff->size;
	return RING_OK;
}

//向环形缓冲区写入一个字节
static int RingBuff_WriteOneByte(RingBuff_t *pRingBuff, unsigned char *pData)
{
	if(NULL == pRingBuff || NULL == pData)
		return RING_ERR;

	//判满
	if(RING_TRUE == RingBuff_isFull(pRingBuff))
	{
		//printf("ring buffer is full!\r\n");
		return RING_ERR;
	}

	pRingBuff->buffer[pRingBuff->tail] = *pData;
	pRingBuff->tail = (pRingBuff->tail+1)%pRingBuff->size;
	return RING_OK;
}

//从环形缓冲区读多个字节
int RingBuff_ReadNByte(RingBuff_t *pRingBuff, unsigned char *pData, int size)
{
	if(NULL == pRingBuff || NULL == pData)
		return RING_ERR;

	for(int i = 0; i < size; i++)
	{
		RingBuff_ReadOneByte(pRingBuff, pData+i);
	}
	return RING_OK;
}

//向环形缓冲区写多个字节
int RingBuff_WriteNByte(RingBuff_t *pRingBuff, unsigned char *pData, int size)
{
	if(NULL == pRingBuff || NULL == pData)
		return RING_ERR;

	for(int i = 0; i < size; i++)
	{
		RingBuff_WriteOneByte(pRingBuff, pData+i);
	}
	return RING_OK;
}

//获取当前环形缓冲区中数据长度
int RingBuff_GetLen(RingBuff_t *pRingBuff)
{
	if(NULL == pRingBuff)
		return RING_ERR;

	if(pRingBuff->tail >= pRingBuff->head)
	{
		return pRingBuff->tail - pRingBuff->head;
	}
	
	return pRingBuff->tail + pRingBuff->size - pRingBuff->head;
}

//获取当前头部数据
unsigned char RingBuff_GetHeadItem(RingBuff_t *pRingBuff)
{
	if(NULL == pRingBuff)
		return RING_ERR;
	
	return pRingBuff->buffer[pRingBuff->head];
}

//获取指定下标数据
unsigned char RingBuff_GetIndexItem(RingBuff_t *pRingBuff, int index)
{
	if(NULL == pRingBuff || index > pRingBuff->size-1)
		return RING_ERR;

	return pRingBuff->buffer[index%pRingBuff->size];
}

三、应用例程(配合串口接受DMA使用)

extern UART_HandleTypeDef huart1;
RingBuff_t Uart1_RingBuff;
uint8_t USART1_DMA_Buff[USART1_DMA_SIZE];
uint8_t USART1_RingBuff[USART1_RING_BUFF_SIZE];

//通讯接口环形缓冲区初始化
void Data_InterFace_Init(void)
{
	RingBuff_Init(&Uart1_RingBuff, USART1_RingBuff, USART1_RING_BUFF_SIZE);
}

//串口DMA接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(&huart1 == huart)
	{
		//将数据拷贝到串口环形缓冲区中
		RingBuff_WriteNByte(&Uart1_RingBuff, USART1_DMA_Buff, USART1_DMA_SIZE);
		
		//使能串口接收DMA
		HAL_UART_Receive_DMA(&huart1, USART1_DMA_Buff, USART1_DMA_SIZE);
	}
}
//使能串口DMA
void Board_Init(void)
{
	//接口缓冲区初始化
	Data_InterFace_Init();
	
	//使能串口1接收DMA
	HAL_UART_Receive_DMA(&huart1, USART1_DMA_Buff, USART1_DMA_SIZE);
}

/* USER CODE END Header_Uart_Dma_Task */
void Uart_Dma_Task(void const * argument)
{
  /* USER CODE BEGIN Uart_Dma_Task */
    pParameter_t parameter = NULL;
    pRingBuff_t pRingBuff = NULL;
	uint8_t data_buff[10];
	uint8_t flag, t_data;
	
	parameter = (pParameter_t)argument;
	pRingBuff = parameter->Data_InterFace[UART1_NUM].pRingBuffCB;
	/* Infinite loop */
	for(;;)
	{	
		while(!RingBuff_isEmpty(pRingBuff))
		{
			if(RingBuff_GetHeadItem(pRingBuff) == 0xEB
			 &&RingBuff_GetIndexItem(pRingBuff, pRingBuff->head+1) == 0x90)
			{
				if(RingBuff_GetLen(pRingBuff) >= 10)
				{
					RingBuff_ReadNByte(pRingBuff, data_buff, 10);
					flag = 1;
				}
				else
				{
					break;
				}
			}
			else
			{
				RingBuff_ReadOneByte(pRingBuff, &t_data);
			}
		}
		
		//判断是否有收到报文
		if(1 == flag)
		{
			flag = 0;
			BSP_Uart1_SendData(data_buff, 10);
		}
		
		osDelay(10);
	}
  /* USER CODE END Uart_Dma_Task */
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32串口环形缓冲区实现 的相关文章

  • GCC - 如何停止链接 malloc?

    我正在努力将我的代码缩减到最小的骨架大小 我使用的是只有 32k 闪存的 STM32F0 需要很大一部分闪存用于数据存储 我的代码已经有大约 20k 闪存大小 其中一些是由于使用了 STM32 HAL 函数 我可以在以后需要时对其进行解释和
  • STM32 F072上的软件如何跳转到bootloader(DFU模式)?

    STM32应用笔记2606对此进行了讨论 但没有简单的代码示例 该答案已使用 IAR EWARM 在 STM32F072 Nucleo 板上进行了测试 这个答案使用 STM32标准外设库 仅此而已 请注意 验证您是否成功进入引导加载程序模式
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • 140-基于stm32单片机智能晾衣杆控制系统Proteus仿真+源程序

    资料编号 140 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 光敏传感器 蜂鸣器 LED灯 制作一个基于stm32单片机智能晾衣杆控制系统Proteus仿真 2 通过光敏传感器
  • 133-基于stm32单片机停车场车位管理系统Proteus仿真+源程序

    资料编号 133 一 功能介绍 1 采用stm32单片机 4位数码管 独立按键 制作一个基于stm32单片机停车场车位管理系统Proteus仿真 2 通过按键进行模拟车辆进出 并且通过程序计算出当前的剩余车位数量 3 将剩余的车位数量显示到
  • 137-基于stm32单片机智能保温杯控制装置Proteus仿真+源程序

    资料编号 137 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DS18B20传感器 电机 制作一个基于stm32单片机智能保温杯控制装置Proteus仿真 2 通过DS18b20传感器检测当前保温杯水的温度 并且
  • Push_back() 导致程序在进入 main() 之前停止

    我正在为我的 STM32F3 Discovery 板使用 C 进行开发 并使用 std deque 作为队列 在尝试调试我的代码 直接在带有 ST link 的设备上或在模拟器中 后 代码最终在 main 中输入我的代码之前在断点处停止 然
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • Arm:objcopy 如何知道 elf 中的哪些部分要包含在二进制或 ihex 中?

    我正在开发一个项目 其中涉及解析arm elf 文件并从中提取部分 显然 elf 文件中有很多部分没有加载到闪存中 但我想知道 objcopy 到底如何知道要在二进制文件中包含哪些部分以直接闪存到闪存中 以arm elf文件的以下reade
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 使用 STM32F0 ADC 单独读取不同的输入

    STM32F072CBU 微控制器 我有多个 ADC 输入 并且希望单独读取它们 STMcubeMX 生成样板代码 假设我希望按顺序读取所有输入 但我无法弄清楚如何纠正这个问题 这篇博文 http blog koepi info 2015

随机推荐

  • 基于stm32f103zet6之使用FSMC驱动TFT的学习

    在完成IO驱动彩屏的试验后 xff0c 就准备着手使用FSMC来驱动彩屏 xff0c 先了解一下预备知识 一 所谓的FSMC机制 简单介绍FSMC在这篇博文里面很清楚 xff0c 推荐一下 http blog csdn net king b
  • (转)ds18b20时序说明

    ds18b20时序说明 新手在DS18B20读写过程中要犯很多错误 老衲普度众生 xff0c 简要说明它怎么用 1 过程1 2是初始化过程 xff0c 每次读取都要初始化 xff0c 否则18b20处于待机状态 xff0c 无法成功读取 过
  • H桥驱动芯片IR2110功能简介

    1 1 驱动芯片IR2110功能简介 在功率变换装置中 xff0c 根据主电路的结构 xff0c 起功率开关器件一般采用直接驱动和隔离驱动两种方式 美国IR公司生产的IR2110驱动器 xff0c 兼有光耦隔离和电磁隔离的优点 xff0c
  • 关于示波器是否必须要接地线的疑问

    这是一个非常隐蔽的问题 xff0c 稍不注意 xff0c 在接入示波器时 xff0c 就会导致线路板上的某些芯片突然爆炸 xff0c 不仅会对项目产生非常大的影响 xff0c 也足以让我们着实郁闷上几天 所以 xff0c 应该足够引起电路设
  • POCO C++库学习和分析 -- 进程

    POCO C 43 43 库学习和分析 进程 Poco Foundation库中涉及进程的内容主要包括了4个主题 xff0c 分别是进程 Process 进程间同步 xff08 inter process synchronization x
  • Mysql安装后在服务里找不到和服务启动不起来的解决方法

    一 安装完MySQL后找不到服务 在那完MySQL数据库后 xff0c 在计算机管理 61 61 服务和应用程序 61 61 服务中找不到MySQL的服务 解决方法 xff1a 1 以管理员的身份运行cmd或者Windows powersh
  • C++中虚继承

    一 虚继承和虚基类 1 多继承产生的冲突 在C 43 43 中多继承时很容易产生命名冲突 xff0c 即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字 xff0c 命名冲突依然有可能发生 xff0c 比如典型的是菱形继承 x
  • 跨平台C++单元测试框架——GTest

    1 简介 GTest是google公司发布的一个跨平台的 Liunx Mac OS X Windows Cygwin Windows CE and Symbian C 43 43 单元测试框架 它提供了丰富的断言 致命和非致命判断 参数化
  • 音频格式之AAC(高级音频编码技术)

    1 简介 ACC xff08 Advanced Audio Coding xff0c 高级音频编码 xff09 是杜比实验室为音乐社区提供的技术 xff0c 出现于1997年 xff0c 基于MPEG 2的音频编码技术 2000年 xff0
  • C++11之lambda回调设置与应用

    在程序中有时候我们需要实现回调效果 xff0c 比如先设置监听 xff0c 然后在后面具体执行完某个操作后再将该操作的结果通知给前面监听中 这种机制实际很常用 xff0c 比如window底下的消息机制 xff0c Qt中的信号槽的机制都有
  • 高速的C/C++编译工具——ccache

    1 简介 ccache xff08 compiler cache 的缩写 xff09 是一个编译器缓存 xff0c 该工具会高速缓存编译生成的信息 xff0c 并在编译的特定部分使用高速缓存的信息 xff0c 比如头文件 xff0c 这样就
  • Django17:内建用户系统

    1 定义 Django带有一个用户认证系统 它处理用户账号 组 权限以及基于cookie的用户会话 用户可以直接是使用Django自带的用户表 2 基本字段 模型类位置from django contrib contrib auth mod
  • Django18:文件上传

    1 上传规范 xff08 1 xff09 前端HTML 文件上传必须为POST提交方式 表达 lt form gt 中文件上传时必须带有enctype 61 multipart formdata 时才会包含文件内容数据 表单中用 lt in
  • Django19:发送邮件

    1 邮件相关协议 xff08 1 xff09 SMTP SMTP xff08 Simple Mail Transfer Protocol xff09 xff0c 简单邮件传输协议 xff08 25号端口 xff09 它是一组用于从原地址到目
  • JsonCpp的基本用法

    1 JsonCpp C 43 43 库 xff0c 允许操作JSON值 xff0c 包括与字符串串行化和序列化 它可在反序列化 序列化步骤中保留现有注释 xff0c 使其成为存储用户输入文件的便捷方式 是一个第三方JSON解析库 xff0c
  • POCO C++库学习和分析 -- 文件系统

    POCO C 43 43 库学习和分析 文件系统 既然作为一个框架性的库 xff0c 自然会提供对于文件系统的操作 在Poco库中 xff0c 封装了一些类去完成上述操作 这些类包括了 xff1a 1 Poco Path 2 Poco Fi
  • C++中的HTTP协议

    1 HTTP Hyper Text Transfer Protocol xff08 超文本传输协议 xff09 是一种通信协议 xff0c 它允许将超文本标记语言 HTML 文档从Web服务器传送到客户端的浏览器 在Internet中所有的
  • C++中析构函数为虚函数

    1 析构函数是否定义为虚函数的区别 xff08 1 xff09 析构函数定义为虚函数时 xff1a 基类指针可以指向派生类的对象 xff08 多态性 xff09 xff0c 如果删除该指针delete p xff1b 就会调用该指针指向的派
  • [Linux C]TCP通讯例程

    这个是最最最基本的例程 xff0c 先开一个坑 xff0c 稍后再慢慢完善 服务端程序 include lt stdio h gt include lt stdlib h gt include lt string h gt include
  • STM32串口环形缓冲区实现

    stm32串口环形缓冲区 一 ringbuff h span class token macro property span class token directive hash span span class token directiv