历史上的今天
今天是:2024年12月25日(星期三)
2020年12月25日 | TQ210_裸机编程(二)——按键控制LED灯
2020-12-25 来源:eefocus
首先我们可以在开发板配套材料中找到按键的电路图,E:TQ210_CD开发板配套电路图Bottompdf格式TQ210_BOARD_V4_20121023。

可以看到按键key1~key6对应的地址线为XEINT0~XEINT5,我们暂时就只用前面几个按键。
然后我们再找地址线在板子中相应的引脚号。

可以看到 按键地址线XEINT0~XEINT5对应的管脚号为GPH0_1~GPH0_5。
现在在S5PV210_UM_REV1.1文档中就能找到GPH0的控制寄存器,对应的控制6个按键。

将按键控制寄存器都设置为外部中断处理。然后去设定外部中断的处理相应参数。
外部中断要设置2个中断寄存器,EXT_INT_CON,EXT_INT_MASK。

由于按键按下时为低电平,所以全部设置为Falling edge triggered。
设置完EXT_INT_CON,还要设置EXT_INT_MASK,(外部中断控制寄存器)。

将需要使用的按键对应的外部中断处理 设置为允许中断。
再设置中断选择寄存器VIC0INTSELECT,选择中断模式(一般为IRQ模式)。

之后再设置VICINTENABLE寄存器,中断使能寄存器。

当中断发生时,需要一个存放中断处理的寄存器VICVECTADDR,中断发生后,就跳转到该寄存器里的函数开始执行。
例如:
VIC0VECTADDR0 = (unsigned int)key_isr;
中断发生后就跳转到key_isr处去执行了。
但是涉及到跳转执行的时候,就需要考虑保护现场的操作了。
例如:在key_isr中
key_isr:
/* 计算返回地址:PC的值等于当前执行的地址+8,
** 当CPU正要执行某条指令时(还未执行),被中断,
** 这是这条刚要执行的指令的地址刚好=PC-4(可查三级流水线工作原理) */
sub lr, lr, #4
stmfd sp!, {r0-r12, lr} /* 保护现场 ,由于不知道使用的具体哪个通用寄存器,所以讲0~12全部压栈*/
bl key_handle
/* 恢复现场 */
ldmfd sp!, {r0-r12, pc}^ /* ^表示把spsr恢复到cpsr */
由于用到中断处理,所以对cpsr(当前程序状态寄存器)要进行参数设置,


要使用IRQ中断,就要使i位为0,
/* 开总中断 */
mrs r0, cpsr /*传送cpsr的内容到r0*/
bic r0, r0, #0x00000080 /* 清楚第7位,IRQ中断禁止位,写0使能IRQ */
msr cpsr, r0 /*传送r0的内容到cpsr*/
BIC―――――位清除指令
指令格式:
BIC{cond}{S} Rd,Rn,operand2
BIC指令将Rn 的值与操作数operand2 的反码按位逻辑”与”,结果存放到目的寄存器Rd 中。指令示例:BIC R0,R0,#0x0F ;将R0最低4位清零,其余位不变。
在上面保护现场的时,程序跳转到key_handle执行。
void key_handle()
{
volatile unsigned char key_code = EXT_INT_0_PEND & 0x3;
VIC0ADDRESS = 0;
EXT_INT_0_PEND |= 3;
if (key_code == 1)
/* GPC0DAT ^= 1 << 3;*/
GPC0DAT |= 0x00000008;
else if (key_code == 2)
/* GPC0DAT ^= 1 << 4;*/
GPC0DAT |= 0x00000010;
}
程序中EXT_INT_0_PEND寄存器为发生中断后的数据变化。1就是发生了中断。

整体源代码如下:
/*key.c*/
#define GPC0CON *((volatile unsigned int *)0xE0200060)
#define GPC0DAT *((volatile unsigned int *)0xE0200064)
#define GPH0CON *((volatile unsigned int *)0xE0200C00)
#define GPH0DAT *((volatile unsigned int *)0xE0200C04)
#define EXT_INT_0_CON *((volatile unsigned int *)0xE0200E00)
#define EXT_INT_0_MASK *((volatile unsigned int *)0xE0200F00)
#define VIC0INTSELECT *((volatile unsigned int *)0xF200000C)
#define VIC0INTENABLE *((volatile unsigned int *)0xF2000010)
#define VIC0VECTADDR0 *((volatile unsigned int *)0xF2000100)
#define VIC0VECTADDR1 *((volatile unsigned int *)0xF2000104)
#define VIC0ADDRESS *((volatile unsigned int *)0xF2000F00)
#define EXT_INT_0_PEND *((volatile unsigned int *)0xE0200F40)
extern void key_isr(void);
void key_handle()
{
volatile unsigned char key_code = EXT_INT_0_PEND & 0x3;
VIC0ADDRESS = 0;
EXT_INT_0_PEND |= 3;
if (key_code == 1)
/* GPC0DAT ^= 1 << 3;*/
GPC0DAT |= 0x00000008;
else if (key_code == 2)
/* GPC0DAT ^= 1 << 4;*/
GPC0DAT |= 0x00000010;
}
int main()
{
GPC0CON &= ~(0xFF << 12);
GPC0CON |= 0x11 << 12;
GPH0CON |= 0xFF << 0;
EXT_INT_0_CON &= ~(0xFF << 0);
EXT_INT_0_CON |= 2 | (2 << 4);
EXT_INT_0_MASK &= ~3;
VIC0INTSELECT &= ~3;
VIC0INTENABLE |=3;
VIC0VECTADDR0 = (unsigned int)key_isr;
VIC0VECTADDR1 = (unsigned int)key_isr;
while (1);
return 0;
}
/*start.S*/
.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 */
史海拾趣
|
我在keil软件里编了一个程序,通过此软件编译连接是好的,无错误,无警告。但当我把它放到仿真器软件里时编译的时候就有错误了,这是怎么一回事?应该如何解决它。以下是那个软件以及仿真软件提示的错误,请大家给我指点一下了,谢谢! //======= ...… 查看全部问答> |
|
我的工程是基于WCE嵌入式系统,生成的nk.nb0用串口烧写 我的工程是基于WCE嵌入式系统,生成的nk.nb0用串口烧写进去,有两种不同的情况 ,一种是直接进入我在EVC中生成的.exe界面,一种是进入WCE的界面,这两种不同的情况是由哪个来决定的了,请问各位大侠了,小女子先谢谢了哈 … 查看全部问答> |
|
大家好。 小弟今年大三,做java开发,对汇编,单片机这样的东西是一点不懂,偏偏老师是一个非常严的人,课程设计一点一点查,抄是没的希望了,只能来这里求助了,望高手不吝赐教,先谢谢了。 一:课程设计目的: 1.在掌握“EL-JY-II计算机组成原 ...… 查看全部问答> |
|
本帖最后由 dontium 于 2015-1-23 11:24 编辑 PAGE 0 : VECS : origin = 0h , length = 040h /* VECTORS */ & ...… 查看全部问答> |




