TQ210裸机编程(4)——按键(中断法)

来源:互联网 发布:after school知乎 编辑:程序博客网 时间:2024/05/16 15:13

S5PV210有4个向量中断控制器(VIC),每个向量中断控制器包含32个中断源。

当某个中断源产生中断时,CPU会自动的将VICxVECTADDRy(x=0,1,2,3,y=0-31)寄存器的值赋给VICxADDRESS(x=0,1,2,3),因此我们可以把我们的中断处理函数的地址赋给VICxVECTADDRy寄存器,

比如我们有个函数

void key_handle()
{    
……
}

我们把key_handle 函数的值赋给VIC0VECTADDR0(外部中断0)

VIC0VECTADDR0 =key_handle;


当外部中断0触发中断时,CPU会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS,并跳转到这个地址去执行,即执行函数key_handle。


代码如下:

start.S

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. .global _start                  /* 声明一个全局的标号 */  
  2. .global key_isr  
  3. _start:  
  4.     /* 设置栈,以调用c函数 */  
  5.     ldr sp, =0x40000000       
  6.   
  7.     /* 开总中断 */  
  8.     mrs r0, cpsr  
  9.     bic r0, r0, #0x00000080     /* 清楚第7位,IRQ中断禁止位,写0使能IRQ */  
  10.     msr cpsr, r0  
  11.   
  12.     bl main                     /* 跳转到C函数去执行 */  
  13.   
  14. halt:  
  15.     b halt  
  16.   
  17. key_isr:  
  18.     /* 计算返回地址:PC的值等于当前执行的地址+8,当CPU正要执行某条指令时(还未执行),被中断, 
  19.     ** 这是这条刚要执行的指令的地址刚好=PC-4 */  
  20.     sub lr, lr, #4  
  21.     stmfd sp!, {r0-r12, lr}     /* 保护现场 */  
  22.     bl key_handle  
  23.     /* 恢复现场 */  
  24.     ldmfd sp!, {r0-r12, pc}^    /* ^表示把spsr恢复到cpsr */  

key.c

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #define GPC0CON             *((volatile unsigned int *)0xE0200060)  
  2. #define GPC0DAT             *((volatile unsigned int *)0xE0200064)  
  3.   
  4. #define GPH0CON             *((volatile unsigned int *)0xE0200C00)  
  5. #define GPH0DAT             *((volatile unsigned int *)0xE0200C04)  
  6.   
  7. #define EXT_INT_0_CON       *((volatile unsigned int *)0xE0200E00)  
  8. #define EXT_INT_0_MASK      *((volatile unsigned int *)0xE0200F00)  
  9.   
  10. #define VIC0INTSELECT       *((volatile unsigned int *)0xF200000C)  
  11. #define VIC0INTENABLE       *((volatile unsigned int *)0xF2000010)  
  12.   
  13. #define VIC0VECTADDR0       *((volatile unsigned int *)0xF2000100)  
  14. #define VIC0VECTADDR1       *((volatile unsigned int *)0xF2000104)  
  15.   
  16. #define VIC0ADDRESS         *((volatile unsigned int *)0xF2000F00)  
  17.   
  18. #define EXT_INT_0_PEND      *((volatile unsigned int *)0xE0200F40)  
  19.   
  20. extern void key_isr(void);  
  21.   
  22. void key_handle()  
  23. {     
  24.     volatile unsigned char key_code = EXT_INT_0_PEND & 0x3;  
  25.       
  26.     VIC0ADDRESS = 0;        /* 清中断向量寄存器 */  
  27.     EXT_INT_0_PEND |= 3;    /* 清中断挂起寄存器 */  
  28.       
  29.     if (key_code == 1)      /* key1 */  
  30.         GPC0DAT ^= 1 << 3;    /* toggle LED1 */  
  31.     else if (key_code == 2) /* key2 */  
  32.         GPC0DAT ^= 1 << 4;    /* toggle LED2 */  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     GPC0CON &= ~(0xFF << 12);  
  38.     GPC0CON |= 0x11 << 12;                    /* 配置GPC0_3和GPC0_4为输出:LED1和LED2 */  
  39.     GPH0CON |= 0xFF << 0;                 /* 配置GPH0_0和GPH0_1为外部中断:key1和key2 */  
  40.       
  41.     EXT_INT_0_CON &= ~(0xFF << 0);  
  42.     EXT_INT_0_CON |= 2 | (2 << 4);            /* 配置EXT_INT[0]和EXT_INT[1]为下降沿触发 */  
  43.     EXT_INT_0_MASK &= ~3;                   /* 取消屏蔽外部中断EXT_INT[0]和EXT_INT[1] */  
  44.       
  45.     VIC0INTSELECT &= ~3;                    /* 选择外部中断EXT_INT[0]和外部中断EXT_INT[1]为IRQ类型的中断 */  
  46.       
  47.     VIC0INTENABLE |= 3;                     /* 使能外部中断EXT_INT[0]和EXT_INT[1] */  
  48.       
  49.     VIC0VECTADDR0 = (int)key_isr;           /* 当EXT_INT[0]触发中断,即用户按下key1时, 
  50.                                              CPU就会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS并跳转到这个地址去执 */  
  51.     VIC0VECTADDR1 = (int)key_isr;  
  52.       
  53.     while (1);  
  54.       
  55.     return 0;  
  56. }  

Makefile

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. key.bin: start.o key.o  
  2.     arm-linux-ld -Ttext 0x20000000 -o key.elf $^  
  3.     arm-linux-objcopy -O binary key.elf $@  
  4.     arm-linux-objdump -D key.elf > key.dis  
  5.       
  6. key.o : key.c  
  7.     arm-linux-gcc -c $< -o $@  
  8. start.o : start.S  
  9.     arm-linux-gcc -c $< -o $@  
  10.       
  11. clean:  
  12.     rm *.o *.elf *.bin *.dis  

将程序下载到内存运行

按下key1,LED1点亮,再次按下key1,LED1熄灭

按下key2,LED2点亮,再次按下key2,LED2熄灭


0 0
原创粉丝点击