打印

请教一下农民讲习所

[复制链接]
楼主: 一只小绵羊
手机看帖
扫描二维码
随时随地手机跟帖
41
批判一下这些歪理:
没看懂38楼的一堆解释,但归根结底,没法改变“ *( pQueueBuffer->pIn++ % ILEN ) = mData ;” 这个写法是错误的事实。类似的写法早见过,人家是这么用:
index++;
index = (index%BUFFER_SIZE);
RxBuffer[index]  = data;
而你的pQueueBuffer->pIn的数值是绝对地址,并不是数组内的偏移量。“ *( pQueueBuffer->pIn++ % ILEN ) = mData ;” 这个写**把别的内存地址改写的,大错特错了,呵呵。
提个小建议:如果你觉得我等低手的水平太低,以后也别再把错的程序摆上来让我们“容易看懂”,我等低手本来水平就低,还要给您老人家的程序“纠错”后再“消化理解”,难度太大。
还有39楼的歪理:
“mCount = pIn - pOut ; ”?后边又加个绝对值?您老人家没自己试试? 举个最简单的例子:pIn的值为aBufferStart,pOut的值为aBufferEnd-2时,请问未读字节的数量是多少?再用您的公式算算?mCount = |pIn - pOut| ;  等于BUFFER_SIZE-2了!高手就是高手,我等低手就是理解不了。

使用特权

评论回复
42
desert_hawk| | 2010-1-5 19:18 | 只看该作者
to 40楼:
楼主举得例子是ARM的。可以看2楼的汇编码。

使用特权

评论回复
43
冷漠| | 2010-1-5 20:11 | 只看该作者
本帖最后由 冷漠 于 2010-1-5 21:29 编辑

41楼真会开玩笑,“*( pQueueBuffer->pIn++ % ILEN ) = mData ;  //(1)” 高手抓这种细节 ?您在37楼刚刚告诉我 :
void         **OSQStart;            /* Pointer to start of queue data               

没事,菜鸟给您写个看得懂的:

aBufferStart [ ( pQueueBuffer->pIn - aBufferStart ) % ILEN ] = mData;  //(2)
假设ILEN=16。

有意思吗? 请41楼高手推论一下,(2)式和(1)式差在哪?谁对?咱是菜鸟,向您学习。

使用特权

评论回复
44
一只小绵羊|  楼主 | 2010-1-5 20:24 | 只看该作者
本帖最后由 一只小绵羊 于 2010-1-5 20:27 编辑

if  ((( pQueueBuffer->pIn ) % ILEN ) !=  pQueueBuffer->pOut )
       *( pQueueBuffer->pIn++ % ILEN ) = mData ;

假设经过这个以后pIN==pOut了,那么再来数据就会丢弃后来数据。
执行
char Queue_Pop( struct QueueBuffer idata *pQueueBuffer )
{   
        while( pOut!=pInt )
       return *( pQueueBuffer->pOut++ % ILEN );
}
也不会弹出数据,是不是就死了

使用特权

评论回复
45
冷漠| | 2010-1-5 20:56 | 只看该作者
37楼连操作系统都上来了?
  void   **OSQIn;     /* Pointer to where next message will be inserted  in   the Q  */
  void   **OSQOut;    /* Pointer to where next message will be extracted from the Q  */
  INT16U   OSQSize;    /* Size of queue (maximum number of entries)                   */
   INT16U  OSQEntries;      /* Current number of entries in the queue                      */

书上图画的清清楚楚,OSQEntries = OSQIn - QOut;  怎么避而不谈。
  
OSQEntries 是操作系统需要用到的变量,难道用户您想把手伸到操作系统内核对象里?您也要用OSQEntries —— mCount ?高啊。

所长可是在裸奔,他自称从来看不上操作系统。呵呵,原来所长也抄书?

再说操作系统的系统函数都是原子性的,整个函数都必须像一条语句一样连续完成。还用得着内部为某个对象互斥?累不累?
举例:如果OS系统函数P(S)/P(V)/P(mutex)这类任务管理函数内部被系统心跳中断的话,还谈什么任务管理?

使用特权

评论回复
46
desert_hawk| | 2010-1-5 21:07 | 只看该作者
哪本书告诉你的“OSQEntries = OSQIn - QOut;”?我只相信源代码。
又是哪个名人说的“互斥”是操作系统的专利?

使用特权

评论回复
47
desert_hawk| | 2010-1-5 21:10 | 只看该作者
本帖最后由 desert_hawk 于 2010-1-5 21:15 编辑

发个裸奔的:
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer[rx_wr_index]=data;
   if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
      rx_buffer_overflow=1;
      };
   };
}

char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
这是CVAVR编译器的用户向导生成的代码,可不是我等低手的原创。

使用特权

评论回复
48
冷漠| | 2010-1-5 21:35 | 只看该作者
本帖最后由 冷漠 于 2010-1-5 21:41 编辑

回44楼,说的没错,是有这个问题。解决方法很简单,18楼做过了。
原理:push( )函数中,pIn 追赶 pOut 时,“缓冲区满”条件修改为 pIn++=pOut;不重合,即可。pop( ) 可以重合。模拟堆栈操作即可。

方法2:设定一个全局 bit 标志 full; 在 push()中, pIn=pOut 时,标志
full = true。
pop()中,利用这个标志。

使用特权

评论回复
49
原野之狼| | 2010-1-6 03:04 | 只看该作者
1 冷漠大侠一开始给出的程序确实有问题,所以我才问这个ILEN表示啥意思。当然有可能您是写的伪码。
2 农民伯伯的程序这么写能比较易懂。
3 农民伯伯的程序中count变量可以不用的,但是得改造下队列的头尾指针的位置。
4 不管是采用农民伯伯的做法还是采用冷漠大侠的做法,都得进行互斥操作。
5 当然不互斥也是可以的,得有条件,条件就是
  A 改造下队列的结构
  B 把指针改成索引
  C 队列长度小于255

使用特权

评论回复
50
冷漠| | 2010-1-6 09:49 | 只看该作者
版主说的是正理,咱们讨论的是mCount这个成员有没有用的问题。即使要用到,能不能根据已知条件计算出来?——化为局部变量,而非共享变量的问题。看来41楼和46楼认为这种计算无法实现,只能作为共享变量在push( )函数内mCount++,pop( )函数内mCount++,

哪本书告诉你的“OSQEntries = OSQIn - QOut;”?我只相信源代码。

还有39楼的歪理:
“mCount = pIn - pOut ; ”?后边又加个绝对值?您老人家没自己试试? .....


看来对41楼和46楼来说,利用函数内部已知条件缩小mCount的作用域,是很困难到事情?至少他想不出个好的解决方案。他只好将其扩大为共享全局变量,这个函数实现mCount++,再利用那个函数实现mCount--,然后再使用互斥机制......
     呵呵,能不能再多想想?你自己想不出来就认为别人也不行?这么简单的问题,......这是不是中外程序员的差距?很简单的问题,我们只能用很复杂的方法。谁能够不用互斥机制解决这个问题,他就可以藐视中国程序员。他就比你强一点点,就欺负你的土**没他的钢**打得远。

     我也学学怎么藐视别人?——如果一定要追究我的mCout=pIn-pOut的正确性,只能说你看不懂伪代码,要不要我把它写全,然后让谁下不来台?有意思吗?现在兴“技术决斗”(钢琴决斗),没有恶意,就是为了更好地互相学习,请41/46 楼先来.......

使用特权

评论回复
51
冷漠| | 2010-1-6 10:00 | 只看该作者
忘了:关于哪本书告诉我下面:
OSQEntries = OSQIn - QOut;

请见《uC/OS-II 》第2版 P246 ,还是37楼推荐我去看的,自己倒问起哪本书上写的?

使用特权

评论回复
52
desert_hawk| | 2010-1-6 10:36 | 只看该作者
本帖最后由 desert_hawk 于 2010-1-6 10:37 编辑

“我也学学怎么藐视别人?”这个你就不用学了,因为据我观察在“藐视别人”这方面,你已经很出色。“故意这样写只是为了让您看得懂。把书抄来您不一定看得懂。”“这么简单的解决方案您还没看懂?”看看这些,你还用学“怎么藐视别人”?

  再谈点技术方面的:不用mCount,把未读字节的数量计算出来,当然可以,但让您老给个解决方案,最后弄了个|pIn - pOut|,然后又说是“伪代码”“伪公式”。我才能不足,就不研究这些“伪”的东西了。注意我在35楼说的是“没法简便的得到”,并没说“不能得到”。计算出来,我想了一下可以用下面的程序:
if(pIn >= pOut) mCount = pIn - pOut;
else  mCount = BUFFER_SIZE - (pOut - pIn);
而这个mCount又是随时可能改变的,不是计算一次就可以一直用下去,我想如果程序中如果需要频繁使用mCount这个变量,每次都使用这种相对麻烦的计算,还不如直接定义一个全局变量mCount省事吧?所谓互斥访问,也只是一条C语句前后的关中断而已,会有多大损失?

“技术决斗”,本人对这个没多大兴趣,我觉得来这个论坛的人,没有几个是以这个目的来的。我记得冷漠大侠似乎对这个兴趣也不大,因为去年我刚开始上这个论坛的时候,就看见有人找你PK,并没见你“应战”,呵呵。
  
至于“OSQEntries = OSQIn - QOut;” 我并没有见源代码里是这么计算的,而且显而易见这么计算肯定是错的。可能又是“伪公式”。我没有ucosii的书,只有电子版的,也没有找到此公式。

技术方面的东西,我已经把我的观点表达完了,至于某些高手对我观点的不认同甚至不屑,呵呵,随他去吧,这个世界本来就是多元化的,对同一件事,不同的人有不同看法,这都很正常。只是提个小建议:讨论问题不要以一种“冷嘲热讽”的态度,让人很不舒服。OK,本人就此打住,在说下去也没什么意思了。

使用特权

评论回复
53
冷漠| | 2010-1-6 11:03 | 只看该作者
本帖最后由 冷漠 于 2010-1-6 11:04 编辑

唉,人和人就差那么一点点。
if(pIn >= pOut) mCount = pIn - pOut;
else  mCount = BUFFER_SIZE - (pOut - pIn);

提醒你:什么叫三目运算符?

我们只会if...else...? 把简单的事复杂化谁都会...
没事,能够受人一点启发,能够让老师给一点点指导,能够做到别人很少想到的事,别说对我冷嘲热讽,就是棍棒、羞辱我都愿意。

别人可以为了研究“蚊子喜欢叮咬什么样的人”而花费30年,我们行吗?这么个简单问题,还能化简吗?化3天时间再想想行不行?

使用特权

评论回复
54
xlsbz| | 2010-1-6 11:43 | 只看该作者
想知道互斥的 看看这个帖子 可能会得到点提示

https://bbs.21ic.com/viewthread.php?tid=47713&highlight=


另外 好像楼上几位提到了三目运算符。

让我这个高人来解释一下。

所谓三目运算符,就是没有必要学会的运算符。

使用特权

评论回复
55
desert_hawk| | 2010-1-6 12:25 | 只看该作者
不好意思,还得说一句:
看了关于“三目运算符”的提示,的确受到了一点启发,用三目运算符,在用C编程的时候会简便一些,毕竟只有一行。但我觉得
mCount = pIn>=pOut?pIn-pOut:BUFFER_SIZE-(pOut-pIn);

if(pIn >= pOut) mCount = pIn - pOut;
else  mCount = BUFFER_SIZE - (pOut - pIn);
这两种写法在被编译后,结果应该不会差很多,尤其是对ARM这种无法对全局变量直接寻址的架构,会被编译成很多条指令,而考虑编程方法时,不应该只考虑怎么写省事吧,人省事了,CPU不见得省事。

使用特权

评论回复
56
冷漠| | 2010-1-6 14:03 | 只看该作者
本帖最后由 冷漠 于 2010-1-6 14:21 编辑

嘻嘻。没事,还没完呢。还有绝招呢?——越往后,能够想到的人就越少。大家应该感谢我:
最后一个化简:
采用什么方法,能够使得在任何(合理范围)情况下,都保证下面计算公式是正确的?(合理,例如 char8 或者 int16 范围内。假定取缓冲区长度ILEN=16。)

mCount = pIn - pOut;   // 也就是说,pIn 总是大于 pOut 。mCount 永远是正整数。

还是那句话:别人怎么想的到?我们怎么不行?

如果我能证明,41楼是不是应该向我道歉?谁看不懂,是他自己的问题,怎么是别人“歪理”?读不懂爱因斯坦的人多的是,我跟着他们说爱因斯坦是大忽悠?

呵呵。

使用特权

评论回复
57
desert_hawk| | 2010-1-6 15:35 | 只看该作者
行了,别自圆其说啦,只会显得很荒谬。道歉的问题,我认为,呵呵,没啥必要。

使用特权

评论回复
58
冷漠| | 2010-1-6 21:13 | 只看该作者
本帖最后由 冷漠 于 2010-1-6 21:33 编辑

呵呵,看看那边 lxyppc 怎么“自圆其说”,荒谬地拿走 300元。别人怎么想的到?57楼怎么就想不到呢?还理直气壮“歪理”。

教你一点:环形缓冲器是个环,没头没尾。别以数组的概念去理解和处理。所以,pOut / pIn 的值绕环一直增长,达到uchar, uint 原理上都是对的,所以,pOut 永远滞后于 pIn ,mCount=pIn - pOut 成立。跟 lxyppc 多学习学习怎么考虑问题,还差得远呢。

提示: start [  pIn % ILEN ]  运算并不改变 pIn 的值。

使用特权

评论回复
59
desert_hawk| | 2010-1-6 22:03 | 只看该作者
发现跟冷漠讨论问题,难度真的很大。到现在为止,这个帖子的讨论,有没有人说过缓冲区的大小是2的n次幂?
如果没有,你让pOut / pIn一直增长然后溢出就有问题了。 别告诉我你在39的“伟大公式”是在心里默念着“缓冲区的大小是2的n次幂”而推导出的,而后不知道哪根神经又告诉你可能还需要加个绝对值。而且我记得你在以前摆出的程序中pOut / pIn都是指针啊,怎么到楼上变索引了?你这东变西变的,而且还有可能是“伪”的,而且还可能有“某个条件”需要24小时之后再通知的。呵呵,我彻底服了。投降!
好吧,您在39楼的大作,那是绝对的正确,绝对的真理,比爱因斯坦们强! OK?
即便如此,我也不觉得每次都对索引进行pIn % ILEN运算,然后pIn - pOut得到mCount比直接定义一个mCount的全局变量更简便。over。

使用特权

评论回复
60
icmap| | 2010-1-6 22:23 | 只看该作者
环形队列如果用到了 Pin 和 Pout 这两个头尾指针,那么 mCount 完全就是多余的,而且还导致不能在中断中和中断外同时对队列进行读写操作。
所长认为完美的键盘处理方法也不够好,例如没有针对每一个按键的独立抗抖处理,没有判别矩形三键冲突。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则