实现功能:GPF0和GPF1接的两个按键,GPB0和GPB1接两个LED,用中断方式按GPF0时,GPB0亮,按GPF1时,GPB1亮。
实验程序:
.extern main
.text
.global _start
_start:
b reset
HandleUndef:
b HandleUndef @未定义指令终止模式
HandleSWI:
b HandleSWI @管理模式地址
HandlePrefetchAbort:
b HandlePrefetchAbort @指令预取终止模式
HandleDateAbort:
b HandleDateAbort @数据访问终止模式
HandleNotUsed:
b HandleNotUsed @保留
b HandleIRQ @IRQ中断模式
HandleFIQ:
b HandleFIQ
reset:
ldr sp,=1024*4 @复位模式的堆栈
bl watch_dog @关闭看门狗
msr cpsr_c,#0xd2 @进入中断模式
ldr sp,=1024*3 @中断模式的栈地址
msr cpsr_c,#0xdf @系统模式
ldr sp,=1024*4
bl led_init @led初始化
bl Interupt_init @中断初始化函数
msr cpsr_c,#0x5f @开启中断
ldr lr,=loop @此两句调用也可用bl main语句
ldr pc,=main
loop:
b loop
HandleIRQ:
sub lr,lr,#4 @计算返回地址
stmdb sp!,{r0-r12,lr} @保存使用到的寄存器
ldr lr,=int_return
ldr pc,=Inter_Handle @调用中断处理函数
int_return:
ldmia sp!,{r0-r12,pc}^ @中断返回
初始化程序:
#include "s3c2410.h"
#define GPB0_out (1<<(0*2))
#define GPB1_out (1<<(1*2))
#define GPF0_eint (2<<(0*2))
#define GPF1_eint (2<<(1*2))
//#define GPF0_disup (1)
//#define GPF1_disup (1<<1)
#define eint0 (~1)
#define eint1 (~(1<<1))
#define ARB_mode0 (~1)
#define ARB_mode6 (~(1<<6))
void watch_dog()
{
WTCON = 0;
}
void led_init()
{
GPBCON |= (GPB0_out | GPB1_out);
GPFCON |= (GPF0_eint | GPF1_eint);
// GPFUP |= (GPF0_disup | GPF1_disup);
}
void Interupt_init()
{
//EXTINT0 |= (3<<0)|(3<<3);
INTMSK &= (eint0 & eint1);
PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) ;
//RIORITY &= (ARB_mode0 & ARB_mode6);
}
中断服务程序:
#include "s3c2410.h"
void Inter_Handle()
{
unsigned long key_down;
key_down = INTOFFSET;
switch(key_down)
{
case 0:
{
GPBDAT |= 0x03; //此语句重要,若没有它,将会出现全亮
GPBDAT &= (~1);
break;
}
case 1:
{
GPBDAT |= 0x03;
GPBDAT &= (~(1<<1));
break;
}
default:
break;
}
SRCPND = (1< INTPND = (1<
}
主函数:
int main()
{
while(1);
return 0;
}
试验中遇到的问题:
主要是arm汇编指令 B 和 BL指令,用B指令调用时,直接跳转到给定的地址,而不保存R14, BL指令与B指令不同的是保存R14,所以在这个实验中,最开始用的是B指令,怎么调也没有调出来,郁闷坏了。之后用BL指令,一烧写就好使了。还有就是其中这条语句: GPBDATA |= 0x03,这条语句也很重要。若没有这条语句,
经过一两次,就变成全亮了。低两位全为0了。
阅读(1461) | 评论(1) | 转发(0) |