历史上的今天
今天是:2024年12月23日(星期一)
2020年12月23日 | TQ210裸机编程(4)——按键(中断法)
2020-12-23 来源:eefocus
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。
代码如下:
.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 */
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) /* key1 */
GPC0DAT ^= 1 << 3; /* toggle LED1 */
else if (key_code == 2) /* key2 */
GPC0DAT ^= 1 << 4; /* toggle LED2 */
}
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] */
VIC0VECTADDR0 = (int)key_isr; /* 当EXT_INT[0]触发中断,即用户按下key1时,
CPU就会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS并跳转到这个地址去执 */
VIC0VECTADDR1 = (int)key_isr;
while (1);
return 0;
}
Makefile
key.bin: start.o key.o
arm-linux-ld -Ttext 0x20000000 -o key.elf $^
arm-linux-objcopy -O binary key.elf $@
arm-linux-objdump -D key.elf > key.dis
key.o : key.c
arm-linux-gcc -c $< -o $@
start.o : start.S
arm-linux-gcc -c $< -o $@
clean:
rm *.o *.elf *.bin *.dis
将程序下载到内存运行
按下key1,LED1点亮,再次按下key1,LED1熄灭
按下key2,LED2点亮,再次按下key2,LED2熄灭
史海拾趣
|
C系列中文模块可以显示字母、数字符号、中文字型及图形,具有绘图及文字画面混合显示功能。提供 三种控制接口,分别是8位微处理器接口,4位微处理器接口及串行接口(OCMJ4X16A/B无串行接口)。所 有的功能,包含显示RAM,字型产生器,都包含在一 ...… 查看全部问答> |
|
报名页面:https://www.eeworld.com.cn/formguide/index.php?formid=90 (请在备注中注明自己所参与的部分) DIY示波器活动QQ群:16254999 在整体方案上参考上的示波器设计方案,采用STM32F103RBT6作为主控CPU,LPC2103作为辅助CPU,对于原有模拟 ...… 查看全部问答> |
|
用热电偶测温,经单片机pid调节,触发固态继电器实现线性升温 但当电网电压变化时,升温曲线不稳定,很不线性 原因到底出在哪里呢,高次谐波?继电器?pid参数?还是其它因素,希望大家各抒己见,十分希望能得到各位的帮助,谢谢!… 查看全部问答> |
|
给分虽然少,但已经是本人分数的多一半了,不好意思哈 现在具体说一下问题的内容: 核心是把mp3文件烧录到arm7板的片外nor flash中,如果没有操作系统,也没有文件系统的话,我应该怎么考虑呢?按照字节串口传输吗?我该如何把mp3文件转成字节的 ...… 查看全部问答> |
|
VC6编的程序,想在ARM9模块上运行,程序是关于串口输入输出的,还有同上位机数据库连接的内容,用了MFC。 请问一下,我这个程序转为EVC4程序,要作些什么,难度几何?… 查看全部问答> |
|
做一个程序 需在WinCE系统.net 1.0 上运行,有什么方法用.net 2.0里实现的功能吗?比如实现WebBrowser功能,能否引用System.Windows.Forms.dll来实现? 虽然几乎不可能,但我还是要问,想知道为什么不行?… 查看全部问答> |
|
Spartan-6 LX9 Microboard不用XCF04怎么实现配置 Spartan-6 LX9 Microboard开发板中不用XCF04怎么实现配置的。 想知道原来装有XCFO4,怎样去掉。 好像只有TDO信号没连拉到JTAG。 [ 本帖最后由 sdjntl 于 2011-8-4 17:39 编辑 ]… 查看全部问答> |
|
采集220V交流电压的时候,交流信号的N线是不是和运放的地是一个啊,无论220是先经过电阻分压还是互感器,220V经过AC/DC给运放供电,都没法让N线和运放的地共起来啊!求指点 … 查看全部问答> |




