您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

FIFO队列二(静态环形队列实现)

系列文章目录
FIFO队列一(原理)
FIFO队列二(静态环形队列实现)


文章目录

  • 前言
  • 一、初始化队列
  • 二、队列是否为空
    • 2.1 Write大于Read
    • 2.2Read 大于 Write
    • 2.3Read 等于 Write
  • 三、队列 入队
  • 四、队列 出队
  • 五、队列是否为满
    • 5.1 Write和 Read 的值不是紧挨着
    • 5.2如果 Write和 Read 的值紧挨着但未满
    • 5.3如果 Write和 Read 的值紧挨着已经满
  • 六、测试


前言

硬件:百问网100ASK_STM32F103_MINI开发板(STM32F103C8T6)
IDE:KEIL 5
按键GPIO口为:PA0
串口为:PA10(USART1_RX)、PA9(USART1_TX)
原理图如下:
在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、初始化队列

初始化就是Read = Write =0


 /* 队列大小 */
#define QUEUE_FIFO_SIZE	9

/** 
 * @brief  
 * @details 
 */
typedef struct
{
	uint8_t aQueueBuf[QUEUE_FIFO_SIZE];		/* 队列数组 */
	uint8_t Read;					/* 队列写记录 (头)*/
	uint8_t Write;					/* 队列读记录(尾)*/
}RingQueue_TypeDef;   

//Static ring queue

/** 缓存 FIFO */
RingQueue_TypeDef RingQueue_st={0};
uint8_t getQueue(void);
void putQueue(uint8_t _Data);
void initQueue(void);
uint8_t isEmptyQueue(void);
uint8_t isFullQueue(void);
/**
  * @brief  初始化FIFO
  * @details  None
  * @Note   None
  * @param[in]   None
  * @return  None
  * @retval  None
  * @par 修改日志
  * 	 于2022-04-06创建
  */
void initQueue(void)
{
	RingQueue_st.Read = 0;
	RingQueue_st.Write = 0;
}

二、队列是否为空

2.1 Write大于Read

如果Write大于Read,说明队列里面还有数据,不为空,所以Write大于Read不能判断为空
在这里插入图片描述

2.2Read 大于 Write

如果Write小于Read,说明队列里面还有数据,不为空,所以Write小于Read也不能判断为空
在这里插入图片描述

2.3Read 等于 Write

在这里插入图片描述

如果 Read 于 Write的值相等,则该队列就一定为空。

/**
  * @brief  FIFO是否为空
  * @details  None
  * @Note   None
  * @param[in]   None
  * @return  None
  * @retval  1  空
  * @retval  0  非空
  * @par 修改日志
  * 	 于2022-04-06创建
  */
uint8_t isEmptyQueue(void)
{
	if (RingQueue_st.Read == RingQueue_st.Write)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

三、队列 入队

1、 入队前要先判断 Write的位置,因为 Write有可能正指向数组最后一个元素,Write再加 1 就越界了。
2、 如何知道 Write是否快越界了? Write+1 后对整个数组长度求余数(%),余数为 0,则 Write+1 处于最后一个数组元素位置,即将越界。

/**
  * @brief  存进FIFO,入队
  * @details  None
  * @Note   None
  * @param[in] _Data 存入的数据 
  * @return  None
  * @retval  None
  * @par 修改日志
  * 	 于2022-04-06创建
  */
void putQueue(uint8_t _Data)
{
	RingQueue_st.aQueueBuf[RingQueue_st.Write] = _Data;
	RingQueue_st.Write = (RingQueue_st.Write+1)%QUEUE_FIFO_SIZE;
}

四、队列 出队

1、 出队前要先判断 Read的位置,因为 Read有可能正指向数组最后一个元素,Read 再加 1 就越界了。
2、 如何知道 Read是否快越界了,Read+1 后对整个数组长度求余数(%),余数为 0,则 Read+1 处于最后一个数组元素位置,即将越界。

/**
  * @brief  出列
  * @details  None
  * @Note   None
  * @param[in]   None
  * @return  脉冲时间,单位为秒
  * @retval  None
  * @par 修改日志
  * 	 于2022-04-06创建
  */
uint8_t getQueue(void)
{
	uint8_t ret;
	ret = RingQueue_st.aQueueBuf[RingQueue_st.Read];
	RingQueue_st.Read = (RingQueue_st.Read+1)%QUEUE_FIFO_SIZE;
	return ret;
}

五、队列是否为满

5.1 Write和 Read 的值不是紧挨着

在这里插入图片描述
如果 Write和 Read 的值不是紧挨着,且Write大于Read,还可以写数据,则队列未满。

在这里插入图片描述
如果 Write和 Read 的值不是紧挨着,且Read大于Write,还可以写数据,则队列未满。

5.2如果 Write和 Read 的值紧挨着但未满

在这里插入图片描述
如果 Write和 Read 的值紧挨着,Write+1%QUEUE_FIFO_SIZE != Read,还可以写数据,则队列未满。

5.3如果 Write和 Read 的值紧挨着已经满

在这里插入图片描述

如果 Write和 Read 的值紧挨着,则队列已满, QUEUE_FIFO_SIZE-1 个元素可以被使用。如果这里不判断为满,再让Write加1,则Read==Write了,就为空了,所以这里要舍一个字节的空间。

/**
  * @brief  FIFO是否为满
  * @details  None
  * @Note   None
  * @param[in]   None
  * @return  None
  * @retval  1  满
  * @retval  0   不满
  * @par 修改日志
  * 	 于2022-04-06创建
  */
uint8_t isFullQueue(void)
{
	if (((RingQueue_st.Write+1)%QUEUE_FIFO_SIZE) == RingQueue_st.Read){
		return 1;
	}
	else{
		return 0;
	}
}

六、测试

int main(void)
{
	int i =0;
    initQueue();
    
    for(i=0;isFullQueue()==0;i++){
		    putQueue(i);
	}
	
	for(i=0;isEmptyQueue()==0;i++){
		printf("get Queue = %d \r\n",getQueue());
	}
	return 0;
}`

测试结果
在这里插入图片描述


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进