搜索
bottom↓
回复: 7

求助,AVR的中断函数响应时间

[复制链接]

出0入0汤圆

发表于 2009-3-30 21:19:41 | 显示全部楼层 |阅读模式
最近在调个东西,在串口中断子程序里有一些处理。但是发现效率很低,57600bps已经不堪重负了。
程序是C写的,看了中断子程序的汇编,前面光寄存器进栈就将近20个,太多了,这样进栈出栈就费了将近100 cycle了。
AVR的寄存器多,在这里变成了缺点。
哪位高人有什么经验吗,指点指点吧。IAR C编译器能不能限制寄存器使用范围?

不要告诉我用汇编,容易死人。

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

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2009-3-30 22:23:07 | 显示全部楼层
可以考虑用 用裸中断+内嵌汇编

出0入0汤圆

发表于 2009-3-31 11:51:47 | 显示全部楼层
唉,老生长谈。
 怎么能在“串口中断子程序里有一些处理”呢?

  正确的解决办法:
   (1)、采用“中断”+缓冲区方式
   (2)、串口中断只负责接收数据,然后装入缓冲区中
   (3)、把所有的处理程序放到主程序中。
   (4)、定时中断服务程序要尽可能的短,否则会长时间打断“串口中断”,导致后面的数据挤掉前面的数据。
        如果不能保证定时中断服务程序短,则允许中断嵌套,一进入定时中断就执行SEI(),开放全局中断。(不提倡)

出0入0汤圆

 楼主| 发表于 2009-3-31 21:48:44 | 显示全部楼层
呵呵,谢谢楼上的这位兄弟提醒,确实,这是一般原则,应该遵守。

不过我这里情况有点特殊,
1. 我是在串口中断里用timer做了个timeout, 就是收完一帧数据之后就会timeout, 这样就可以判断一帧收完了。atmel的arm上面uart硬件有这个功能,很好用,想在avr上实现一下。
2. 每帧数据想算一下校验和,还想进一步地判断一下本机地址,如果不是立即丢掉。
这样中断里的动作就多了。
3. 说是中断里的一些处理,实际上就几行而已,居然就用了那么多寄存器。

如果不放在中端里判断,怕是没等到主程序去处理,AVR那点可怜的ram已经装满了。
本以为串口是个低速设备,8位的怎么也能处理得来,结果还有点难度,呵呵。

还是谢谢楼上的兄弟提醒,应该遵守原则,我改改程序试试。

出0入0汤圆

发表于 2009-4-1 10:05:08 | 显示全部楼层
fantaq :
  看了你的叙述,
  1. 我是在串口中断里用timer做了个timeout, 就是收完一帧数据之后就会timeout, 这样就可以判断一帧收完了。atmel的arm上面   uart硬件有这个功能,很好用,想在avr上实现一下。
  2. 每帧数据想算一下校验和,还想进一步地判断一下本机地址,如果不是立即丢掉。  
   这样中断里的动作就多了。
  3. 说是中断里的一些处理,实际上就几行而已,居然就用了那么多寄存器。
   如果不放在中端里判断,怕是没等到主程序去处理,AVR那点可怜的ram已经装满了。
   本以为串口是个低速设备,8位的怎么也能处理得来,结果还有点难度,呵呵。

 
  看了你的叙述1,好像你借用了MODBUS协议的规则,其实MODBUS协议接收到一个字符之后,就开启定时器开始计时,当3.5个字符的静止时间内还未接收到“下一个字符”,就认为已经接收到完整的一帧数据。
    我的所有数据帧分析全部放在主程序中,编写了MODBUS协议2年来,从没有出现过问题,从波特率1200-115200,PC机定时每隔50ms
不停的发送,通讯质量都非常好。
    超时可以在定时中断服务程序中判断,每来一次定时中断,就将超时时间-1,当超时时间减到0,就认为已经接收到一帧完整的数据,然后再判断接收指针是否合法。

  下面是我的接收中断服务程序:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                可靠地判断帧结束,防止通信停滞
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 利用单独的软件定时器,来判断一帧接收报文结束,可以防止若报文接收不完整,该帧通信任务无法结束而影响下一帧的接收。
//由于一帧报文中字节与字节之间的时间间隔和帧与帧之间的时间间隔相比要小得多,因此每当接收一个新字节,就启动软件定时器
//开始计时,定时器的时间设定为帧与帧的最小时间间隔。波特率不同,该时间间隔也不同。
//  (1).若不到预定的时间内又接收到下一个字节,则说明一帧报文未结束,定时器重新计时;若定时器顺利计数到预定时间,就
//会触发相应的中断号,在该定时器中断子程序中设定帧结束标志字节,表明一帧报文接收完毕。
// (2).当主程序内检测到一帧报文接收完毕后,会通过核查从方地址及循环冗余校验字节是否正确来判断该帧的有效性。若确定
//接收到的是一帧发送给已方的正确报文,则会根据报文内的功能码对该帧命令进行相应的处理,并准备发送帧。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma interrupt_handler USART1_RI_ISR:iv_USART1_RX
void USART1_RI_ISR(void)
{
    INT8U ch;
    INT8U status;

    status = UCSR1A;
    ch = UDR1;
    if (USART1_receCount < (MSCOMM_BUFFER_LENGTH)
        USART1_mscomm_buffer[USART1_receCount++] = ch;
    USART1_receTimeOut = 2;//设置超时计时
}


  下面是我的发送中断服务程序:

#pragma interrupt_handler USART1_UDRE_ISR:iv_USART1_UDRE//“数据空中断”发送数据
void USART1_UDRE_ISR(void)
{
        UDR1 = USART1_send_buffer[USART1_sendPosi++];
        if (USART1_sendPosi >= USART1_sendCount)
        {
                UCSR1B &= ~BIT(5);
                UCSR1B |= BIT(6);
        }
}


//发送完成中断发送最后一个字节(因为是RS485,因此必须确保最后一个发送到PC机后,再将总线置为接收状态)
#pragma interrupt_handler USART1_TX_ISR:iv_USART1_TX
void USART1_TX_ISR(void)
{
        USART1_checkoutError = 0;
        USART1_receCount = 0;
        USART1_RECIVE();
}

出0入0汤圆

发表于 2009-4-1 16:05:59 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2009-4-5 19:47:32 | 显示全部楼层
ba_wang_mao:

太感谢了,不过我后来用模拟器跑了几遍,模拟器可以精确测cycle数阿,发现原来速度是够用的,还是程序的bug, 呵呵。

Thanks!

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-10-3 17:20

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

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