搜索
bottom↓
回复: 20

求教傻孩子,环形FIFO出队问题,可以入列,非法出列。

[复制链接]

出0入0汤圆

发表于 2014-10-22 22:19:26 | 显示全部楼层 |阅读模式
        开始是用傻孩子那篇用宏定义的FIFO,后来有问题,我就改成函数的方式了。稍做修改用在自己的程序上。 也把宏改成通俗的了。
        先说问题,改完后可以入列,意思是入列正常,出列也能出,但是全为零。  我做了实验,前面入列8次,全对的,出列也是八次。。。全为零。。。


  1. 定义结构体
  2. typedef struct
  3. {
  4.         uint8_t Ep_add;
  5.         uint8_t Ep_val;
  6. } EP_Data;
  7. 定义队列结构体
  8. typedef struct {
  9.     EP_Data         *ptBuffer;                                            
  10.     uint8_t                tSize;                                                
  11.     uint8_t      tHead;                                                  
  12.     uint8_t      tTail;                                                  
  13.     uint8_t      tCounter;                                             
  14. }t_ep_queue_t;

  15. t_ep_queue_t  EP_Queue; //声明队列
  16. EP_Data epbuf[ep_size];//定义缓冲区
  17. /*        队列初始化                */                                                  
  18. bool t_ep_queue_init(t_ep_queue_t *ptQueue, EP_Data *ptBuffer, uint8_t tSize)
  19. {                                                                           
  20.     t_ep_queue_t *ptQ = (t_ep_queue_t *)ptQueue;      
  21.     if (NULL == ptQueue || NULL == ptBuffer || 0 == tSize) {               
  22.         return false;                                                      
  23.     }                                                                                                                                            
  24.     ptQ->ptBuffer = ptBuffer;                                               
  25.     ptQ->tSize = tSize;                                                     
  26.     ptQ->tHead = 0;                                                         
  27.     ptQ->tTail = 0;                                                         
  28.     ptQ->tCounter = 0;
  29.                                                                            
  30.     return true;                                                            
  31. }                                                                           
  32. /*        入队 函数*/                                                                               
  33. bool t_ep_enqueue(t_ep_queue_t *ptQueue, EP_Data *tObj)                               
  34. {                                                                                                                                                       
  35.         bool bResult = false;                                                                                                       
  36.         t_ep_queue_t *ptQ = (t_ep_queue_t *)ptQueue;               
  37.         if (NULL == ptQ && NULL == tObj) {                                                                                 
  38.                 return false;                                                                                                               
  39.         }                                                                                                                                               
  40.                                                                                                                                                                                                                                                                        
  41.                         if (ptQ->tCounter != ptQ->tSize) {                                                               
  42.                         ptQ->ptBuffer[ptQ->tTail] = *tObj;                                                                                                                                                        
  43.                         if (++ptQ->tTail >= ptQ->tSize) {                                                                
  44.                                 ptQ->tTail = 0;                                                                                        
  45.                         }       
  46.                         ptQ->tCounter++;
  47.                         bResult = true;                                                                                                
  48.                         }                                                                                                                                                                                                                                                                       
  49.         return bResult;                                                                                                                
  50. }                                                                                                                                                       
  51.   /*        出队        函数        */                                                      
  52. bool t_ep_dequeue(t_ep_queue_t *ptQueue, EP_Data *ptObj)            
  53. {                                                                          
  54.         bool bResult = false;                                                                                                       
  55.         t_ep_queue_t *ptQ = (t_ep_queue_t *)ptQueue;               
  56.         if(ptQ == NULL && ptObj == NULL){                                                                               
  57.                 return false;                                                                                                               
  58.           }                                                                                                                                                                                                                                                        
  59.                         if (ptQ->tCounter != 0) {                                                                               
  60.                                 *ptObj = ptQ->ptBuffer[ptQ->tHead];                                                                                                                                       
  61.                                 if(ptQ->tSize >= ++ptQ->tHead){                                                               
  62.                                         ptQ->tHead = 0;                                                                                
  63.                                         }
  64.                                 ptQ->tCounter--;
  65.                         bResult = true;                                                                                                
  66.                         }                                                                                                                               
  67.                                                                                                                                                                                                                                   
  68.     return bResult;                                                         
  69. }                                                                        
  70. /* 我就看看,就是不出出队*/                                                                       
  71.                                                                                                                        
  72. void Ep_init()
  73. {
  74.         t_ep_queue_init(&EP_Queue,&epbuf[0],ep_size);
  75. }

  76. bool Ep_enqueue(EP_Data *value)
  77. {       
  78.         return t_ep_enqueue(&EP_Queue,value);
  79. }

  80. bool Ep_dequeue(EP_Data *value)
  81. {
  82.         return t_ep_dequeue(&EP_Queue,value);
  83. }

  84. /*出队主程序*/
  85. void EP_Task()
  86. {
  87.         EP_Data wep;
  88.         if(Ep_dequeue(&wep) == true)
  89.                 {
  90.                 eeprom_write(wep.Ep_add,wep.Ep_val);
  91.                 }
  92. }

复制代码


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

出0入0汤圆

 楼主| 发表于 2014-10-22 22:31:00 | 显示全部楼层
好了。。我找到问题了= = 在出队中if(ptQ->tSize >= ++ptQ->tHead) 这句写错了,应该是if(ptQ->tSize <= ++ptQ->tHead)

出0入0汤圆

 楼主| 发表于 2014-10-22 22:33:11 | 显示全部楼层
花了两个小时,就这一个小错误。。。从入列到出列,到初始化全仔细看了。。不得不说,PIC的IDE优化太多了。。。不按套路出牌,在结构体里,count和size在我仿真中值一直是零哎。。

出0入0汤圆

发表于 2014-10-26 12:21:36 | 显示全部楼层
本帖最后由 myqiang1990 于 2014-10-26 12:32 编辑

本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~
  1. /*******************************************************************************
  2. ** 文件名:             Queue.c
  3. ** 版本:                  1.0
  4. ** 工作环境:         RealView MDK-ARM 4.23
  5. ** 作者:                 陈志强
  6. ** 生成日期:         2012-5-18
  7. ** 功能:                 
  8. ** 相关文件:       
  9. ** 修改日志:
  10. ** 注意事项:  
  11.                             采用循环队列接收POST的数据,为什么要采用循环队列呢?因为TCP
  12.                                 每次发下来的数据你根本就不知道是多少到底是不是512的整数倍!
  13.                                 但是我们解码必须保证是512个字节的整数数据!
  14.                                
  15. *******************************************************************************/
  16. #include "stm32f4xx.h"
  17. #include "queue.h"
  18. #include <string.h>
  19. /*******************************************************************************
  20. *全局变量:       
  21. *全局说明:
  22. ********************************************************************************/
  23. Q_Queue  Dq;

  24. static uint32_t APPStartddress;
  25. static uint32_t IAPStartddress;
  26. u8 PrgBuffer[PBLOCK] = {0}; //编程缓冲
  27. /*******************************************************************************
  28. *函数原型:void Q_Int(void)
  29. *参数入口:no
  30. *参数出口: no
  31. *函数说明: no
  32. ********************************************************************************/
  33. void Q_Int(Q_Queue *q)
  34. {
  35.    q->head = 0;
  36.    q->tail = 0;
  37.    q->size = 0;
  38.    CleanData();
  39.    APPStartddress = APPLICATION_ADDRESS;
  40.    IAPStartddress = IAP_START_ADDRESS;
  41. }
  42. /*******************************************************************************
  43. *函数原型:void Q_In(Q_Queue *q, u8 data)
  44. *参数入口:no
  45. *参数出口: no
  46. *函数说明: 入队
  47. ********************************************************************************/
  48. static u8 Q_InPut(Q_Queue *q, u8 data)
  49. {
  50.   if((q->tail + 1) % BLOCK == q->head)//满了
  51.    {
  52.      return Q_FULL;
  53.    }
  54.   else
  55.    {
  56.       q->Data[q->tail] = data;
  57.       q->tail = (q->tail + 1) % BLOCK;
  58.       q->size++;
  59.    }
  60.   return Q_OK;
  61. }
  62. /*******************************************************************************
  63. *函数原型:void Q_Out(Q_Queue *q, u8 *data)
  64. *参数入口:no
  65. *参数出口: no
  66. *函数说明: 出队
  67. ********************************************************************************/
  68. static u8 Q_OutPut(Q_Queue *q, u8 *data)
  69. {
  70.   if(q->tail == q->head)//空
  71.    {
  72.      return Q_EMPTY;
  73.    }
  74.   else
  75.    {
  76.        *data = q->Data[q->head];
  77.         q->head = (q->head + 1) % BLOCK;
  78.         q->size--;       
  79.    }
  80.    return Q_OK;
  81. }
  82. /*******************************************************************************
  83. *函数原型:void Q_DataInPut(Q_Queue *q, u8 *data, u16 len)
  84. *参数入口:no
  85. *参数出口: no
  86. *函数说明: 数据入队
  87. ********************************************************************************/
  88. u8 Q_DataInPut(Q_Queue *q, u8 *dataaddr, u16 len)
  89. {
  90.    u16 i = 0;

  91.    for(i = 0; i < len; i++)
  92.     {
  93.           if(Q_InPut(q, *(dataaddr + i)) == Q_FULL)
  94.             return Q_FULL;
  95.         }
  96.   return Q_OK;
  97. }
  98. /*******************************************************************************
  99. *函数原型:u8 Q_DataOutPut(Q_Queue *q, u8 *buffer, u16 len)
  100. *参数入口:no
  101. *参数出口: no
  102. *函数说明: 处理
  103. ********************************************************************************/
  104. u8 Q_DataOutPut(Q_Queue *q, u8 *buffer, u16 len)
  105. {
  106.   u16 i = 0;

  107.   for(i = 0; i < len; i++)
  108.    {
  109.      if(Q_OutPut(q, buffer + i) == Q_EMPTY)
  110.           return Q_EMPTY;
  111.    }
  112. return Q_OK;
  113. }
复制代码
  1. /*******************************************************************************
  2. ** 文件名:             Queue.h
  3. ** 版本:                  1.0
  4. ** 工作环境:         RealView MDK-ARM 4.23
  5. ** 作者:                 陈志强
  6. ** 生成日期:         2012-5-18
  7. ** 功能:                 
  8. ** 相关文件:       
  9. ** 修改日志:
  10. ** 注意事项:  
  11.                             循环队列
  12. *******************************************************************************/
  13. #ifndef _QUEUE_H_
  14. #define _QUEUE_H_
  15. /*******************************************************************************/
  16. #define BLOCK   5120
  17. #define PBLOCK  512

  18. #define Q_FULL  0x01
  19. #define Q_EMPTY 0x02
  20. #define Q_OK    0x03
  21. /*******************************************************************************/
  22. typedef struct
  23. {
  24.    u32 head;
  25.    u32 tail;
  26.    u32 size;
  27.    u8  Data[BLOCK];

  28. }Q_Queue;

  29. extern Q_Queue  Dq;

  30. #define CleanData()   memset(Dq.Data, 0, BLOCK)
  31. /*******************************************************************************/
  32. void Q_Int(Q_Queue *q);
  33. u8 Q_DataInPut(Q_Queue *q, u8 *dataaddr, u16 len);
  34. u8 Q_DataOutPut(Q_Queue *q, u8 *buffer, u16 len);
  35. void ProgameHanld(Q_Queue *q);
  36. /*******************************************************************************/
  37. #endif
复制代码

出0入296汤圆

发表于 2014-10-28 15:16:25 | 显示全部楼层
myqiang1990 发表于 2014-10-26 12:21
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~

建议不要用%运算。

出0入0汤圆

发表于 2014-10-28 16:39:17 | 显示全部楼层
myqiang1990 发表于 2014-10-26 12:21
本屌丝在一个WEB服务器里面接受加密文件用的~仅供参考~

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

出0入0汤圆

发表于 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~~

这个循环列队是不是很简洁啊~~呵呵~~

出0入0汤圆

发表于 2014-10-28 17:53:37 | 显示全部楼层
本帖最后由 myqiang1990 于 2014-10-28 17:55 编辑


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

出0入296汤圆

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

会产生整数除法运算。

出0入0汤圆

发表于 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取余运算!

出0入0汤圆

发表于 2014-10-28 20:23:35 来自手机 | 显示全部楼层
Gorgon_Meducer 发表于 2014-10-28 18:34
会产生整数除法运算。

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

出0入0汤圆

 楼主| 发表于 2014-10-28 22:07:41 来自手机 | 显示全部楼层
开始我也用取余那样算,后来改了 ,毕竟计算机是0和1的。

出0入0汤圆

发表于 2014-12-14 22:41:00 | 显示全部楼层
myqiang1990的程序挺好,学习了

出0入296汤圆

发表于 2014-12-16 10:55:33 | 显示全部楼层
小溪 发表于 2014-10-28 20:23
请问,产生整数出发有什么不好吗?

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

出0入0汤圆

发表于 2014-12-21 16:13:21 | 显示全部楼层
有用,谢谢

出0入0汤圆

发表于 2016-3-24 21:41:40 | 显示全部楼层

出0入0汤圆

发表于 2016-4-27 10:32:45 | 显示全部楼层
Gorgon_Meducer 发表于 2014-12-16 10:55
还是除法……没有硬件除法器的话肯定没有整数比较来得快

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

出0入0汤圆

发表于 2016-4-27 10:40:25 | 显示全部楼层
a_2012_m 发表于 2016-4-27 10:32
不用取余运算,有什么好的方式替代吗?

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

出0入0汤圆

发表于 2016-4-27 10:55:17 | 显示全部楼层
MARK.环形FIFO ,正在学习!

出0入0汤圆

发表于 2016-4-28 08:57:32 | 显示全部楼层
ALUMEI 发表于 2016-4-27 10:40
参考linux 内核源码的 kfifo部分。 fifo的经典了

谢谢,参考kfifo看看!

出0入296汤圆

发表于 2016-4-28 20:48:06 | 显示全部楼层
a_2012_m 发表于 2016-4-27 10:32
不用取余运算,有什么好的方式替代吗?

如果是2的整倍数,用逻辑&运算,
如果不是,简单的用if 判断就可以了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-18 08:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表