×
单片机 > 单片机程序设计 > 详情

TQ210——按键(中断查询法)

发布时间:2021-05-07 发布时间:
|

底板上有8个独立按键,可分别使用查询法和中断法控制按键。通过原理图可知:按键按下,GPIO检测到低电平,松开时高电平。


直接查询法程序的实现简单,但是效率很低,CPU一直在查询,啥事也干不了。中断查询法程序的实现较为复杂,但是效率高。


GPIO寄存器(GPH0CON,GPH0DAT),外部中断寄存器(EXT_INT_0_CON,EXT_INT_0_MASK),中断通道选择(VIC0INTSELECT),中断使能(VIC0INTENABLE),中断向量地址(VIC0VECTADDR0,VIC0VECTADDR1),清除中断向量(EXT_INT_0_PEND)


.global _start /*声明一个全局的标号 */

.global key_isr

_start:

/* 设置栈,以调用c函数 */

ldr sp, =0x40000000

/* 开总中断 */

mrs r0,cpsr

bic r0,r0, #0x00000080 /* 清楚第7位,IRQ中断禁止位,写0使能IRQ */

msr cpsr,r0

bl main /* 跳转到C函数去执行 */

halt:

b halt

key_isr:

/* 计算返回地址:PC的值等于当前执行的地址+8,

** 当CPU正要执行某条指令时(还未执行),被中断,

** 这是这条刚要执行的指令的地址刚好=PC-4 */

sub lr,lr, #4

stmfd sp!,{r0-r12, lr} /* 保护现场 */

bl key_handle

/* 恢复现场 */

ldmfd sp!,{r0-r12, pc}^ /* ^表示把spsr恢复到cpsr */

#define GPC0CON *((volatileunsigned int *)0xE0200060)

#define GPC0DAT *((volatileunsigned int *)0xE0200064)

#define GPH0CON *((volatileunsigned int *)0xE0200C00)

#define GPH0DAT *((volatileunsigned int *)0xE0200C04)

#define EXT_INT_0_CON *((volatileunsigned int *)0xE0200E00)

#define EXT_INT_0_MASK *((volatileunsigned int *)0xE0200F00)

#define VIC0INTSELECT *((volatileunsigned int *)0xF200000C)

#define VIC0INTENABLE *((volatileunsigned int *)0xF2000010)

#define VIC0VECTADDR0 *((volatileunsigned int *)0xF2000100)

#define VIC0VECTADDR1 *((volatileunsigned int *)0xF2000104)

#define VIC0ADDRESS *((volatile unsigned int*)0xF2000F00)

#define EXT_INT_0_PEND *((volatileunsigned int *)0xE0200F40)

extern void key_isr(void);

void key_handle()

{

volatileunsigned char key_code = EXT_INT_0_PEND & 0x03;

VIC0ADDRESS= 0; /* 清中断向量寄存器 */

EXT_INT_0_PEND&= ~0x03; /* 清中断挂起寄存器 */

if(key_code == 1) /* key1 */

{

GPC0DAT&= ~(0x01 << 3); /* toggleLED1 */

GPC0DAT|= 1 << 3; /* toggle LED1 */

}

else if(key_code == 2) /* key2 */

{

GPC0DAT&= ~(0x01 << 4); /* toggleLED1 */

GPC0DAT|= 1 << 4; /* toggle LED1 */

}

}

int main()

{

GPC0CON&= ~(0xFF << 12);

GPC0CON |=0x11 << 12; /*配置GPC0_3和GPC0_4为输出:LED1和LED2 */

GPH0CON |=0xFF << 0; /*配置GPH0_0和GPH0_1为外部中断:key1和key2 */

EXT_INT_0_CON&= ~(0xFF << 0);

EXT_INT_0_CON|= 2 | (2 << 4); /*配置EXT_INT[0]和EXT_INT[1]为下降沿触发 */

EXT_INT_0_MASK&= ~3; /* 取消屏蔽外部中断EXT_INT[0]和EXT_INT[1] */

VIC0INTSELECT&= ~3; /*选择外部中断EXT_INT[0]和外部中断EXT_INT[1]为IRQ类型的中断 */

VIC0INTENABLE|= 3; /*使能外部中断EXT_INT[0]和EXT_INT[1] */

/* 当EXT_INT[0]触发中断,即用户按下key1时,

** CPU就会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS并跳转到这个地址去执 */

VIC0VECTADDR0= (unsigned int)key_isr;

VIC0VECTADDR1= (unsigned int)key_isr;

while (1);

return 0;

}


裸机编程编译的时候一定要加16字节的头信息,编译生成的bin文件通过SD卡或者TFTP的方法下载到开发板。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
FPGA和AVR单片机的自动调谐系的设计