M0的中断系统-M0的外部中断是所有的IO口都可以实现的,这一点比较特殊。今天试了试LPC1114的外部中断功能,本以为很简单的问题还遇到了麻烦,问题如下,根据ZLG提供的工程例子将程序烧写可以正常运行。在源代码基础上将中断的IO口由P3_2移到了P0_2,发现程序怎么都运行部正确。验证后发现程序的中断服务程序时没有被运行的。遂怀疑发生了中断向量异常。于是与一遍遍的对手册,看例程修改程序都无法正确通过。因为ZLG的例子都是基于模板下的。程序上重定义了很多寄存器。在阅读上存在很大的障碍。没办法我拨通了ZLG的服务电话。刚讲明来意对方即表示理解。看样子出现这个问题的很多。事后我才了解到。在这个工程模板下。中断的服务程序需要在2个文件中先注册和申明后才能正确的运行。纳闷的事不注册程序也不报错。而且手册中也并未提及...结果排错了很久..杯具啊..闲话不多说进入正题。M0的中断系统。M0中断与普通中断类使。唯一的亮点就是具有双边沿测试,这对于做PTT检测很有帮助。先来认识下寄存器
GPIOXIS(X为0-3表示0-3组的IO口)中断模式选择,选择是电平触发还是边沿触发。由于每组IO都是12个。所以这个32位的寄存器有效位是12位。其余的不要写入数据。GPIO1IS=0X01;//这句表示选择P1.0这个IO口的中断为电平触发模式。
GPIOXIBE:GPIO的双边沿触发寄存器。例:GPIO1IBE=0X01;//表示P1.0这个IO口在上边沿河下边沿都会触发中断。初始值为0x00
GPIOXIEV:触发电平选择。选择中断来时是上升沿还是下降沿中断有效。GPIO1IEV=0X01;//设置P1.0这个IO口的中断是在下降沿或是低电平时有效。为什么是或咧?因为具体的中断触发事件是GPIOXIEV和GPIOXIS两个寄存器共同决定的。
GPIOXIE:这个寄存器就是中断开启控制寄存器了。当对应IO口的那位为1时,该位的中断才被允许。例:GPIO1IE=0X01;表示允许P1.0这个IO口产生中断。
以上就是进行中断操作必须配置的寄存器。当然不止这些寄存器,还有些寄存器在实际意义不大到在此不提。
配置完了寄存器,就是需要写中断的入口函数和服务函数了,ZLG的模板对中断服务建立了函数管理机制。统一用一个函数来进行对中断服务函数的名称设置。
zyIsrSet(NVIC_PIOINT0, (unsigned long)GPIOIsr, PRIO_ONE);就是这个函数。函数的3个参数分别含义是中断向量号。ZLG进行了重定义。中断服务函数名。也就是说你的中断服务函数的名字一定要是GPIOIsr喔。不然会报错的。最后一个是中断优先级。LPC1114采用了嵌套中断优先级机制所以可以对优先级进行设置。本程序只有一个服务函数所以PRIO_ONE(事先经过宏定义为1,优先级最高)
有了这些就可以构成完整的中断服务体系,在做的就像51那样写中断服务函数。当然不用加中断向量号了。在此提醒一点。在LPC1114中断服务函数中一定要清除中断标记否则中断服务函数不会结束运行造成程序停滞!切记切记!在此介绍最后一个GPIO中断相关寄存器。GPIOXIC中断清除寄存器。对应位为1清除中断标记。例:GPIO1IC=0X01;//表示清除P1.0上的中断标记。
最后说一下关于中断服务函数的声明
在工程文件的vector_cfg.h文件下第31行时对异常中断处理的申明
在define前面表示的是中断事件。可以看出和系统拥有的中断事件是对应的。后面的是对应的中断服务函数名。如果说你开启了相应的中断就需要在后面将改成与你的中断服务函数名一致。
在就是在工程文件vector_table.C文件下的30行的外部函数定义加入你定义好的中断服务函数名。这样就说完成了。如此就不会出现中断向量异常。特此附上源代码和工程实例(基于TKstduio环境)attachment download
#include "..\config.h"
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
#define BEEP (1ul << 7)
#define BEEP_INIT() GPIO2DIR |= BEEP /* 蜂鸣器初始化 */
#define BEEPOFF() GPIO2DATA |= BEEP /* 蜂鸣器关 */
#define BEEPON() GPIO2DATA &= ~BEEP /* 蜂鸣器开 */
#define LED_NUM 4 /* LED数量4个 */
/*********************************************************************************************************
全局变量
*********************************************************************************************************/
const INT32U led_mask[] = {1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
/*********************************************************************************************************
** Function name: myDelay
** Descriptions: 软件延时
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void myDelay (INT32U ulTime)
{
INT32U i;
i = 0;
while (ulTime--) {
for (i = 0; i < 5000; i++);
}
}
/*
函数名:GPI0_SEL
功能:GPIO输出功能设置
参数:name-选择GPIO组数 num-引脚数
返回值:0-管脚值出现错误
1-配置正确
*/
unsigned char GPIO_SEL(unsigned char name,unsigned char num)
{
if(((name>3)||(name<0))&&((num<0)||(num>11)))
return 0;//数据出现错误立即结束函数运行
switch(name)
{
case 0:GPIO0DIR|=(1<<num);break;
case 1:GPIO1DIR|=(1<<num);break;
case 2:GPIO2DIR|=(1<<num);break;
case 3:GPIO3DIR|=(1<<num);break;
default :break;
}
return 1;//配置正确返回1
}
/*
函数名:GPIO_INTSEL
功能:GPIO中断管脚设置
参数:IS-中断模式选择 为1设置为电平触发
IBE-双边沿中断选择 为1设置为双边沿触发
IEV-触发电平选择 为1设置为下降沿或低电平触发
IE-开启中断选择 为1开启对应管脚的中断
NAME-管脚组号 0-3选择相应的管脚组
num-引脚号 0-11选择相应的引脚号
返回值:0-出现管脚号设置错误
1-配置正确
*/
unsigned char GPIO_INTSEL(unsigned char Name,
unsigned char num,
unsigned char IS,
unsigned char IBE,
unsigned char IEV,
unsigned char IE
)
{
if(((Name>3)||(Name<0))&&((num<0)||(num>11)))
return 0;//数据出现错误立即结束函数运行
switch(Name)
{
case 0:GPIO0IS|=(IS)<<num;
GPIO0IBE|=(IBE)<<num;
GPIO0IEV|=(IEV)<<num;
GPIO0IE|=(IE)<<num;
break;
case 1:GPIO1IS|=(IS)<<num;
GPIO1IBE|=(IBE)<<num;
GPIO1IEV|=(IEV)<<num;
GPIO1IE|=(IE)<<num;
break;
case 2:GPIO2IS|=(IS)<<num;
GPIO2IBE|=(IBE)<<num;
GPIO2IEV|=(IEV)<<num;
GPIO2IE|=(IE)<<num;
break;
case 3:GPIO3IS|=(IS)<<num;
GPIO3IBE|=(IBE)<<num;
GPIO3IEV|=(IEV)<<num;
GPIO3IE|=(IE)<<num;
default:break;
}
return 1;
}
void GPIOIsr (void)
{
GPIO0IC |= (1<<0); /* 清除中断标志 */
GPIO0DATA&=0X00;
}
/*********************************************************************************************************
** Function name: main
** Descriptions: 当硬件基于EasyCortexM3-1300开发板时,进行LED测试需要短接P2.8与LED1、P2.9与LED2、
** P2.10与LED3、P2.11与LED4。
** 用户也可以根据自己的底板的设计自行连接
** input parameters: 无
** output parameters: 无
** Returned value: 无
中断用到的P0.2脚,点亮LED用到的是P0.1脚
注意事项:在使用ZLG模板时用到中断服务函数需要先注册和申明,否则造成中断异常
需要修改VECTOR_CFG.H和VECTOR_TABLE.C文件
*********************************************************************************************************/
int main (void)
{
targetInit(); /* 初始化目标板,切勿删除 */
pinInit(); /* 引脚初始化 */
SYSAHBCLKCTRL |= (1ul << 6); /* 使能GPIO模块时钟 */
GPIO_SEL(0,1);
GPIO_INTSEL(0,2,0,0,1,1);//设置P0.2引脚作为中断的输入引脚
zyIsrSet(NVIC_PIOINT0, (unsigned long)GPIOIsr, PRIO_ONE);
//设置为P0口产生中断,定义中断的入口函数为GPIOIsr,定义中断的优先级为最高级。本程序只有一个中断优先级
while (1)
{
}
}
/*********************************************************************************************************
End Of File
*******************************************
用户377235 2013-9-26 19:26