系列文章目录
FIFO队列一(原理)
FIFO队列二(静态环形队列实现)
文章目录
前言
硬件:百问网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;
}`
测试结果