搜索
bottom↓
回复: 9

马老师书USART一章中有一个问题,请指教

[复制链接]

出0入0汤圆

发表于 2013-2-19 16:53:31 | 显示全部楼层 |阅读模式
在第一版中 USART实用设计基础 , P404页第十四行 ,
if(++rx_counter==RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
}
这几条语句的意思只能说明,接受缓冲区已满,此时并没有溢出,而是刚刚满,这时如果把rx_counter=0;那下面的程序会判断rx_counter的值,如果是0就不会执行了。
请读过此书的PY帮忙解释一下!

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-2-20 01:30:30 | 显示全部楼层
就是要在刚刚满的时候通过rx_buffer_overflow告知主程序取走缓冲区里的数据,否则下一个数据将覆盖前面的数据导致前面接收数据作废。

出0入0汤圆

 楼主| 发表于 2013-2-20 06:18:16 | 显示全部楼层
tearsman520 发表于 2013-2-20 01:30
就是要在刚刚满的时候通过rx_buffer_overflow告知主程序取走缓冲区里的数据,否则下一个数据将覆盖前面的数 ...

如果刚刚满就执行rx_counter=0;的话,那缓存区最多只能存7个数据,存第8个数据的时候,下面的while(rx_counter==0);就会一直等待,认为缓存区没有数据,而实际是有8个数据没有处理。

出0入0汤圆

发表于 2013-2-20 18:59:20 | 显示全部楼层
faw 发表于 2013-2-20 06:18
如果刚刚满就执行rx_counter=0;的话,那缓存区最多只能存7个数据,存第8个数据的时候,下面的while(rx_co ...

你需要全面地看一下这个程序,完整的接收程序是这样的:
// USART Receiver interrupt service routine

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;

      };

   };

}



#ifndef _DEBUG_TERMINAL_IO_

// Get a character from the USART Receiver buffer

#define _ALTERNATE_GETCHAR_

#pragma used+

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;

}

#pragma used-

#endif

你有疑问的 if (++rx_counter == RX_BUFFER_SIZE) 这段语句是放在USART接收中断里执行的,而接收中断是配合getchar()这个函数去做的,正常的使用流程是:调用getchar()→等待用户输入→RX中断产生→getchar返回用户输入的字符。在getchar函数里,只要rx_counter不为0,就立刻返回数据,同时rx_counter-1,因此你说的情况是不可能发生的。除非用户以超过MCU指令执行频率的速度敲击键盘,并且键盘的反应也超过MCU指令执行频率,才会出现你说的情况。

出0入0汤圆

 楼主| 发表于 2013-2-21 06:57:07 | 显示全部楼层
tearsman520 发表于 2013-2-20 18:59
你需要全面地看一下这个程序,完整的接收程序是这样的:
// USART Receiver interrupt service routine
  ...

我已经全面地看过程序好几遍了,可是还是想不通,我认为 getchar()函数应该配合中断函数一起执行,但是接收中断时可以中断getchar()函数的,假设我串口一起发送10个数据,00~09,那你说此时程序怎么处理。是能接收到三个数据,还是全能接收到!(你的意思是,接收到一个就读出去一个,根本不可能接收到8个数据,我可以这样理解吗?(那是不是也根本不可能接收到5个数据?或更少3个数据?))
可能是我想的有点偏激,但知识就是这样的,不弄透了也记不住啊。

出0入85汤圆

发表于 2013-2-21 08:54:10 | 显示全部楼层
这个是环形队列的,当缓冲区队列满时清除rx_counter,在主程序中如果要读会有一个接收数据的延迟,缓冲队列只是为了弥补主程序任务多时带来的串口事件处理的不及时,但我觉得不能无限制的影响串口事件的处理,如果你的主程序任务较多,你可以增加缓冲队列的长度

出0入36汤圆

发表于 2013-2-21 09:20:09 | 显示全部楼层
楼主提出来了,就说明楼主思考过了,会否是书中笔误呢?等待马老师解说

出0入0汤圆

发表于 2013-2-26 13:42:31 | 显示全部楼层
faw 发表于 2013-2-21 06:57
我已经全面地看过程序好几遍了,可是还是想不通,我认为 getchar()函数应该配合中断函数一起执行,但是接 ...

依照你的假设,串口一起发10个数据,需要说明的是,在发送这10个数据之前,用户已经调用getchar这个函数了,因为getchar()这个函数的目的就是为了返回USART口接收到的数据。

现在再看,USART波特率就按最高的算115200bps,这表示中断的频率是115200/10=11520Hz(只有接收到完整的一个字节时才会产生中断,USART协议包括起始位停止位,所以,一个字节是10bit)。

那么,中断的间隔就是1/11520,约为86.8微秒,也就是说,一个中断产生后,可供程序处理的时间是86.8微秒,除去中断产生、结束时现场保护和现场恢复的时间,假设20微秒,那么getchar()函数还是有66.8微秒的时间,把一个数据返回。现在假设AVR的频率就只有1MHz,其指令执行速度为1MIPS,那么粗略估计getcha()函数只需要不到20微秒的时间就可返回一个字节。何况,程序还开设了缓冲区。有什么道理不能返回这10个字节呢??

当然,如果用户编程不当,是会出现你所说的情况的,就是说,由于用户其他程序的结构问题,导致MCU无法及时从缓冲区取走数据,就会产生数据丢失。

出0入0汤圆

 楼主| 发表于 2013-3-2 12:19:42 | 显示全部楼层
tearsman520 发表于 2013-2-26 13:42
依照你的假设,串口一起发10个数据,需要说明的是,在发送这10个数据之前,用户已经调用getchar这个函数 ...

多谢指点,现在总算是明白了!经过实际编程测试过,果然不会出现上述的情况!

出0入0汤圆

发表于 2013-3-22 23:57:05 | 显示全部楼层
学习了,也迷茫了几天,好像清楚了 ,还是有点模糊 ,再看看书
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-3-29 08:59

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

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