求教傻孩子,环形FIFO出队问题,可以入列,非法出列。
开始是用傻孩子那篇用宏定义的FIFO,后来有问题,我就改成函数的方式了。稍做修改用在自己的程序上。 也把宏改成通俗的了。先说问题,改完后可以入列,意思是入列正常,出列也能出,但是全为零。我做了实验,前面入列8次,全对的,出列也是八次。。。全为零。。。
定义结构体
typedef struct
{
uint8_t Ep_add;
uint8_t Ep_val;
} EP_Data;
定义队列结构体
typedef struct {
EP_Data *ptBuffer;
uint8_t tSize;
uint8_t tHead;
uint8_t tTail;
uint8_t tCounter;
}t_ep_queue_t;
t_ep_queue_tEP_Queue; //声明队列
EP_Data epbuf;//定义缓冲区
/* 队列初始化 */
bool t_ep_queue_init(t_ep_queue_t *ptQueue, EP_Data *ptBuffer, uint8_t tSize)
{
t_ep_queue_t *ptQ = (t_ep_queue_t *)ptQueue;
if (NULL == ptQueue || NULL == ptBuffer || 0 == tSize) {
return false;
}
ptQ->ptBuffer = ptBuffer;
ptQ->tSize = tSize;
ptQ->tHead = 0;
ptQ->tTail = 0;
ptQ->tCounter = 0;
return true;
}
/* 入队 函数*/
bool t_ep_enqueue(t_ep_queue_t *ptQueue, EP_Data *tObj)
{
bool bResult = false;
t_ep_queue_t *ptQ = (t_ep_queue_t *)ptQueue;
if (NULL == ptQ && NULL == tObj) {
return false;
}
if (ptQ->tCounter != ptQ->tSize) {
ptQ->ptBuffer = *tObj;
if (++ptQ->tTail >= ptQ->tSize) {
ptQ->tTail = 0;
}
ptQ->tCounter++;
bResult = true;
}
return bResult;
}
/* 出队 函数 */
bool t_ep_dequeue(t_ep_queue_t *ptQueue, EP_Data *ptObj)
{
bool bResult = false;
t_ep_queue_t *ptQ = (t_ep_queue_t *)ptQueue;
if(ptQ == NULL && ptObj == NULL){
return false;
}
if (ptQ->tCounter != 0) {
*ptObj = ptQ->ptBuffer;
if(ptQ->tSize >= ++ptQ->tHead){
ptQ->tHead = 0;
}
ptQ->tCounter--;
bResult = true;
}
return bResult;
}
/* 我就看看,就是不出出队*/
void Ep_init()
{
t_ep_queue_init(&EP_Queue,&epbuf,ep_size);
}
bool Ep_enqueue(EP_Data *value)
{
return t_ep_enqueue(&EP_Queue,value);
}
bool Ep_dequeue(EP_Data *value)
{
return t_ep_dequeue(&EP_Queue,value);
}
/*出队主程序*/
void EP_Task()
{
EP_Data wep;
if(Ep_dequeue(&wep) == true)
{
eeprom_write(wep.Ep_add,wep.Ep_val);
}
}
各种值不出队,但入队次数和出队次数倒是正常的 好了。。我找到问题了= = 在出队中if(ptQ->tSize >= ++ptQ->tHead) 这句写错了,应该是if(ptQ->tSize <= ++ptQ->tHead) 花了两个小时,就这一个小错误。。。从入列到出列,到初始化全仔细看了。。不得不说,PIC的IDE优化太多了。。。不按套路出牌,在结构体里,count和size在我仿真中值一直是零哎。。 本帖最后由 myqiang1990 于 2014-10-26 12:32 编辑
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~{:smile:}
/*******************************************************************************
** 文件名: Queue.c
** 版本: 1.0
** 工作环境: RealView MDK-ARM 4.23
** 作者: 陈志强
** 生成日期: 2012-5-18
** 功能:
** 相关文件:
** 修改日志:
** 注意事项:
采用循环队列接收POST的数据,为什么要采用循环队列呢?因为TCP
每次发下来的数据你根本就不知道是多少到底是不是512的整数倍!
但是我们解码必须保证是512个字节的整数数据!
*******************************************************************************/
#include "stm32f4xx.h"
#include "queue.h"
#include <string.h>
/*******************************************************************************
*全局变量:
*全局说明:
********************************************************************************/
Q_QueueDq;
static uint32_t APPStartddress;
static uint32_t IAPStartddress;
u8 PrgBuffer = {0}; //编程缓冲
/*******************************************************************************
*函数原型:void Q_Int(void)
*参数入口:no
*参数出口: no
*函数说明: no
********************************************************************************/
void Q_Int(Q_Queue *q)
{
q->head = 0;
q->tail = 0;
q->size = 0;
CleanData();
APPStartddress = APPLICATION_ADDRESS;
IAPStartddress = IAP_START_ADDRESS;
}
/*******************************************************************************
*函数原型:void Q_In(Q_Queue *q, u8 data)
*参数入口:no
*参数出口: no
*函数说明: 入队
********************************************************************************/
static u8 Q_InPut(Q_Queue *q, u8 data)
{
if((q->tail + 1) % BLOCK == q->head)//满了
{
return Q_FULL;
}
else
{
q->Data = data;
q->tail = (q->tail + 1) % BLOCK;
q->size++;
}
return Q_OK;
}
/*******************************************************************************
*函数原型:void Q_Out(Q_Queue *q, u8 *data)
*参数入口:no
*参数出口: no
*函数说明: 出队
********************************************************************************/
static u8 Q_OutPut(Q_Queue *q, u8 *data)
{
if(q->tail == q->head)//空
{
return Q_EMPTY;
}
else
{
*data = q->Data;
q->head = (q->head + 1) % BLOCK;
q->size--;
}
return Q_OK;
}
/*******************************************************************************
*函数原型:void Q_DataInPut(Q_Queue *q, u8 *data, u16 len)
*参数入口:no
*参数出口: no
*函数说明: 数据入队
********************************************************************************/
u8 Q_DataInPut(Q_Queue *q, u8 *dataaddr, u16 len)
{
u16 i = 0;
for(i = 0; i < len; i++)
{
if(Q_InPut(q, *(dataaddr + i)) == Q_FULL)
return Q_FULL;
}
return Q_OK;
}
/*******************************************************************************
*函数原型:u8 Q_DataOutPut(Q_Queue *q, u8 *buffer, u16 len)
*参数入口:no
*参数出口: no
*函数说明: 处理
********************************************************************************/
u8 Q_DataOutPut(Q_Queue *q, u8 *buffer, u16 len)
{
u16 i = 0;
for(i = 0; i < len; i++)
{
if(Q_OutPut(q, buffer + i) == Q_EMPTY)
return Q_EMPTY;
}
return Q_OK;
}/*******************************************************************************
** 文件名: Queue.h
** 版本: 1.0
** 工作环境: RealView MDK-ARM 4.23
** 作者: 陈志强
** 生成日期: 2012-5-18
** 功能:
** 相关文件:
** 修改日志:
** 注意事项:
循环队列
*******************************************************************************/
#ifndef _QUEUE_H_
#define _QUEUE_H_
/*******************************************************************************/
#define BLOCK 5120
#define PBLOCK512
#define Q_FULL0x01
#define Q_EMPTY 0x02
#define Q_OK 0x03
/*******************************************************************************/
typedef struct
{
u32 head;
u32 tail;
u32 size;
u8Data;
}Q_Queue;
extern Q_QueueDq;
#define CleanData() memset(Dq.Data, 0, BLOCK)
/*******************************************************************************/
void Q_Int(Q_Queue *q);
u8 Q_DataInPut(Q_Queue *q, u8 *dataaddr, u16 len);
u8 Q_DataOutPut(Q_Queue *q, u8 *buffer, u16 len);
void ProgameHanld(Q_Queue *q);
/*******************************************************************************/
#endif
myqiang1990 发表于 2014-10-26 12:21
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~
建议不要用%运算。 myqiang1990 发表于 2014-10-26 12:21
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~
我有一个疑问:队列中的元素个数size(即tail和head的差值)小于BLOCK,也就是说队列并没有满,但是有可能head或者tail大于BLOCK,此时Data数据缓冲区不就溢出了吗? 本帖最后由 myqiang1990 于 2014-10-28 17:50 编辑
Gallen.Zhang 发表于 2014-10-28 16:39
我有一个疑问:队列中的元素个数size(即tail和head的差值)小于BLOCK,也就是说队列并没有满,但是有可 ...
NO ~~NO~~~认真分析q->tail = (q->tail + 1) % BLOCK;和q->head = (q->head + 1) % BLOCK;这两句话~~不可能大于 BLOCK,下标只可能在0--BLOCK - 1之间循环,数据个数只能在0---BLOCK之间循环
tail和head在做你追我赶反复运动~数据只可能在BLOCK这么大的数据块中循环运动~~意思是他们两个的运动范围就是0--BLOCK~不会超过BLOCK~~
这个循环列队是不是很简洁啊~~呵呵~~{:smile:} 本帖最后由 myqiang1990 于 2014-10-28 17:55 编辑
Gorgon_Meducer 发表于 2014-10-28 15:16
建议不要用%运算。
为什么呢?我觉得加个if判断不够简洁啊~~所以用了%~~是不是%会不会导致入队出队效率不够高? myqiang1990 发表于 2014-10-28 17:53
为什么呢?我觉得加个if判断不够简洁啊~~所以用了%~~是不是%会不会导致入队出队效率不够高? ...
会产生整数除法运算。 myqiang1990 发表于 2014-10-28 17:46
NO ~~NO~~~认真分析q->tail = (q->tail + 1) % BLOCK;和q->head = (q->head + 1) % BLOCK;这两句话~~不可 ...
谢谢提醒,我忽略了对BLOCK取余运算!{:smile:} Gorgon_Meducer 发表于 2014-10-28 18:34
会产生整数除法运算。
请问,产生整数出发有什么不好吗? 开始我也用取余那样算,后来改了 ,毕竟计算机是0和1的。 myqiang1990的程序挺好,学习了 小溪 发表于 2014-10-28 20:23
请问,产生整数出发有什么不好吗?
还是除法……没有硬件除法器的话肯定没有整数比较来得快 有用,谢谢 {:smile:}{:smile:}{:smile:} Gorgon_Meducer 发表于 2014-12-16 10:55
还是除法……没有硬件除法器的话肯定没有整数比较来得快
不用取余运算,有什么好的方式替代吗? a_2012_m 发表于 2016-4-27 10:32
不用取余运算,有什么好的方式替代吗?
参考linux 内核源码的 kfifo部分。 fifo的经典了 MARK.环形FIFO ,正在学习! ALUMEI 发表于 2016-4-27 10:40
参考linux 内核源码的 kfifo部分。 fifo的经典了
谢谢,参考kfifo看看! a_2012_m 发表于 2016-4-27 10:32
不用取余运算,有什么好的方式替代吗?
如果是2的整倍数,用逻辑&运算,
如果不是,简单的用if 判断就可以了
页:
[1]