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同志~~~ |