春节前做了一个简单的开箱测试,跑了个流水灯,大概了解了一下CH563的基本开发流程。假期间天天走亲访友、吃喝醉睡,板子扔在一边整个假期居然一下也没碰。昨天上班,刚开工,没什么事干,又把板子拿起来测试了一下CH563的中断系统。
CH563的中断模式与其它ARM芯片差不多,分为IRQ与FIQ,同时每种模式还分为查询入口与直跳入口中断。第一篇测试文章里提到的IRQ_Handler(),FIQ_Handler()这两个函数就是默认的查询入口中断处理函数。在使用查询入口中断时,我们要把中断处理相关内容写到这两个函数里。由于在查询方式下所有的中断源发生中断后都是跳向这两个函数,所以一般要在这两个函数里先对中断源进行判断,再跳转到相应的处理程序里。显然这种方式会多消耗一些处理器时间。
而相对的直跳入口与51单片机的中断处理差不多,都是通过指定中断向量,一旦某一特定中断发生时,就直接跳转到指定的中断处理函数里去,从而节省了一点处理器时间。
为了了解CH563的中断处理方式,俺设计了两个小程序来分别测试查询入口与直跳入口。使用的都是PB管脚做为外中断源,利用板上的三个LED灯来指示是否进入了中断处理程序。
程序1为查询入口,中断源为PB6、PB7。PB6设定为上升沿触发,PB7设定为下降沿触发。PB7是直接利用板上的按钮S2来触发中断,从而控制三个LED依次单独点亮。PB6则用了一根杜邦线通过与GND的接触来触发中断,将三个LED的状态反转。
下面为程序1的代码,具体寄存器的作用都作了注释:
#include "CH563BAS.H" #include "CH563SFR.H" #include "SYSFREQ.H" #define LED 0x38 CHAR LEDMASK[]={0x30,0x28,0x18}; CHAR IntTime; __irq void IRQ_Handler() { if(R8_INT_STATUS_PB_0&0x80) //是否为PB.7中断 { Delay_ms(30); //在中断处理程序里做延时消抖,就是这么任性:) if(!(R8_PB_PIN_0&0x80)) { if(IntTime<3) { R8_PB_CLR_0 |=LED; //LED清零 R8_PB_OUT_0 |= LEDMASK[IntTime]; } if(++IntTime>=3) IntTime=0; } } if(R8_INT_STATUS_PB_0&0x40) //是否为PB.6中断 { Delay_ms(30); if((R8_PB_PIN_0&0x40)) { R8_PB_OUT_0 ^=LED; } } R8_INT_STATUS_PB_0 = 0xff; // 中断标志清零 } __irq void FIQ_Handler(){} void IRQ_InitPB_7_6(void) { R8_PB_PU_0 |= 0xc0; //设置PB.7.6为上拉 R8_PB_DIR_0 &= ~0xc0; //设置PB.7.6为输入 R8_INT_ENABLE_PB_0 |= 0xc0; //打开两IO外部中断 R8_INT_MODE_PB_0 |=0xc0; //设置中断触发方式为边沿触发 R8_INT_POLAR_PB_0 &= 0x7f; //设置PB.7下降沿触发 R8_INT_POLAR_PB_0 |= 0x40; //设置PB.6上升沿触发 R8_INT_STATUS_PB_0 = 0xff; R8_INT_EN_IRQ_1 |= RB_IE_IRQ_PB; //使能PB口IRQ中断 R8_INT_EN_IRQ_GLOB|= RB_IE_IRQ_GLOB; //使能全局IRQ中断 } void Init_LED(void) { R8_PB_DIR_0 |= LED; //PB.3.4.5为输出 R8_PB_OUT_0 |= LED; } int main() { IRQ_InitPB_7_6( ); Init_LED(); IntTime=0; while(1) { } }