导购 网站模板,广东网站制作公司,短网址api接口,wordpress 产品类标题以KEY2控制LED3亮灭为例#xff1a; 一、轮询方式 【0】检测按键k2#xff0c;按键k2按下一次#xff0c;灯LED2闪一次。 【1】查看原理图#xff0c;连接引脚和控制逻辑 #xff08;1#xff09;按键k2 连接在GPX1_1引脚 #xff08;2#xff09;控制逻辑 k2 按… 以KEY2控制LED3亮灭为例 一、轮询方式 【0】检测按键k2按键k2按下一次灯LED2闪一次。 【1】查看原理图连接引脚和控制逻辑 1按键k2 连接在GPX1_1引脚 2控制逻辑 k2 按下 ---- K2闭合 ---- GPX1_1 低电压 k2 常态 ---- K2打开 ---- GPX1_1 高电压 【2】查看相应的芯片手册 【2-1】循环检测GPX1_1引脚输入的电平为低电压时按键按下 1配置GPX1_1引脚功能为输入设置内部上拉下拉禁止。 GPX1.CON GPX1.CON (~(0xf4)) ; GPX1.PUD GPX1.PUD ~(0x3 2); 2循环检测 [cpp] view plaincopy while(1) { if(!(GPX1.DAT (0x11))) // 返回为真按键按下 { msdelay(10); if(!(GPX1.DAT (0x11))) //二次检测去抖 { GPX2.DAT | 0x1 7; //Turn on LED2 mydelay_ms(500); GPX2.DAT ~(0x17); //Turn off LED2 mydelay_ms(500); while(!(GPX1.DAT (0x11))); } } } 这种轮询方式始终占着CPU不利于操作。 二、中断方式 将K2按下时GPX1_1引脚获得的电平作为异常事件。使能异常处理k2每按下一次响应一次异常处理。SPI 传递流程如下示 注 Exynos4412中断控制器包括160个中断控制源这些中断源来自软中断SGI私有外部中断PPI公共外部中断SPI。 Exynos4412采用GIC中断控制器主要是因为Contex-A9 是多核处理器GICGeneric Interrupt Controller通用中断控制器用来选择使用哪个CPU接口具体主要有两个功能 1分配器设置一个开关是否接收外部中断源为该中断源选择CPU接口 2CPU接口设置一个开发是否接受该中断源请求 具体实现如下 1、外设一级 ---设置 GPIO控制器 1-- 将GPX1_1引脚的上拉和下拉禁止 GPX1PUD[3:2] 0b00; 2 -- 将GPX1_1引脚功能设置为中断功能 WAKEUP_INT1[1] --- EXT_INT41[1] GPX1CON[7:4] 0xf 3 -- EXT_INT41CON 配置触发电平 当前配置成下降沿触发 EXT_INT41CON[6:4] 0x2 4 -- EXT_INT41_FLTCON0 配置中断引脚滤波 默认就是打开的不需要配置 5 -- EXT_INT41_MASK 中断使能寄存器 使能INT41[1] EXT_INT41_MASK[1] 0b0 6 -- EXT_INT41_PEND 中断状态寄存器 当GPX1_1引脚接收到中断信号中断发生中断状态寄存器EXT_INT41_PEND 相应位会自动置1 注意中断处理完成的时候需要清除相应状态位。置1清0. EXT_INT41_PEND[1] 0b1 2、中断控制器 1-- 找到外设中断名称和GIC中断控制器对应的名称 查看芯片手册本例Exynos_4412 -- 9.2表 WAKEUP_INT1[1] --- EXT_INT41[1] --- INT[9] --- SPI[25]/ID[57] 其对应INT[9]中断ID为57这是非常重要的在后面的寄存器设置中起很大作用 下面是外设与中断控制器处理具体流程 2 -- GIC使能 ICDDCR 1 使能分配器。 3 -- 使能相应中断到分配器 ICDISER.ICDISER1 | (0x1 25); //57/32 1...25 取整数那个寄存器 和余数哪位 ICDISER用于使能相应中断到分配器一个bit控制一个中断源一个ICDISER可以控制32个中断源这里INT[9] 对应的中断ID为57所以在ICDSER1中进行设置57/32 1余25所以这里在ICDISER1第25位置一。 4 -- 选择CPU接口 设置SPI[25]/ID[57]由那个cpu处理当前设置为cpu0的irq中断 ICDIPTR.ICDIPTR14 | 0x018; //SPI25 interrupts are sent to processor 0 //57/4 14..1 14号寄存器的[15:8] ICDIPTR寄存器每8个bit 控制一个中断源 5 -- 全局使能cpu0中断处理 CPU0.ICCICR | 0x1; 使能中断到CPU。 6 -- 优先级屏蔽寄存器设置cpu0能处理所有的中断。 CPU0.ICCPMR 0xFF; 3、ARM内核(cpu0) 前面两步设置好就可以等待中断的发生了当中断发生时ARM内核的处理过程如下 1-- 四大步三小步 --- 硬件 1拷贝 CPSR 到 SPSR_mode 2设置适当的 CPSR 位 2-1--改变处理器状态进入 ARM 态 2-2--改变处理器模式进入相应的异常模式 2-3--设置中断禁止位禁止相应中断 (如果需要) 3保存返回地址到 LR_mode 4设置 PC 为相应的异常向量 2 -- 中断服务程序 --- start.S 汇编 [cpp] view plaincopy .text .global _start _start: b reset ldr pc,_undefined_instruction ldr pc,_software_interrupt ldr pc,_prefetch_abort ldr pc,_data_abort ldr pc,_not_used ldr pc,_irq ldr pc,_fiq _undefined_instruction: .word _undefined_instruction _software_interrupt: .word _software_interrupt _prefetch_abort: .word _prefetch_abort _data_abort: .word _data_abort _not_used: .word _not_used _irq: .word irq_handler _fiq: .word _fiq reset: ldr r0,0x40008000 mcr p15,0,r0,c12,c0,0 Vector Base Address Register init_stack: ldr r0,stacktop /*get stack top pointer*/ /********svc mode stack********/ mov sp,r0 sub r0,#128*4 /*512 byte for irq mode of stack*/ /****irq mode stack**/ msr cpsr,#0xd2 mov sp,r0 sub r0,#128*4 /*512 byte for irq mode of stack*/ /***fiq mode stack***/ msr cpsr,#0xd1 mov sp,r0 sub r0,#0 /***abort mode stack***/ msr cpsr,#0xd7 mov sp,r0 sub r0,#0 /***undefine mode stack***/ msr cpsr,#0xdb mov sp,r0 sub r0,#0 /*** sys mode and usr mode stack ***/ msr cpsr,#0x10 mov sp,r0 /*1024 byte for user mode of stack*/ b main .align 4 /**** swi_interrupt handler ****/ /**** irq_handler ****/ irq_handler: sub lr,lr,#4 stmfd sp!,{r0-r12,lr} .weak do_irq bl do_irq ldmfd sp!,{r0-r12,pc}^ stacktop: .word stack4*512 .data stack: .space 4*512 3--中断处理程序 --- do_irq函数 C语言函数原型void name(void) 1 读取正在处理的中断ID寄存器ICCIAR irq_num (CPU0.ICCIAR 0x1FF); 2根据irq_num分支处理中断 [cpp] view plaincopy switch(irq_num) { . case 57: break; .... } 3清除中断状态位 3-1i.外设级EXT_INT41_PEND | 0x1 1; 3-2ii.GIC级ICDICPR.ICDICPR1 | 0x1 25; 3-3iii.CPU0级 CPU0.ICCEOIR (CPU0.ICCEOIR ~(0x1FF)) | irq_num; 下面是C 程序 [cpp] view plaincopy #include exynos_4412.h #include led.h void delay_ms(unsigned int num) { int i,j; for(inum; i0;i--) for(j1000;j0;j--) ; } void do_irq(void) { static int a 1; int irq_num; irq_num CPU0.ICCIAR0x3ff; //获取中断号 switch(irq_num) { case 57: printf(in the irq_handler\n); if(a) led_on(1); else led_off(1); a !a; EXT_INT41_PEND EXT_INT41_PEND |((0x1 1)); //清GPIO中断标志位 ICDICPR.ICDICPR1 ICDICPR.ICDICPR1 | (0x1 25); //清GIC中断标志位 break; } CPU0.ICCEOIR CPU0.ICCEOIR(~(0x3ff))|irq_num; //清cpu中断标志位 } /* * 裸机代码不同于LINUX 应用层 一定加循环控制 */ int main (void) { GPX1.CON GPX1.CON (~(0xf 4)) |(0xf 4); //配置引脚功能为外部中断 GPX1.PUD GPX1.PUD (~(0x3 2)); //关闭上下拉电阻 EXT_INT41_CON EXT_INT41_CON (~(0xf 4))|(0x2 4); //外部中断触发方式 EXT_INT41_MASK EXT_INT41_MASK (~(0x1 1)); //使能中断 ICDDCR 1; //使能分配器 ICDISER.ICDISER1 ICDISER.ICDISER1 | (0x1 25); //使能相应中断到分配器 ICDIPTR.ICDIPTR14 ICDIPTR.ICDIPTR14 (~(0xff 8))|(0x1 8); //选择CPU接口 CPU0.ICCPMR 255; //中断屏蔽优先级 CPU0.ICCICR 1; //使能中断到CPU led_init(); while(1) { } return 0; }