【DSP学习】外部中断实验-基于普中DSP28335开发攻略
参考材料普中DSP28335开发攻略一、外部中断配置1 失能 CPU 级中断并初始化 PIE 控制器寄存器和 PIE 中断向量表在前面学习中断章节中我们知道 F28335 的外设中断需通过 PIE 控制器来管理因此需要初始化 PIE 相应的寄存器和中断向量表。TI 公司已经提供了对应的函数来完成这些操作。分别是 InitPieCtrl()和 InitPieVectTable()。从函数名即可明白它的功能所以在开发 F28335 程序时不需要准确记住函数知道其含义然后查找即可。这两个函数分别在 DSP2833x_PieVect.c、 DSP2833x_GlobalVariableDefs.c 文件中。大家可以打开看下这里就不列出了。此步代码如下InitPieCtrl();IER0x0000;IFR0x0000;InitPieVectTable();这段代码是在进行DSP中断系统的初始化相当于在系统启动时把整个中断处理框架“清零”并设置为一个已知的、安全的状态。我们一句一句来解释代码逐行解释1.InitPieCtrl();作用初始化PIE控制器寄存器。具体操作将PIE控制寄存器PIECTRL、PIE应答寄存器PIEACK、所有PIE分组的中断使能寄存器PIEIER1-PIEIER12和中断标志寄存器PIEIFR1-PIEIFR12全部清零。结果所有PIE分组的中断都被禁止所有挂起的中断标志都被清除。相当于把所有PIE的“开关”都关掉所有“请求灯”都灭掉。2.IER 0x0000;作用清零CPU级中断使能寄存器。IER (Interrupt Enable Register)CPU级别的总开关控制INT1-INT14这14根中断线是否使能。 0x0000把所有14个CPU中断线全部禁止。此时即使PIE那边有中断请求比如ADC中断CPU也会完全忽略不会响应任何可屏蔽中断。3.IFR 0x0000;作用清零CPU级中断标志寄存器。IFR (Interrupt Flag Register)记录是否有中断请求到达CPU。某个位为1表示对应的中断线有尚未处理的请求。 0x0000把所有中断标志位清零。相当于把CPU“收件箱”里的所有未读邮件全部清空表示没有任何待处理的中断请求。4.InitPieVectTable();作用初始化PIE中断向量表。具体操作将96个外设中断的默认服务函数入口地址填入PIE向量表位于RAM中的那块特殊内存的对应位置。结果当某个中断发生时CPU能够从这个表里找到对应的函数地址并跳转过去。如果这一步不做向量表里全是随机值中断一来程序就会跑飞。为什么需要这个顺序先清PIE确保没有任何残留的、在上一轮或启动过程中意外产生的中断请求。再关CPU中断确保上述清理过程不会被任何新中断打断。清CPU标志清理可能已有的CPU中断标志。最后装向量表所有清理工作完成准备好地址本后续使能中断就可以正常工作。这是中断系统初始化的标准安全流程先关闭并清理所有可能干扰的因素再填好关键数据向量表。2 使能 IO 口时钟配置 IO 口为输入由于本章使用开发板上矩阵按键 IO 口作为外部中断输入线因此需要使能对应的 IO 口时钟及配置 IO 口模式在按键实验章节中我们就介绍过要把对应 IO 口设置为输入模式这部分配置与按键实验一样。3 设置 IO 口与中断线的映射关系前面说过F28335 共支持 7 个外部中断 XINT1-XINT7其中 XINT1-XINT2 只能对 GPIO0-GPIO31 配置XINT3-XINT7 只对 GPIO32-GPIO63 配置。所以需要选择对应的外部中断线及 IO 口配置比如我们 K1 它是连接在 GPIO12 上要使用外部中断功能可以是外部中断 1 或者外部中断 2假如使用外部中断 1其代码如下EALLOW;GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL12;// XINT1 是 GPIO12EDIS;这段代码的作用是将GPIO12引脚与外部中断1XINT1在硬件上连接起来。简单说就是告诉芯片当GPIO12上的电平发生变化时触发XINT1这个外部中断。一、背景知识为什么需要这一步F28335的7个外部中断XINT1-XINT7并不是固定死在某个GPIO引脚上的而是可配置的。XINT1和XINT2可以从GPIO0-GPIO31中任选一个作为触发源XINT3-XINT7可以从GPIO32-GPIO63中任选一个你的开发板上按键K1连接到了GPIO12。所以你需要明确告诉芯片“GPIO12这个引脚请把它连接到XINT1中断线上”。二、代码逐行解释EALLOW;// ① 解锁受保护寄存器GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL12;// ② 设置映射关系EDIS;// ③ 重新锁定①EALLOW;—— 解锁作用F28335中有一些关键寄存器是受保护的不能随意修改。EALLOW是一个汇编指令EALLOW Enable Allow执行后可以临时修改这些保护寄存器。如果不写向GPIOXINT1SEL写入会无效甚至触发错误。②GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL 12;—— 核心映射GpioIntRegs外部中断选择寄存器的结构体。GPIOXINT1SELXINT1的GPIO选择寄存器。这是一个专门用来配置“XINT1使用哪个GPIO引脚”的寄存器。.bit.GPIOSEL寄存器的位域用于写入GPIO编号。 12写入数值12表示选择GPIO12。意思把GPIO12这个引脚在芯片内部连接到XINT1上。以后GPIO12的电平变化就会触发XINT1中断。③EDIS;—— 重新锁定EDISEnable Disable与EALLOW配对使用执行后寄存器恢复保护状态防止后续程序意外修改关键配置。4 指定中断向量表中断服务函数地址这个通过对 PIE 中断向量表寄存器的相应位进行设置中断服务函数名可自定义但是要符合 C 语言标识符命名规则在中断函数名前需加上地址符“”。在对 PIE 中断向量表寄存器设置时要先声明 EALLOW修改完成后还要声明 EDIS。比如外部中断 1其设置如下EALLOW;// 修改被保护的寄存器修改前应添加 EALLOW 语句PieVectTable.XINT1EXTI1_IRQn;EDIS;// EDIS 的意思是不允许修改被保护的寄存器5 使能外设对应的 PIE 中断由于外设中断较多它们是由 PIE 统一管理所以要根据你所使用的外设中断选择对应的组和该组内的通道比如外部中断 1它是由 PIE 组 1 的第 4 通道连接这个在前面中断介绍时讲解过。因此可由 PIE 控制寄存器中相应中断使能位来控制。其实现代码如下所示PieCtrlRegs.PIEIER1.bit.INTx41;// 使能 PIE 组 1 的 INT4这段代码的作用是在PIE外设中断扩展模块层面使能外部中断1XINT1。简单说前面已经把GPIO12映射到了XINT1现在这一步是告诉PIE控制器“XINT1这个中断请求请放行让它通过”。一、背景知识XINT1在PIE中的位置回忆PIE的结构12个组GROUP1-GROUP12每组8个通道INTx.1-INTx.8。XINT1外部中断1的位置是GROUP1第4通道即INT1.4。PIE GROUP1 ──┬── INT1.1 (ADC) ├── INT1.2 (ADC) ├── INT1.3 (ADC) ├── INT1.4 (XINT1) ← 外部中断1在这里 ├── INT1.5 (XINT2) ├── INT1.6 (XINT3) ├── INT1.7 ... └── INT1.8 ...所以要使能XINT1就必须操作GROUP1的第4通道。二、代码逐层拆解PieCtrlRegs.PIEIER1.bit.INTx41;部分含义PieCtrlRegsPIE控制寄存器组由TI官方定义的结构体在DSP2833x_PieCtrl.h中声明.PIEIER1PIE中断使能寄存器1控制GROUP1的所有8个通道的使能IER Interrupt Enable Register.bit.INTx4访问该寄存器的位域第4位x表示通道号4表示第4通道 1写入1表示使能这个通道的中断6 设置外部中断触发方式并使能中断我们知道外部中断的触发方式有上升沿触发正边沿和下降沿触发负边沿根据自己的需求来选择。当按键按下时我们是让其输入一个低电平到 IO 口而默认处于高电平所以按键按下时会产生一个下降沿因此选择下降沿触发。外部中断的触发方式及中断使能是由 XIntruptRegs 寄存器控制具体实现代码如下XIntruptRegs.XINT1CR.bit.POLARITY0;// 下降沿触发中断XIntruptRegs.XINT1CR.bit.ENABLE1;// 使能 XINT1使能 CPU 级中断及全局中断这个通过对 IER 和 EINT 寄存器相应位设置进行使能或者失能。其代码如下IER|M_INT1;// 使能 CPU 中断 1INT1EINT;// 开全局中断ERTM;当使用仿真器调试时可开启 DEBUG 中断即使用 ERTM 语句。这段代码完成了外部中断触发的最后两步配置触发方式、使能中断以及打开CPU级中断的总开关。一、外部中断触发方式配置XIntruptRegs.XINT1CR.bit.POLARITY0;// 下降沿触发中断XIntruptRegs.XINT1CR.bit.ENABLE1;// 使能 XINT1XINT1CR是什么XINT1CR External Interrupt 1 Control Register外部中断1控制寄存器它是一个16位寄存器控制XINT1的触发极性和使能状态寄存器结构简化XINT1CR (16位寄存器) ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐ │ 15-4 │ 3 │ 2 │ 1 │ 0 │ │ (保留)│ │ │ │ │ └───────┴───────┴───────┴───────┴───────┘ ↑ ↑ │ └─── 位1: ENABLE (使能) └─────────── 位0: POLARITY (极性)位名称值含义0POLARITY0下降沿触发高→低1上升沿触发低→高1ENABLE0禁止XINT1中断1使能XINT1中断为什么选择下降沿按键K1一端接GPIO12另一端接GND未按下GPIO12通过上拉电阻为高电平按下瞬间GPIO12从高→低产生下降沿所以POLARITY 0下降沿触发是正确的选择二、使能CPU级中断IER|M_INT1;// 使能 CPU 中断 1INT1IER是什么IER Interrupt Enable RegisterCPU中断使能寄存器控制CPU的14个中断线INT1-INT14是否接收中断请求M_INT1是什么M_INT1是一个宏定义通常为0x0001二进制0000 0000 0000 0001表示IER的第0位INT1为什么需要这一步PIE已经打开了XINT1PIEIER1.INTx41但PIE的输出连接的是CPU的INT1如果CPU的INT1是关闭的信号到了门口也进不去IER | M_INT1就是打开CPU的INT1大门三、打开全局中断EINT;// 开全局中断ERTM;// 使能实时调试模式仅调试时用EINT是什么EINT Enable INTerrupt汇编指令作用清除CPU状态寄存器中的INTM位Interrupt Master FlagINTM0时CPU响应所有可屏蔽中断INTM1时CPU忽略所有可屏蔽中断指令操作INTM值效果EINTEnable INT0开总中断DINTDisable INT1关总中断ERTM是什么ERTM Enable Real Time Mode使能实时调试模式仅在使用仿真器在线调试时才需要作用允许在断点暂停时某些中断如过流保护仍然能够响应如果不调试程序烧录后独立运行这句可以不加7 编写外部中断服务函数配置好中断后如果有触发即会进入中断服务函数中断服务函数名在前面已定义好所以要保证一致否则将不会进入中断服务函数内执行。在 DSP28335软件开发中要在中断服务函数名前加上关键字 interrupt。例如外部中断 1 的中断服务函数interruptvoidEXTI1_IRQn(void){...功能程序}在中断执行结束前要清除相应的中断标志位以等待下次中断的到来。二、外部中断初始化函数使用外部中断我们必须先对它进行配置。其初始化代码如下voidEXTI1_Init(void){EALLOW;SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK1;//GPIOinputclockEDIS;EALLOW;//KEY端口配置GpioCtrlRegs.GPAMUX1.bit.GPIO120;GpioCtrlRegs.GPADIR.bit.GPIO120;GpioCtrlRegs.GPAPUD.bit.GPIO120;GpioCtrlRegs.GPAQSEL1.bit.GPIO120;//外部中断1XINT1与系统时钟SYSCLKOUT同步GpioCtrlRegs.GPBMUX2.bit.GPIO480;GpioCtrlRegs.GPBDIR.bit.GPIO481;GpioCtrlRegs.GPBPUD.bit.GPIO480;GpioDataRegs.GPBCLEAR.bit.GPIO481;EDIS;EALLOW;GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL12;//XINT1是GPIO12EDIS;EALLOW;//修改被保护的寄存器修改前应添加EALLOW语句PieVectTable.XINT1EXTI1_IRQn;EDIS;//EDIS的意思是不允许修改被保护的寄存器PieCtrlRegs.PIEIER1.bit.INTx41;//使能PIE组1的INT4XIntruptRegs.XINT1CR.bit.POLARITY0;//下降沿触发中断XIntruptRegs.XINT1CR.bit.ENABLE1;//使能XINT1IER|M_INT1;//使能CPU中断1INT1EINT;//开全局中断ERTM;}在 EXTI1_Init()函数中首先开启 GPIO 时钟并初始化 GPIO12 为输入状态然后选择 GPIO12 为外部中断 1 功能设置外部中断入口函数使能 PIE 中断最后选择外部中断触发方式为下降沿触发并开启外部中断功能和总中断。这些配置是按照前面介绍的步骤完成除了时钟外其他顺序可以调换。其实如果你会配置外部中断 1那么其他外部中断都是类似的。三、外部中断服务函数初始化外部中断后中断就已经开启了当指定按键按下后会触发一次中断这时程序就会进入中断服务函数执行所以我们还需要编写对应的 外部中断函数这里我们以 GPIO12 管脚的 K1 按键进行讲解其他的按键的中断函数类似具体代码如下interruptvoidEXTI1_IRQn(void){Uint32 i;for(i0;i10000;i);//键盘消抖动while(!KEY_H1);LED2_TOGGLE;PieCtrlRegs.PIEACK.bit.ACK11;}在 F28335 中断服务函数中 需要在中断服务函数名前加上一个关键字 “interrupt”标识为中断函数。进入中断函数后还需要对按键进行消抖处理每当 K1 按键按下D2 指示灯都会状态取反一次。最后特别注意在中断函数执行完成前一定要记得将相应的 PIEACKx 清零否则下次将不再进入中断。可通过 PIE 控制寄存器的 PIEACK 中的 ACK1 写 1 来完成清零操作。程序中的 KEY_H1 是按键驱动文件内定义的宏这个在按键实验章节已介绍这里不再重复。四、主函数编写好外部中断初始化和中断服务函数后接下来就可以编写主函数了代码如下voidmain(){inti0;InitSysCtrl();InitPieCtrl();IER0x0000;IFR0x0000;InitPieVectTable();LED_Init();EXTI1_Init();EXTI2_Init();while(1){i;if(i%20000){LED1_TOGGLE;}DELAY_US(100);}}主函数实现的功能很简单首先初始化系统时钟、PIE 中断相关寄存器及中断向量表本套教程所有有关中断代码都采用这种设置后面就不做重复。再对使用到的硬件端口时钟和 IO 口初始化然后调用我们前面编写的 EXTI 的初始化函数最后进入 while 循环语句不断让 D1 指示间隔 200ms 闪烁。有的朋友就会问在主函数中怎么没有看到按键对 LED 的控制呢因为我们在 EXTI1_Init()和 EXTI2_Init()函数内就已经把按键管脚映射到中断线上并配置了相应的触发方式当有按键按下即会进入对应中断服务函数执行相应的功能程序LED 的控制就在中断函数内完成的。实验现象使用仿真器将开发板和电脑连接成功后把编写好的程序编译后如果没有报错即可将点击仿真调试程序即会写入到芯片的 RAM 内运行结果是按键 K1控制 D2 亮灭K4 按键控制 D3 亮灭D1 指示灯闪烁提示系统运行状态。当系统断电后程序不会继续执行因为我们现在使用的是仿真调试即程序写入到 RAM 内而非 FLASH
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2609832.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!