搜索
bottom↓
回复: 2

老师,书中USART例程里开关中断不懂

[复制链接]

出0入0汤圆

发表于 2009-12-13 14:51:20 | 显示全部楼层 |阅读模式
// USART Transmitter interrupt service routine
ISR(USART_TXC_vect)
{
    if (tx_counter)
    {
        --tx_counter;
        UDR=tx_buffer[tx_rd_index];
        if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
    }
}

void Putchar(unsigned char c)
{
    while (tx_counter == TX_BUFFER_SIZE);
    cli();////
    if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
    {
        tx_buffer[tx_wr_index]=c;
        if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
        ++tx_counter;
    }
    else
        UDR=c;
    sei();////
}

程序从网上下的,没有教材。Putchar里的关中断和开中断,看了您置顶的那个帖子,您说是为了保护防止频繁读写对数据的破坏。我想了很久,也没想到到底什么情况下会遭到破坏。tx_counter是在写进数据之后才++的,在这之前是没有影响读数据的。还有接收结束中断为什么不用UDRE中断?  老师给讲讲。:)     PS:这个缓冲区挺巧妙的,呵呵。

出0入0汤圆

发表于 2009-12-13 15:50:36 | 显示全部楼层
1。Putchar是提供用户的API,它可能会被上面的发送中断被打断。看下面:

    cli();////
    if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
    {
        tx_buffer[tx_wr_index]=c;
        if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
        ++tx_counter;
    }
    else
        UDR=c;
    sei();////

  如果if语句执行完后被发送中断打断了,那么在中断中tx_counter要被修改的,这样中断返回后,tx_counter已经不是原来IF判断时的值了。另外如果缓冲区比较大,超过255,那么tx_counter就是整形16位的数,对tx_counter的操作,比如++,需要几条指令才能完成,如果加了一半时被中断打断了,中断中的tx_counter就可能不对的。
  关键是tx_counter这个变量,称为临界变量。因为它在中断中需要使用并被改变,所以在上层代码中对 tx_counter的操作需要采用“原子操作”。意思是对其操作过程是“原子”的,不能被打断。这里关中断,然后开中断,就是保证这个“原子操作”。

    如果不这样做,这就是一个隐藏非常深的BUG,不容易发现(因为不是没次都会产生问题)。很多产品偶尔会出现问题,但就是找不出原因,通常软件中存在类似这样的BUG。

2。第2个问题好象你问错了,应该是问发送中断吧。
   AVR的USART有3个中断,接收一个,发送2个:发送完成(完成中断)和发送缓冲区空(空中断)。
   发送缓冲区空并不意味着这个字节已经发送出去了,它表示程序写到发送缓冲区的数据已经到了发送端的移位寄存器中了(产生空中断),这个数据还需要经过10个(或更多)USART的CLK,由硬件一个位一个位的串出去。直到最后一个停止位串出后,这才是发送完成(完成中断)。这两个中断的时间是有先后的。
   程序写一个字节到发送缓冲区后,该字节进入移位寄存器中被硬件发送,此时产生“空中断”,尽管移位寄存器中还在发送这个字节,但程序可以把下一个需要发送的字节写到发送缓冲区了。这样当移位寄存器串出前一个字节后,马上就会接者串第2个字节,否则就要等程序写入第2个字节再串出去。后者效率就低了。

3。在应用中两个中断都可以使用,但方法是不同的。
   使用完成中断比较保险,不容易出问题,代码也比较简单,建议一般人使用。
   而使用空中断可以提高效率,加快发送数据的速度(发送多个字节时,字节可以一个紧接一个的发送,不需要等待)。对于一次发送大批量数据的情况下,最好使用“空中断”,但还是需要与“完成中断”配合去确定最后一个字节的发送情况:因为要确认最后一个字节也彻底发送完了,就要看“完成中断”了,而不时“空中断”了。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-3 06:21

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

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