搜索
bottom↓
回复: 86

[共享][版本更新][古董贴]C语言代码模板_环形队列

  [复制链接]

出0入296汤圆

发表于 2008-1-26 02:54:15 | 显示全部楼层 |阅读模式
本帖最后由 Gorgon_Meducer 于 2013-3-12 12:50 编辑


古董贴仅供考古,相同内容最新版本,请参考http://www.amobbs.com/thread-5515836-1-1.html



  1. #ifndef _USE_TPL_QUEUE_H_
  2. #define _USE_TPL_QUEUE_H_
  3. /***********************************************************
  4. *   模板库说明:环形队列模板                               *
  5. *   版本:      v1.10                                      *
  6. *   作者:      王卓然                                     *
  7. *   创建日期:  2008年1月19日                              *
  8. * -------------------------------------------------------- *
  9. *  [支 持 库]                                              *
  10. *   支持库名称:RD_MacroAndConst.h                         *
  11. *   需要版本:  v0.04 &abv                                 *
  12. *   支持库说明:系统常用宏定义库                           *
  13. * -------------------------------------------------------- *
  14. *  [版本更新]                                              *
  15. *   修改:      王卓然                                     *
  16. *   修改日期:  2008年3月8日                               *
  17. *   版本:      v1.10                                      *
  18. * -------------------------------------------------------- *
  19. *  [版本历史]                                              *
  20. *       v1.00   提供了基本的代码模板和基本的队列操作函数。 *
  21. *       v1.10   增加了一个扩展的Peek函数,可以连续的向后预 *
  22. *               读队列中的内容。并增加了队列清空的函数。   *
  23. * -------------------------------------------------------- *
  24. *  [使用说明]                                              *
  25. ***********************************************************/

  26. /********************
  27. * 头 文 件 配 置 区 *
  28. ********************/
  29. # include "RD_MacroAndConst.h"

  30. /********************
  31. *   系 统 宏 定 义  *
  32. ********************/

  33. /*------------------*
  34. *   常 数 宏 定 义  *
  35. *------------------*/

  36. /*------------------*
  37. *   动 作 宏 定 义  *
  38. *------------------*/
  39. # define START_DEFINE_QUEUE(__NAME,__SIZE,__TYPE,__POS_TYPE)  \
  40.                 __TYPE  s_Queue##__NAME##Buffer[(__SIZE)] = {0};\
  41.                 __POS_TYPE  s_Queue##__NAME##Tail = 0;\
  42.                 __POS_TYPE  s_Queue##__NAME##Head = 0;\
  43.                 __POS_TYPE  s_Queue##__NAME##Counter = 0;\
  44.                 __POS_TYPE  s_Queue##__NAME##PeekCounter = 0;\
  45.                 \
  46.                 BOOL Queue_##__NAME##_Add_Data(__TYPE Data)\
  47.                 {\
  48.                     SAFE_CODE_PERFORMANCE\
  49.                     (\
  50.                         if ((s_Queue##__NAME##Tail == s_Queue##__NAME##Head)\
  51.                           && (s_Queue##__NAME##Counter != 0))\
  52.                         {\
  53.                             EXIT_SAFE_CODE\
  54.                             return FALSE;\
  55.                         }\
  56.                         \
  57.                         s_Queue##__NAME##Buffer[s_Queue##__NAME##Tail] = Data;\
  58.                         s_Queue##__NAME##Tail = (s_Queue##__NAME##Tail == (__SIZE - 1)) ? \
  59.                                                 0 : (s_Queue##__NAME##Tail + 1);\
  60.                         s_Queue##__NAME##Counter++;\
  61.                     )\
  62.                     \
  63.                     return TRUE;\
  64.                 }\
  65.                 \
  66.                 BOOL Queue_##__NAME##_Get_Data(__TYPE *pData)\
  67.                 {\
  68.                     SAFE_CODE_PERFORMANCE\
  69.                     (\
  70.                         if (((s_Queue##__NAME##Tail == s_Queue##__NAME##Head)\
  71.                           && (s_Queue##__NAME##Counter == 0))\
  72.                           || (pData == NULL))\
  73.                         {\
  74.                             EXIT_SAFE_CODE\
  75.                             return FALSE;\
  76.                         }\
  77.                         \
  78.                         (*pData) = s_Queue##__NAME##Buffer[s_Queue##__NAME##Head];\
  79.                         s_Queue##__NAME##Head = (s_Queue##__NAME##Head == (__SIZE - 1)) ? \
  80.                                                 0 : (s_Queue##__NAME##Head + 1);\
  81.                         s_Queue##__NAME##Counter--;\
  82.                         s_Queue##__NAME##PeekCounter = s_Queue##__NAME##Head;\
  83.                     )\
  84.                     \
  85.                     return TRUE;\
  86.                 }\
  87.                 \
  88.                 BOOL Queue_##__NAME##_Peek_Data(__TYPE *pData)\
  89.                 {\
  90.                     SAFE_CODE_PERFORMANCE\
  91.                     (\
  92.                         if (((s_Queue##__NAME##Tail == s_Queue##__NAME##Head)\
  93.                           && (s_Queue##__NAME##Counter == 0))\
  94.                           || (pData == NULL))\
  95.                         {\
  96.                             EXIT_SAFE_CODE\
  97.                             return FALSE;\
  98.                         }\
  99.                         \
  100.                         (*pData) = s_Queue##__NAME##Buffer[s_Queue##__NAME##Head];\
  101.                     )\
  102.                     \
  103.                     return TRUE;\
  104.                 }\
  105.                 \
  106.                 BOOL Queue_##__NAME##_Check_Empty(void)\
  107.                 {\
  108.                     SAFE_CODE_PERFORMANCE\
  109.                     (\
  110.                         if ((s_Queue##__NAME##Tail == s_Queue##__NAME##Head)\
  111.                           && (s_Queue##__NAME##Counter == 0))\
  112.                         {\
  113.                             EXIT_SAFE_CODE\
  114.                             return TRUE;\
  115.                         }\
  116.                     )\
  117.                     return FALSE;\
  118.                 }\
  119.                 \
  120.                 __POS_TYPE Queue_##__NAME##_Get_Count(void)\
  121.                 {\
  122.                     return s_Queue##__NAME##Counter;\
  123.                 }\
  124.                 BOOL Queue_##__NAME##_Peek_Extend(__TYPE *pData)\
  125.                 {\
  126.                     SAFE_CODE_PERFORMANCE\
  127.                     (\
  128.                         if ((s_Queue##__NAME##PeekCounter == s_Queue##__NAME##Tail)\
  129.                             || (pData == NULL))\
  130.                         {\
  131.                             EXIT_SAFE_CODE\
  132.                             return FALSE;\
  133.                         }\
  134.                         \
  135.                         (*pData) = s_Queue##__NAME##Buffer[s_Queue##__NAME##PeekCounter];\
  136.                         s_Queue##__NAME##PeekCounter++;\
  137.                         s_Queue##__NAME##PeekCounter = (s_Queue##__NAME##PeekCounter == (__SIZE)) ? \
  138.                                                 0 : (s_Queue##__NAME##PeekCounter);\
  139.                     )\
  140.                     \
  141.                     return TRUE;\
  142.                 }\
  143.                 void Queue_##__NAME##_Reset_Peek_Counter(void)\
  144.                 {\
  145.                     SAFE_CODE_PERFORMANCE\
  146.                     (\
  147.                         s_Queue##__NAME##PeekCounter = s_Queue##__NAME##Head;\
  148.                     )\
  149.                 }\
  150.                 void Queue_##__NAME##_Clear(void)\
  151.                 {\
  152.                     SAFE_CODE_PERFORMANCE\
  153.                     (\
  154.                         s_Queue##__NAME##Tail = s_Queue##__NAME##Head;\
  155.                         s_Queue##__NAME##Counter = 0;\
  156.                         s_Queue##__NAME##PeekCounter = s_Queue##__NAME##Head;\
  157.                     )\
  158.                 }
  159.                
  160.                
  161. # define END_DEFINE_QUEUE

  162. # define GET_QUEUE_DATA(__NAME,__ADDR)          Queue_##__NAME##_Get_Data(__ADDR)
  163. # define PEEK_QUEUE_DATA(__NAME,__ADDR)         Queue_##__NAME##_Peek_Data(__ADDR)
  164. # define ADD_QUEUE_DATA(__NAME,__VAR)           Queue_##__NAME##_Add_Data(__VAR)
  165. # define GET_QUEUE_COUNT(__NAME)                Queue_##__NAME##_Get_Count()
  166. # define CHECK_QUEUE_EMPTY(__NAME)              Queue_##__NAME##_Check_Empty()
  167. # define PEEK_QUEUE_DATA_EXTEND(__NAME,__ADDR)  Queue_##__NAME##_Peek_Extend(__ADDR)
  168. # define RESET_PEEK_COUNTER(__NAME)             Queue_##__NAME##_Reset_Peek_Counter();
  169. # define CLEAR_QUEUE(__NAME)                    Queue_##__NAME##_Clear();

  170. # define EXTERN_REFERENCE_QUEUE(__NAME,__TYPE,__POS_TYPE)  \
  171.             extern BOOL Queue_##__NAME##_Add_Data(__TYPE Data);\
  172.             extern BOOL Queue_##__NAME##_Get_Data(__TYPE *pData);\
  173.             extern BOOL Queue_##__NAME##_Peek_Data(__TYPE *pData);\
  174.             extern BOOL Queue_##__NAME##_Check_Empty(void);\
  175.             extern __POS_TYPE Queue_##__NAME##_Get_Count(void);\
  176.             extern BOOL Queue_##__NAME##_Peek_Extend(__TYPE *pData);\
  177.             extern void Queue_##__NAME##_Reset_Peek_Counter(void);\
  178.             extern void Queue_##__NAME##_Clear(void);
  179.             
  180. /********************
  181. *  用户变量类型定义 *
  182. ********************/

  183. /********************
  184. *    结构体定义区   *
  185. ********************/

  186. /********************
  187. *   函 数 引 用 区  *
  188. ********************/

  189. /********************
  190. *   全局变量引用区  *
  191. ********************/

  192. #endif
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入296汤圆

 楼主| 发表于 2008-1-26 02:57:00 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2012-8-1 21:45 编辑

[使用方法]

假设我想建立一个按键缓冲区,我们需要首先声明一个环形队列,名叫PS2KeyBuffer,大小为8个字节
  1. START_DEFINE_QUEUE(PS2KeyBuffer,8,uint8,uint8)
  2. END_DEFINE_QUEUE
复制代码
接下来,我们可以通过以下方法访问这个队列
  1. # define __PUT_DATA(n)          ADD_QUEUE_DATA(PS2KeyBuffer,(n))
  2. # define __GET_DATA(n)          GET_QUEUE_DATA(PS2KeyBuffer,&(n))
  3. # define __GET_QUEUE_COUNT      GET_QUEUE_COUNT(PS2KeyBuffer)
  4. # define __PEEK_DATA(n)         PEEK_QUEUE_DATA(PS2KeyBuffer,&(n))
  5. # define __CHECK_EMPTY          CHECK_QUEUE_EMPTY(PS2KeyBuffer)
复制代码
很方便哈?代码效率也很高哦

出0入0汤圆

发表于 2008-1-26 08:36:35 | 显示全部楼层
呵呵,好东西,先收着

出0入0汤圆

发表于 2008-1-26 10:19:04 | 显示全部楼层
记号

出0入0汤圆

发表于 2008-1-26 10:52:18 | 显示全部楼层
收藏,希望你的好东西都能在你的新书中找到,这样我们买书就很值了。以往买的很多书都是垃圾,相互抄的,期待
楼主的大作早日面世

我的大部分东西都在书中,在DEMO以外的章节中还有专题讲嵌入式相关的数据结构。以实践和实用为主,决不掉书袋。

出0入0汤圆

发表于 2008-1-26 12:11:22 | 显示全部楼层
RD_MacroAndConst.h

是什么头文件,没看过啊,LZ用的是什么编译器?

出0入296汤圆

 楼主| 发表于 2008-1-26 14:10:41 | 显示全部楼层
这个头文件是我自己写的,在我的专栏的顶楼有。
这个模板是C语言通用的,我自己用的是ICC编译器。

出0入0汤圆

发表于 2008-1-26 14:15:59 | 显示全部楼层
好东西,先来个记号

出0入0汤圆

发表于 2008-5-24 23:42:14 | 显示全部楼层
建议楼主共享时提供C文件,刚才试验了一下,错误一大堆,半天才查出来,原来是换行符后面多了空格!
宏定义的错误真不好找

出0入296汤圆

 楼主| 发表于 2008-5-25 02:07:43 | 显示全部楼层
楼上批评的是,我以后一定注意。谢谢您的测试!

出0入0汤圆

发表于 2008-5-25 10:15:02 | 显示全部楼层
中断调用的情况似乎没考虑。

出0入147汤圆

发表于 2008-5-25 10:45:11 | 显示全部楼层
楼主没处理考虑中断应该是为了考虑通用性
是不是可以增加两个开关中断的宏,插入到对队列指针操作得地方
这样在移植到不同平台时只要修改这两个宏就可以了
不用每次在调用的时候关开中断,毕竟只是在修改指针得时候才需要屏蔽中断

出0入296汤圆

 楼主| 发表于 2008-5-25 12:42:28 | 显示全部楼层
我考虑中断了。大家仔细看
SAFE_CODE_PERFORMANCE
(
    ……
)

这个宏就是用来屏蔽中断的。

出0入0汤圆

发表于 2008-5-25 13:31:57 | 显示全部楼层
不是说楼主忘设置临界段了,那个SAFE_CODE_PERFORMANCE我看到了。
我是指,因为楼主使用了SAFE_CODE_PERFORMANCE,如果在中断中调用某个读写函数就会引起中断嵌套错误。
要通用的话,那个SAFE_CODE_PERFORMANCE和那个退出临界段的宏也要是支持中断嵌套的。

出0入296汤圆

 楼主| 发表于 2008-5-25 13:49:55 | 显示全部楼层
to 【14楼】 gingin
    用#undef 和#define 重新定义这个宏就可以根据需要来配置了。
如果可能,尽量不要在中断中使用对队列进行操作的函数。AVR的中断
系统有一个特点,除非同一个中断发生了两次,一般情况下,发生的中
断如果全局响应被关闭时,该中断只是被缓冲了,当全局响应开启时,
AVR会立即响应该中断。

出0入0汤圆

发表于 2008-6-25 00:44:06 | 显示全部楼层
mark~~

出0入0汤圆

发表于 2008-6-25 09:26:52 | 显示全部楼层
记号

出0入0汤圆

发表于 2008-6-25 09:40:28 | 显示全部楼层
没仔细看,不知道和数据结构中的循环队列是不是一个东东??

出0入296汤圆

 楼主| 发表于 2008-6-25 10:43:07 | 显示全部楼层
to 【18楼】 edaworld 笨笨小熊
    就是循环队列哈。

出0入0汤圆

发表于 2008-8-1 18:12:54 | 显示全部楼层
模板啊!!!模板不是不好,不过检错很麻烦,如果出问题,很难检测出来!而且编译器报错时有不能定位~~~

出0入0汤圆

发表于 2008-8-1 21:13:18 | 显示全部楼层
环形队列挺常用,我也用宏写了一个比较简单的,有时间贴上来。

大家有兴趣的话研究研究这个(别人写的),没仔细看,虽不是为单片机写的,可以借鉴一下:
http://bbs.chinaunix.net/viewthread.php?tid=759781&highlight=%B7%B6%D0%CD

出0入0汤圆

发表于 2008-8-27 10:42:34 | 显示全部楼层
哇,Gorgon Meducer 傻孩子
 我一看到上述包含编译开关代码就头痛。

#define QUEUE_MAX_LENGTH 50

typedef struct tagELEMENT
{
        unsigned char bVal;
        unsigned int Addr;
} ELEMENT;

struct EEPROM_QUEUE
{
        ELEMENT element[QUEUE_MAX_LENGTH];
        int rear;
        int front;
};

struct EEPROM_QUEUE QUEUE;

void QUEUE_Init(void)
{
        QUEUE.rear = 0;
        QUEUE.front = 0;
}


BOOL QUEUE_EMPTY(void)
{
        if (QUEUE.rear == QUEUE.front)
                return (TRUE);
        return (FALSE);
}


BOOL QUEUE_FULL(void)
{
        if ((QUEUE.rear+1) % QUEUE_MAX_LENGTH == QUEUE.front)
                return (TRUE);
        return (FALSE);
}


BOOL QUEUE_In(ELEMENT element)
{
        if (!QUEUE_FULL())
        {
                QUEUE.rear = (QUEUE.rear + 1) % QUEUE_MAX_LENGTH;
                QUEUE.element[QUEUE.rear].bVal = element.bVal;
                QUEUE.element[QUEUE.rear].Addr = element.Addr;
                return (TRUE);
        }
        return (FALSE);
}


BOOL QUEUE_Out(ELEMENT *element)
{
        if (!QUEUE_EMPTY())
        {
                QUEUE.front = (QUEUE.front + 1) % QUEUE_MAX_LENGTH;
                element->bVal = QUEUE.element[QUEUE.front].bVal;
                element->Addr = QUEUE.element[QUEUE.front].Addr;
                return (TRUE);
        }
        return (FALSE);
}

出0入0汤圆

发表于 2010-3-23 19:43:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-22 16:58:27 | 显示全部楼层
楼主啊,你发的帖子,AVR端口位操作支持库 ICC,我下载了你的代码,但是现在我却没有,RD_UseBITs.h、RD_MacroAndConst.h和LIB_Config.h这三个头文件。不知道楼主能不能帮个忙,将这三个头文件相应版本的代码发给我,不胜感谢,我的邮箱xyzjacky@sina.com

出0入0汤圆

发表于 2010-4-22 17:17:24 | 显示全部楼层
mark

出0入296汤圆

 楼主| 发表于 2010-4-22 17:27:36 | 显示全部楼层
to 【24楼】 xyzjacky  
    就在我专栏的置顶贴里面。

出0入0汤圆

发表于 2010-4-22 17:34:14 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-6-20 00:03:40 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-6-20 20:19:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-15 14:20:10 | 显示全部楼层
mark

出0入9汤圆

发表于 2010-8-15 14:39:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-12 11:44:13 | 显示全部楼层
ji

出0入0汤圆

发表于 2010-10-12 13:40:39 | 显示全部楼层
标记学习

出0入0汤圆

发表于 2010-10-15 18:31:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-3 12:42:49 | 显示全部楼层
标记学习

出0入0汤圆

发表于 2010-11-3 13:22:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-3 13:30:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-21 00:46:49 | 显示全部楼层
循环队列

出0入0汤圆

发表于 2011-2-21 08:29:59 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-4-12 15:17:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-20 19:43:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-5 10:18:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-24 17:47:09 | 显示全部楼层
多谢傻孩子共享好东东

出0入0汤圆

发表于 2012-1-11 11:03:11 | 显示全部楼层
mark 环形队列

出0入0汤圆

发表于 2012-5-14 21:17:23 | 显示全部楼层
好东西 当然支持

出0入0汤圆

发表于 2012-7-11 15:27:51 | 显示全部楼层
楼主辛苦了,ba_wang_mao的也不错

出0入0汤圆

发表于 2012-8-4 11:28:31 | 显示全部楼层
mark           

出0入0汤圆

发表于 2012-8-6 14:33:21 | 显示全部楼层
mark,学习

出0入0汤圆

发表于 2012-8-6 21:03:56 | 显示全部楼层
学习学习,谢谢.

出0入0汤圆

发表于 2012-8-6 21:04:43 | 显示全部楼层
路过学习一下!!!!!!

出0入0汤圆

发表于 2012-9-27 16:38:32 | 显示全部楼层
经典的,回味!
头像被屏蔽

出0入0汤圆

发表于 2012-10-6 13:51:50 | 显示全部楼层
Gorgon_Meducer 发表于 2008-1-26 02:57
[使用方法]

假设我想建立一个按键缓冲区,我们需要首先声明一个环形队列,名叫PS2KeyBuffer,大小为8个 ...

傻孩子老师您好:有一个关于串口发送中断的问题想请教你一下:
我最近做了一个关于发送中断的工程,关于串口发送中断有一些疑问,我的部分代码如下:
第一种情况:
void transmit_byte(uchar DAT)
{
  uchar tmphead;
  tmphead=(uart_txhead+1)&UART_TX_BUFFER_MASK;//calculate buffer index
  while(tmphead==uart_txtail)// wait for free space in buffer
  {
   ;
  }
  uart_txbuf[tmphead]=DAT;//store data in buffer
  uart_txhead=tmphead;//store new index
  UCSRB|=(1<<UDRIE);//enable UDRE interrupt
}
#pragma interrupt_handler  Usart_txc:14
void Usart_txc()
{
   uchar tmptail;
   if(uart_txhead!=uart_txtail)// check all data is transmitted
   {
    tmptail=(uart_txtail+1)&UART_TX_BUFFER_MASK;//calculate buffer index
        uart_txtail=tmptail;//store new index
        UDR=uart_txbuf[tmptail];//start transmition
   }
  
}
以上两个是发送中断函数,在主程序中是
void main()
{
  while(1)
{
transmit_byte(0x00);
transmit_byte(0x01);

}
}
以上配置的波特率是9600
这是第一种按照发送缓冲区和发送中断函数结合使用的,目前在PC机上可以实现发送功能;
第二种情况:
void  send(uchar DAT)//串口发送一个字节
{         
    while( !(UCSRA & (1<<UDRE)) );
    UDR=DAT;
}
主函数位
void main()
{
  while(1)
{
   send(0x00);
   send(0x01);
}
}
以上配置的波特率是9600

用示波器测上面两种情况 发现波形都是一样的,并没有出现您所说的:用中断发送函数比查询更加节约MCU的时间。有些不懂 请问是怎么回事?怎么可以测出用串口中断发送的数据包比用查询发送的数据包速度快??谢谢傻孩子老师!

出0入296汤圆

 楼主| 发表于 2012-10-6 19:08:52 | 显示全部楼层
taocongrong 发表于 2012-10-6 13:51
傻孩子老师您好:有一个关于串口发送中断的问题想请教你一下:
我最近做了一个关于发送中断的工程,关于 ...

这是很早之前的说法了,当时没有说清楚,其实所谓的节省时间其实非常笼统,更精确的说法是这样的
1、通过中断配合缓冲区的方法,可以使得系统在发送的时候只关注将数据送到缓冲区的过程,而不关注
   发送是否成功这样的细节——也就是说至少不用让系统死等每一个字节都发送成功(也就是所谓的阻
   塞式代码)
2、在同样使用非阻塞代码的情况下,也就是我们所说的多任务的情况下,使用缓冲区可以保证字节发送
   的连续性,不使用缓冲区则字节与字节之间的间隔有可能会随着主循环中要处理的任务数量增加而增
   加——这一现象是跟你用的芯片、跑的时钟频率、波特率以及任务的多少有关系的。要想验证,有两
   种方法,用理论验证,也就是搞清楚轮询模式下while把所有任务跑一圈所需要的周期,这个周期就有
   可能成为字节发送的间隔——这个你自己应该可以想得通;另外一种方法就是用一个较低频率的系统,
   比如AVR跑1M,然后跑多个任务(每一个任务都是 none-block的),然后你应该可以很清晰的看到
   任务的多少与字节与字节之间时间间隔的关系——当然,建议你用高一点的波特率,因为波特率越低
   字节发送所需的时间就越长。

所有这些都是相对的概念,以前说的比较绝对,现在要纠正一下。
头像被屏蔽

出0入0汤圆

发表于 2012-10-7 17:58:19 | 显示全部楼层
本帖最后由 taocongrong 于 2012-10-7 18:10 编辑
Gorgon_Meducer 发表于 2012-10-6 19:08
这是很早之前的说法了,当时没有说清楚,其实所谓的节省时间其实非常笼统,更精确的说法是这样的
1、通过 ...


谢谢您,谢谢傻孩子老师,为什么叫你傻 孩子,你那么聪明,呵呵,不过还是要谢谢你 。

出0入264汤圆

发表于 2012-10-8 20:25:42 | 显示全部楼层
taocongrong 发表于 2012-10-7 17:58
谢谢您,谢谢傻孩子老师,为什么叫你傻 孩子,你那么聪明,呵呵,不过还是要谢谢你 。  ...

之前手机回帖不方便,现在在电脑上面回你。

好像你有个问题没有搞清楚。不管是中断+缓冲方式  还是直接等待发送这种方式,这个效率不是你用示波器测波特率能够测出来的。
对于指定的波特率,难道你能够测出来两种波形???


好了,下面重点讲讲效率的问题。

假设系统中有一个主机, N个从机,通信方式为主机主动发起,从机应答。每个命令包长度为10个字节。
假定波特率9600 bps

则一个命令包长度发送完毕耗时约为 11 ms

采用查询方式发送:

//伪代码,下面函数发送指定 字节, 采用等待方式发送
SendCmdPacket(uint8 * pBuffer, uint8 u8Length)

//伪代码,下面函数发送指定 字节, 采用中断+缓冲方式
SendCmdPacketToBuffer(uint8 * pBuffer, uint8 u8Length)


则调用SendCmdPacket()发送时候,该函数会阻塞 11ms 直到发送完毕

相反,调用SendCmdPacketToBuffer()发送时候,该函数将数据包复制到缓冲区后,立即返回,耗时可能只有不到 0.1 ms 时间
加上中断处理时间 整个数据包发送完毕消耗CPU时间约为 1ms

相比查询方式,中断方式可以多出10ms 时间用来处理其它任务,这10 ms 就是效率!!!
而且通信数据包长度越长,优势越明显。


你的主机系统不可能只有通信任务,如果还有按键,显示等等其它任务,则用中断+缓冲能够提高整个系统的实时性!

明白否?

出0入296汤圆

 楼主| 发表于 2012-10-8 23:55:07 | 显示全部楼层
mcu_lover 发表于 2012-10-8 20:25
之前手机回帖不方便,现在在电脑上面回你。

好像你有个问题没有搞清楚。不管是中断+缓冲方式  还是直接 ...

这个例子举得好。不过他有可能是观测字节与字节之间的时间间隔。在使用none-block代码且任务极少,
波特率不高或者CPU时钟很高的情况下,缓冲法和查询法的区别可能不是几千块钱的示波器能观察得到的。
在这种情况下,只有none-block的任务增多,波特率比较高,CPU时钟比较低的情况下才可能从示波器上
观测到字节与字节之间时间价格的显著差异——用中断+缓冲法比单纯的查询法字节间距离更小。
头像被屏蔽

出0入0汤圆

发表于 2012-10-11 17:32:33 | 显示全部楼层
头像被屏蔽

出0入0汤圆

发表于 2012-11-2 14:23:29 | 显示全部楼层
Gorgon_Meducer 发表于 2012-10-6 19:08
这是很早之前的说法了,当时没有说清楚,其实所谓的节省时间其实非常笼统,更精确的说法是这样的
1、通过 ...

王老师 你说的 你的版块中的状态机的名字叫什么啊!

出0入296汤圆

 楼主| 发表于 2012-11-2 18:28:05 | 显示全部楼层
taocongrong 发表于 2012-11-2 14:23
王老师 你说的 你的版块中的状态机的名字叫什么啊!

[FSM]状态机入门——程咬金只有三板斧厉害

出0入0汤圆

发表于 2012-11-28 22:49:16 | 显示全部楼层
太经典了,谢谢楼长!

出0入0汤圆

发表于 2012-11-29 23:22:09 | 显示全部楼层
能不能上传一个完整的程序Demo?

出0入0汤圆

发表于 2013-2-5 16:53:28 | 显示全部楼层
lz强悍....

出0入0汤圆

发表于 2013-2-7 10:44:03 | 显示全部楼层
看的有点吃力,楼主能不能先介绍点相关的书籍,先补补基础

出0入0汤圆

发表于 2013-2-7 10:54:35 | 显示全部楼层
好东西。。谢谢

出0入296汤圆

 楼主| 发表于 2013-2-7 23:15:57 | 显示全部楼层
feiante116 发表于 2013-2-7 10:44
看的有点吃力,楼主能不能先介绍点相关的书籍,先补补基础

先看看数据结构吧。现在有很多书都是用C语言来介绍数据结构的。

出0入0汤圆

发表于 2013-3-5 15:43:12 | 显示全部楼层
第140行的 s_Queue##__NAME##PeekCounter++;是不是多余的?

出0入296汤圆

 楼主| 发表于 2013-3-5 17:03:03 | 显示全部楼层
sbk100 发表于 2013-3-5 15:43
第140行的 s_Queue##__NAME##PeekCounter++;是不是多余的?

141代码有点问题,我更新了。谢谢你。

出0入0汤圆

发表于 2013-3-11 09:12:00 | 显示全部楼层
在什么情况下用Peek_Extend()这个函数呢?

出0入0汤圆

发表于 2013-3-12 09:29:36 | 显示全部楼层
傻孩子大虾,我用了这个头文件,编译也是错误一堆啊~,现在不知道错在哪里了啊~

出0入0汤圆

发表于 2013-3-12 09:50:43 | 显示全部楼层
有5个错误,都是类似这种:syntax error; found `Queue_PS2KeyBuffer_Add_Data' expecting `;'

出0入296汤圆

 楼主| 发表于 2013-3-12 12:45:35 | 显示全部楼层
abcdzhy 发表于 2013-3-12 09:50
有5个错误,都是类似这种:syntax error; found `Queue_PS2KeyBuffer_Add_Data' expecting `;' ...

用这个帖子里面我提供的模板http://www.amobbs.com/thread-5515836-1-1.html

出0入0汤圆

发表于 2013-3-12 14:22:18 | 显示全部楼层
Gorgon_Meducer 发表于 2008-1-26 02:57
[使用方法]

假设我想建立一个按键缓冲区,我们需要首先声明一个环形队列,名叫PS2KeyBuffer,大小为8个 ...

请问傻孩子,你这个模板相对与用纯c写的有何优势,效率高怎么体现的?感觉这样代码不容易读,倒是代码量少了很多,相对的也比较花心思。

出0入0汤圆

发表于 2013-3-12 14:46:20 | 显示全部楼层
多谢傻孩子大虾,我去研究下!

出0入0汤圆

发表于 2013-3-12 14:55:48 | 显示全部楼层
收藏一下

出0入0汤圆

发表于 2013-3-12 15:16:47 | 显示全部楼层
本帖最后由 abcdzhy 于 2013-3-12 15:29 编辑

找到错的原因了,是我没有定义BOOL,改成bool就没错了。你现在写的那个看着很高深啊,我粗看了一下,感觉少了这个原子操作的定义:__ATOM_ACCESS,不知道是我没找到还是怎么回事。还有就是老版的这个版本有这个定义# define END_DEFINE_QUEUE,没看到这个有什么作用啊!

出0入296汤圆

 楼主| 发表于 2013-3-12 18:40:58 | 显示全部楼层
meirenai 发表于 2013-3-12 14:22
请问傻孩子,你这个模板相对与用纯c写的有何优势,效率高怎么体现的?感觉这样代码不容易读,倒是代码量 ...

一次操心,终身受益。也就是,只要你一次获得了可靠的代码,以后你就可以稳定的获得同样的结果。

出0入296汤圆

 楼主| 发表于 2013-3-12 18:46:21 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-3-12 18:56 编辑
abcdzhy 发表于 2013-3-12 15:16
找到错的原因了,是我没有定义BOOL,改成bool就没错了。你现在写的那个看着很高深啊,我粗看了一下,感觉少 ...


关于原子操作的宏,看 DEF_SAFE_QUEUE 和 DEF_QUEUE 两个宏的定义。
另外一个问题,关于宏# define END_DEFINE_QUEUE,这是为了保证各式上的一致,同时也是为了以后能够扩展宏的功能或者结构留下伏笔。

出0入0汤圆

发表于 2013-3-12 20:28:50 | 显示全部楼层
多谢傻孩子大虾回复!

出0入0汤圆

发表于 2013-3-23 18:35:58 | 显示全部楼层
谢谢楼主  学习了

出0入0汤圆

发表于 2013-4-7 18:51:52 | 显示全部楼层
mark。。。。。。。。。。。。。

出0入0汤圆

发表于 2013-4-8 14:20:19 | 显示全部楼层
mark……

出0入0汤圆

发表于 2013-5-23 22:09:06 | 显示全部楼层
环形队列,高端

出0入0汤圆

发表于 2014-1-1 00:49:00 | 显示全部楼层
看不懂·····要学的好多···路要慢慢走···

出0入0汤圆

发表于 2014-1-6 11:12:03 | 显示全部楼层
Gorgon_Meducer 发表于 2013-3-5 17:03
141代码有点问题,我更新了。谢谢你。

傻孩子,每次关注你的版块,你都能够帮助一些热心的坛友解决问题,我个人感觉你在嵌入式C的算法方法,研究的比较透,是否可以考虑出一本这方面的书,我挺期待的,呵呵......

出0入296汤圆

 楼主| 发表于 2014-1-6 15:27:00 | 显示全部楼层
lpdpzc 发表于 2014-1-6 11:12
傻孩子,每次关注你的版块,你都能够帮助一些热心的坛友解决问题,我个人感觉你在嵌入式C的算法方法,研 ...

谢谢哈,我也有这个计划,看这个帖子
http://www.amobbs.com/thread-5506790-1-1.html

最近在忙一些大家伙,暂时缓了缓。不过2014年会是一个很有成果的年份。谢谢关注哈。不过与其等书,不如有什么
实际问题一起拿出来我们在这里交流交流更直接哈。

出0入0汤圆

发表于 2014-1-12 22:22:18 | 显示全部楼层
mark...................

出0入0汤圆

发表于 2015-8-14 22:50:31 | 显示全部楼层
mark一 下,傻孩子 的环形队列  
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-27 12:13

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

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