fantaq 发表于 2009-3-30 21:19:41

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

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

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

void_c 发表于 2009-3-30 22:23:07

可以考虑用 用裸中断+内嵌汇编

ba_wang_mao 发表于 2009-3-31 11:51:47

唉,老生长谈。
 怎么能在“串口中断子程序里有一些处理”呢?

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

fantaq 发表于 2009-3-31 21:48:44

呵呵,谢谢楼上的这位兄弟提醒,确实,这是一般原则,应该遵守。

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

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

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

ba_wang_mao 发表于 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 = ch;
    USART1_receTimeOut = 2;//设置超时计时
}


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

#pragma interrupt_handler USART1_UDRE_ISR:iv_USART1_UDRE//“数据空中断”发送数据
void USART1_UDRE_ISR(void)
{
        UDR1 = USART1_send_buffer;
        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();
}

sjzd 发表于 2009-4-1 16:05:59

mark

fantaq 发表于 2009-4-5 19:47:32

ba_wang_mao:

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

Thanks!

zhexuejia 发表于 2013-3-22 16:16:47

thank s   
页: [1]
查看完整版本: 求助,AVR的中断函数响应时间