本帖最后由 aizhixi106 于 2012-11-4 22:11 编辑
这段时间实在是太忙了,事件比较多,感慨下,跨平台移植程序,问题比较多,还有就是理解别人的程序也比较麻烦,统一的格式和命名要按规范来是很重要的。 上一周,跟几个工程师,讨论一个电流的问题,搞了一个星期,最后终于解决了,呵呵。 题外话,该交作业了,上次就说更新了,拖了这么长时间,现在交上作业。哈哈。
Stellaris_LM3s9B96的-------------------------中断 关于中断中断的定义,我就不多讲了,这个学过51的,都应该知道。 关于Stellaris 中断基本编程方法 编写一个中断程序的基本方法如下: 1 . 使能相关片内外设,并进行基本的配置 对于中断源所涉及的片内外设必须要首先使能,使能的方法是调用头文件<sysctl.h>中 的函数SysCtlPeripheralEnable( )。使能该片内外设以后,还要进行必要的基本配置。
2 . 设置具体中断的类型或触发方式 不同片内外设具体中断的类型或触发方式也各不相同。在使能中断之前,必须对其进行 正确的设置。以GPIO为例,分为边沿触发、电平触发两大类,共5 种,这要通过调用函数 GPIOIntT ypeSet( ) 来进行设置。 3 .使能中断 对于Stellaris 系列ARM,使能一个片内外设的具体中断,通常要采取分3 步走的方法: 调用片内外设具体中断的使能函数 调用函数IntEnable( ) ,使能片内外设的总中断 调用函数IntMasterEnable( ) ,使能处理器总中断 4 编写中断服务函数 C 语言是函数式语言,ISR 可以称为“中断服务函数”。中断服务函数从形式上跟普通 函数类似,但在命名及具体的处理上有所不同。 到这里,我们的大体明白一个中断应该怎么写? 我们用一个具体的例子,来说明中断。 有按键LED就能点亮,再按一下,就熄灭。就这么简单 #include "SystermInit.h" #define LED GPIO_PIN_3 #define BUTTON GPIO_PIN_7 //#define TheSysClock 16000000 int main() {
clockInit(); //使能外设GPIO SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); //配置管脚驱动,驱动电流2MA其实已足够 GPIOPadConfigSet(GPIO_PORTF_BASE,LED,GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); GPIOPadConfigSet(GPIO_PORTJ_BASE,BUTTON,GPIO_STRENGTH_2MA,GPIO_PIN_ TYPE_STD_WPU); //配置方向 GPIODirModeSet(GPIO_PORTF_BASE,LED,GPIO_DIR_MODE_OUT); GPIODirModeSet(GPIO_PORTJ_BASE,BUTTON,GPIO_DIR_MODE_IN); //GPIO中断方式 GPIOIntTypeSet(GPIO_PORTJ_BASE,BUTTON,GPIO_LOW_LEVEL); //打开GPIO的中断 GPIOPinIntEnable(GPIO_PORTJ_BASE,BUTTON); //使能GPIOJ的中断 IntEnable(INT_GPIOJ); //使能中中断 IntMasterEnable(); // 使能处理器中断 while(1) { } } void IntGPIOj(void) { unsigned char ucVal; unsigned long ulStatus; ulStatus=GPIOPinIntStatus(GPIO_PORTJ_BASE,true);
GPIOPinIntClear(KEY_PORT, ulStatus); if(ulStatus&BUTTON) { ucVal=GPIOPinRead(GPIO_PORTF_BASE,LED); GPIOPinWrite(GPIO_PORTF_BASE,LED,~ucVal); SysCtlDelay(10*(TheSysClock/8000)); // 延时约10ms,消除按键抖动 while (GPIOPinRead(GPIO_PORTJ_BASE, BUTTON) == 0x00); // 等待KEY抬起 SysCtlDelay(10*(TheSysClock/ 8000)); // 延时约10ms,消除松键抖动 } } 程序中我已经加了说明,应该很容易理解,这里我们注意下,中断的类型。 我们可以从头文件中看到,中断类型的定义, //***************************************************************************** // // Values that can be passed to GPIOIntTypeSet as the ulIntType parameter, and // returned from GPIOIntTypeGet. // //***************************************************************************** #define GPIO_FALLING_EDGE 0x00000000 // Interrupt on falling edge #define GPIO_RISING_EDGE 0x00000004 // Interrupt on rising edge #define GPIO_BOTH_EDGES 0x00000001 // Interrupt on both edges #define GPIO_LOW_LEVEL 0x00000002 // Interrupt on low level #define GPIO_HIGH_LEVEL 0x00000007 // Interrupt on high level
在这个里面我们可以看的很清楚,GPIO的中断有几种类型,这里我们需要注意下,这个的设置。 在中断程序中,我们还需要注意下,我就在进入中断的时候,我们要清除中断标志,这个很重要,我之前犯过这样的错误,导致中断位没有清楚,一直没有找到原因,后来才发现中断标志没有清除。 在开始接触ARM的时候中断其实根本就不知道怎么写,为什么没有中断向量呢? 对于从单片机转向ARM的时候,我遇到过这样的困惑,后来发现,这个中断是需要注册的,关于中断注册有很多方法,在STATUP.S中注册下就行了,但是这种方法的缺点就是程序移植性不是太好。也可以通过函数来实现,这里不做说明。 在STATUP.S中有个 The vector table.,我们就是在这里注册中断函数,中断函数是由你自己定义的,这个你可以随便定义。 当注册完成之后,我们还需要对外引用。 需要加上 extern IntGPIOj 如图:
到这里,我们其实对照代码,再来理解中断,应该不是很复杂,就是先使能端口,然后设置中断类型,这样就行了。 中断在单片机中,还是很重要的,弄懂中断,就等于学会单片机了。对于ARM,也是一样的,我是这样理解的。例子其实很简单,但是如果你自己动手调试,对于没有接触过ARM新学ARM的同学,还是有点难度,我开始弄的时候,也花了点时间,弄懂,后面的什么定时器中断,UART 中断啊,都是菜。 呵呵,关于中断就写到这吧,GPIO口的中断是一个蛮好的中断入门的例子,帖子中有写的不对的,还希望大家指正,谢谢~~~ 下一章更新个TIMER 如何使用。以及因为自己的一个小的错误,我花了两天的时间来查原因,最后发现,有些时候基础的东西,很重要,你要了解清楚。 待续~~~~~~~~~~~~~~~~~~~
|