个人主页: 长夜漫漫想学习
本文收录专栏: ARM学习之路
其他专栏: C语言学习之路
学习格言:路漫漫其修远兮,吾将上下而求索
欢迎点赞、关注、收藏( •̀ ω •́ )✧ 一起努力,一起学习!
目录
1、ARM程序启动执行
2、接口编程
2.1、点亮LED灯(实验)
2.2、硬件接口编程的流程
2.3、start.s程序里实现点亮LED灯
3、按键控制LED灯
3.1、GPX1寄存器
3.2、GPX1CON(配置寄存器)
3.3、GPX1DAT(数据寄存器)
3.4、按键控制LED程序
对于ARM的CPU,当执行程序时有可能产生异常,此时CPU会切换到对应的工作模式,CPU会跳到异常向量表去执行(PC会赋值为对应的异常地址)。
对于ARM程序,第一段执行代码为异常向量表,为汇编代码,进行对应的异常向量定义、初始化、异常处理。
通过CPU如何控制外部硬件这样的编程过程,理解为接口编程。
GPIO:挂载在APB总线上,GPIO为通用输入输出端口。管理芯片上所有的引脚的输入与输出。
GPIO控制器作用:
(1)输出高电平或低电平
(2)输入高电平或低电平
(1)找到对应控制设备----LED(本实验LED)
(2)进行电路分析,从外设板连接到核心板,外部硬件和soc控制器连接控制。
(3)设置芯片的控制器控制引脚线的高低电平
编程流程
查看LED电路
查看SOC连接对应引脚
LED3----连接芯片引脚为A3,只要芯片的控制器能够控制引脚线为高电平,LED就亮
LED3----XEINT8/KP_COLO/ALV_DBG4/GPX1_0
GPX1_0----GPIO----X1(控制器管脚组)----0(组中引脚编号为0)
GPX1控制器
GPX1CON(控制寄存器)配置
GPX1DAT(数据寄存器)
GPX1CON控制器,通过操作对应的寄存器(赋值),GPX1CON控制器就完成对应的功能在寄存器中,某几位用来表示一个编号(管脚)。
GPX1DAT(数据寄存器):如果是输入模式,则对应位的值就表示外部引脚的电平状态(如: [5]位,表示是第5号管脚的电平),如果是输出模式,则对应位的值就表示输出到外部引脚的电平状态(如:[4]位,则表示输出到第4号管脚的电平)
GPX1CON:控制寄存器(控制功能) ---- 0x11000C20
GPX1DAT:数据寄存器 ---- 0x11000C24
GPXXCON:用于选择引脚功能
GPXXDAT:用于读/写引脚数据
[3:0] :0x1----output(本实验选择0x1)、0x0----input
[0] :GPX1控制器对应0号引脚
GPX1DAT:操作0号引脚电平--—[0]---0号引脚
汇编程序
_data_abort: .word _data_abort
_not_used: .word _not_used
_irq: .word irq_handler
_fiq: .word _fiq
reset:
ldr r0,=0x40008000
mcr p15,0,r0,c12,c0,0 @ Vector Base Address Register
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0 @ Enable svc mode of cpu
mov r0, #0xfffffff
mcr p15, 0, r0, c1, c0, 2 @ Defines access permissions for each coprocessor
@ Privileged and User mode access
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
@Set the FPEXC EN bit to enable the FPU:
MOV r3, #0x40000000
fmxr FPEXC, r3
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00001000 @ set bit 12 (---I) Icache
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0
/* LED Test Code */
/*
ldr r0, =0x114001E0
ldr r1, [r0]
bic r1, r1, #0xf0000
orr r1, r1, #0x10000
str r1, [r0]
ldr r0, =0x114001E8
ldr r1, [r0]
bic r1, r1, #0x300
str r1, [r0]
ldr r0, =0x114001E4
ldr r1, [r0]
orr r1, r1, #0x10
str r1, [r0]
*/
init_stack:
ldr r0,stacktop /*get stack top pointer*/
/********svc mode stack********/
mov sp,r0
sub r0,#128*4 /*512 byte for irq mode of stack*/
/****irq mode stack**/
msr cpsr,#0xd2
mov sp,r0
sub r0,#128*4 /*512 byte for irq mode of stack*/
/***fiq mode stack***/
msr cpsr,#0xd1
mov sp,r0
sub r0,#0
/***abort mode stack***/
msr cpsr,#0xd7
mov sp,r0
sub r0,#0
/***undefine mode stack***/
msr cpsr,#0xdb
mov sp,r0
sub r0,#0
/*** sys mode and usr mode stack ***/
msr cpsr,#0x10
mov sp,r0 /*1024 byte for user mode of stack*/
@/---------------点亮LED灯----------------/
led_on:
@led3
@gpx1_0 GPX1 0
ldr r0,=0x11000c20
ldr r1,[r0] @ r1 =[3:0]的值
bic r1,#0xf
orr r1,#0x1
str r1,[r0]
@ gpxdat
ldr r1,[r0,#4]
orr r1,#0x1
str r1,[r0,#4]
loop:
b loop
注:GPX1CON-----0x0c20
GPX1DAT-----0x0c24
注:配置input(0x0)功能
一个按键控制两个LED灯
void delay()//延时函数
{
int i=0,j=0;
for(;i<100000;i++)
{
for(;j<1000000;j++)
{
}
}
}
int main()
{
unsigned int * k2 = 0x11000c20;//key2
unsigned int *p=0x11000c20;
unsigned int *q=0x11000c40;
*k2 = *k2 & ~(0xf<<4);//把4-7位清零,配置为输入
*p = *p & ~(0xf) | 0x1; //output
*q = *q & ~(0xf<<28) | (0x1<<28); //output
k2 = k2+1;//把寄存器的值全部取出,查看第一位(引脚1)
while(1)
{
if((*k2 & 1<<1) != 0)//k2未按下时执行
{
*(p+1) = *(p+1) & ~1 | 1; //led3_on(亮)
delay();
*(p+1) = *(p+1) & ~1 ; //led3_off(灭)
delay();
}
else
{
*(q+1) = *(q+1) & ~1<<7 | 1<<7; //led2_on(亮)
delay();
*(q+1) = *(q+1) & ~1<<7 ; //led2_off(灭)
delay();
}
}
return 0;
}
使用两个按键分别控制LED灯
void delay()//延时函数
{
int i=0,j=0;
for(;i<100000;i++)
{
for(;j<1000000;j++)
{
}
}
}
int main()
{
unsigned int * k2 = 0x11000c20;//key2
unsigned int * k3 = 0x11000c20;//key3
unsigned int *p=0x11000c20;
unsigned int *q=0x11000c40;
*k2 = *k2 & ~(0xf<<4);//把4-7位清零,配置为输入
*k3 = *k3 & ~(0xf<<8);
*p = *p & ~(0xf) | 0x1; //output
*q = *q & ~(0xf<<28) | (0x1<<28); //output
k2 = k2+1;//把寄存器的值全部取出,查看第一位(引脚1)
k3 = k3+1;
while(1)
{
if((*k2 & 1<<1) == 0)//k2按下时执行
{
*(p+1) = *(p+1) & ~1 | 1; //led3_on(亮)
delay();
*(p+1) = *(p+1) & ~1 ; //led3_off(灭)
delay();
}
if((*k3 & 1<<2) == 0)//k3按下时执行
{
*(q+1) = *(q+1) & ~1<<7 | 1<<7; //led2_on(亮)
delay();
*(q+1) = *(q+1) & ~1<<7 ; //led2_off(灭)
delay();
}
}
return 0;
}
✨本篇到此结束啦!欢迎点赞收藏❤关注