原创 IAR FOR ARM中C++类成员函数做中断函数的三个主要步骤

2008-2-9 12:30 5955 6 6 分类: MCU/ 嵌入式

原帖出处: http://bbs.21ic.com/club/bbs/list.asp?boardid=42&t=2853557



hotpower 发表于 2008-2-9 12:19 ZLG-MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

4楼: 类成员函数做中断函数的三个主要步骤


1.在类中声明ISP()
class SystemObj
{
public:
//................
//类成员函数做中断函数
    static void HibernateISR(void);//必须声明为静态函数!!!
    static void SysTickISR(void);//必须声明为静态函数!!!
public:
    volatile unsigned int RamTest;
    union
    {
        volatile unsigned char WorkFlag;
        struct
        {
            unsigned char Watchdog:         1;//允许喂狗
            unsigned char SysTickFlag:      1;//节拍中断
            unsigned char MainLoopFlag:     1;//主循环运行
            unsigned char MainWatchdog:     1;//主循环喂狗
        };
    };
};

class UartObj {
public:
//.........
//类成员函数做中断函数
    static void UART0ISR(void);//必须声明为静态函数!!!
};

2.构造类成员函数
//5mS定时中断服务程序(类成员函数做中断函数)
//static//此处不能加static!!!
//类成员变量必须指明实际的类!!!(System.MainWatchdog 不能写成MainWatchdog)
void SystemObj::SysTickISR(void)
{
    Keyboard.Exec();//"零耗时键盘"消抖及运行命令
    if (System.Watchdog)//允许喂狗
    {
      if (!System.MainWatchdog)//中断喂狗论
        {
            if (!System.SysTickFlag && System.MainLoopFlag)//主程序在工作
            {
                WatchdogIntClear(WATCHDOG_BASE);//真正的硬件喂狗!!!
            }
        }
    }
    System.SysTickFlag = true;//通知主循环节拍中断正常工作
}

//休眠激活中断服务程序(类成员函数做中断函数)
//static//此处不能加static!!!
void SystemObj::HibernateISR(void)
{
   HWREG(HIB_CTL) &= ~ HIB_CTL_HIBREQ;
   HibernateIntClear(HIBERNATE_INT_PIN_WAKE    | HIBERNATE_INT_LOW_BAT |
                 HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_RTC_MATCH_1);
}

//串口中断服务程序(类成员函数做中断函数)
//static//此处不能加static!!!
void UartObj::UART0ISR(void)
{

    unsigned long ulStatus;
    ulStatus = UARTIntStatus(UART0_BASE, true);
    UARTIntClear(UART0_BASE, ulStatus);
    while(UARTCharsAvail(UART0_BASE))
    {
        UARTCharPutNonBlocking(UART0_BASE, UARTCharGetNonBlocking(UART0_BASE));
    }
}

3.在startup.c内的中断向量表内填写需要中断的类成员函数地址
__root static const uVectorEntry g_pfnVectors[] @ "INTVEC" =
{
    { .ulPtr = __sfe( "CSTACK" ) },
    __program_start,                        // The reset handler
//    ResetISR,                             // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    IntDefaultHandler,                      // The PendSV handler
    &SystemObj::SysTickISR,                 // The SysTick handler
//不能用下列写法
//    &System.SysTickISR,                     // The SysTick handler
//...................
    &UartObj::UART0ISR,                     // UART0 Rx and Tx
//不能用下列写法
//    &Uart.UART0ISR,                         // UART0 Rx and Tx
    IntDefaultHandler,                      // UART1 Rx and Tx
//...................
    IntDefaultHandler,                      // Ethernet
    &SystemObj::HibernateISR                // Hibernate
//不能用下列写法
//    &System.HibernateISR                    // Hibernate
};


可以看出IAR实在不如GCC~~~不过还是能过得去的~~~

请看:
//static//此处不能加static!!!
//类成员变量必须指明实际的类!!!(System.MainWatchdog 不能写成MainWatchdog)
void SystemObj::SysTickISR(void)
{
    Keyboard.Exec();//"零耗时键盘"消抖及运行命令
    if (System.Watchdog)//允许喂狗
//...................

哈哈~~~看看gcc的2个步骤吧(它隐含了中断向量表)
1.在类中声明ISP()
class AdcObj {
public:
//................
//类成员函数做中断函数
  void SIG_ADC(void)  __attribute__ ((signal));
private:
  unsigned char AdcNum;//加volatile将增大空间72个字节
  unsigned char AdcCount;//加volatile将增大空间4个字节
  volatile unsigned int AdcSum[8];//不改变
  unsigned int AdcMax[8];//加volatile将增大空间4个字节
  volatile unsigned int AdcMin[8];//不改变
};

2.构造类成员函数
void AdcObj::SIG_ADC(void)
{
unsigned int adcval;
  adcval = ADC & 0x3ff;//取ADC转换电压,并保存
  SetAdcChNum(AdcNum + 1);//设置新通道
/*-----------------------------------------------------------
  求最大值,最小值,累加和(0,5不用侧)
------------------------------------------------------------*/
  if (AdcNum & 1) {//偶数不测试
    AdcSum[AdcNum] += adcval;//存累加和
    if (adcval > AdcMax[AdcNum]) {
      AdcMax[AdcNum] = adcval;//最大值
    }
    if (adcval < AdcMin[AdcNum]) {
      AdcMin[AdcNum] = adcval;//存最小值
    }
  }
//...........................
}

可以看出gcc才是最完美的类成员函数做中断函数~~~
而IAR的类成员函数做中断函数后不能访问自己类的其他成员实在倒塌~~~

哈哈~~~估计是菜农还没彻底将其倒塌...估计还要求助TestCode同志~~~

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条