slzm40 发表于 2014-10-22 22:19:26

求教傻孩子,环形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);
                }
}



各种值不出队,但入队次数和出队次数倒是正常的

slzm40 发表于 2014-10-22 22:31:00

好了。。我找到问题了= = 在出队中if(ptQ->tSize >= ++ptQ->tHead) 这句写错了,应该是if(ptQ->tSize <= ++ptQ->tHead)

slzm40 发表于 2014-10-22 22:33:11

花了两个小时,就这一个小错误。。。从入列到出列,到初始化全仔细看了。。不得不说,PIC的IDE优化太多了。。。不按套路出牌,在结构体里,count和size在我仿真中值一直是零哎。。

myqiang1990 发表于 2014-10-26 12:21:36

本帖最后由 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

Gorgon_Meducer 发表于 2014-10-28 15:16:25

myqiang1990 发表于 2014-10-26 12:21
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~

建议不要用%运算。

Gallen.Zhang 发表于 2014-10-28 16:39:17

myqiang1990 发表于 2014-10-26 12:21
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~

我有一个疑问:队列中的元素个数size(即tail和head的差值)小于BLOCK,也就是说队列并没有满,但是有可能head或者tail大于BLOCK,此时Data数据缓冲区不就溢出了吗?

myqiang1990 发表于 2014-10-28 17:46:49

本帖最后由 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:53:37

本帖最后由 myqiang1990 于 2014-10-28 17:55 编辑

Gorgon_Meducer 发表于 2014-10-28 15:16
建议不要用%运算。

为什么呢?我觉得加个if判断不够简洁啊~~所以用了%~~是不是%会不会导致入队出队效率不够高?

Gorgon_Meducer 发表于 2014-10-28 18:34:17

myqiang1990 发表于 2014-10-28 17:53
为什么呢?我觉得加个if判断不够简洁啊~~所以用了%~~是不是%会不会导致入队出队效率不够高? ...

会产生整数除法运算。

Gallen.Zhang 发表于 2014-10-28 19:58:52

myqiang1990 发表于 2014-10-28 17:46
NO ~~NO~~~认真分析q->tail = (q->tail + 1) % BLOCK;和q->head = (q->head + 1) % BLOCK;这两句话~~不可 ...

谢谢提醒,我忽略了对BLOCK取余运算!{:smile:}

小溪 发表于 2014-10-28 20:23:35

Gorgon_Meducer 发表于 2014-10-28 18:34
会产生整数除法运算。

请问,产生整数出发有什么不好吗?

slzm40 发表于 2014-10-28 22:07:41

开始我也用取余那样算,后来改了 ,毕竟计算机是0和1的。

Timerunner321 发表于 2014-12-14 22:41:00

myqiang1990的程序挺好,学习了

Gorgon_Meducer 发表于 2014-12-16 10:55:33

小溪 发表于 2014-10-28 20:23
请问,产生整数出发有什么不好吗?

还是除法……没有硬件除法器的话肯定没有整数比较来得快

Timerunner321 发表于 2014-12-21 16:13:21

有用,谢谢

gxay2000 发表于 2016-3-24 21:41:40

{:smile:}{:smile:}{:smile:}

a_2012_m 发表于 2016-4-27 10:32:45

Gorgon_Meducer 发表于 2014-12-16 10:55
还是除法……没有硬件除法器的话肯定没有整数比较来得快

不用取余运算,有什么好的方式替代吗?

ALUMEI 发表于 2016-4-27 10:40:25

a_2012_m 发表于 2016-4-27 10:32
不用取余运算,有什么好的方式替代吗?

参考linux 内核源码的 kfifo部分。 fifo的经典了

wt19891114 发表于 2016-4-27 10:55:17

MARK.环形FIFO ,正在学习!

a_2012_m 发表于 2016-4-28 08:57:32

ALUMEI 发表于 2016-4-27 10:40
参考linux 内核源码的 kfifo部分。 fifo的经典了

谢谢,参考kfifo看看!

Gorgon_Meducer 发表于 2016-4-28 20:48:06

a_2012_m 发表于 2016-4-27 10:32
不用取余运算,有什么好的方式替代吗?

如果是2的整倍数,用逻辑&运算,
如果不是,简单的用if 判断就可以了
页: [1]
查看完整版本: 求教傻孩子,环形FIFO出队问题,可以入列,非法出列。