目录
一、所需知识点储备
-
常见二极管和三极管
二极管:当A点电流大于B点时,二极管从左往右导通
三极管: 左图:当A点电流大于B点时,电流从上往下走,三极管导通;
右图:当B点电流大于A点时,电流从下往上走
-
常见的LED原理图
第一种:
第二种:
第三种:
第四种:
-
开发板所用原理图
-
详解所需寄存器
1、详解GPFCON(0x56000050)
GPFCON用于选取引脚,要使用某个引脚的时候需要打来芯片手册进行查看,I/O的在手册P292.
该开发板引出用于LED灯的引脚是GPF4、5、6,我们现在点亮第一个LED所用到的是GPF4引脚,所以要将GPF4[9:8]设置为01的输出功能。其他引脚不变。即GPFCON=0000000100000000,用电脑计算器进行进制换算得到十六进制为0x100。
用汇编表示
ldr r1, =0x56000050
ldr r0, =0x100 /* mov r0, #0x100 */
str r0, [r1]
用C语言表示
unsigned int *pGPFCON = (unsigned int *)0x56000050;
/* 配置GPF4为输出引脚 */
*pGPFCON = 0x100;
2、详解GPFDAT(0x56000054)
GPFDAT用于引脚输出高电平还是低电平,当配置为1时输出高电平,配置为0时输出低电平。从开发板原理图草图可以看出,这里要设置为0输出低电平时LED才会亮
用汇编表示
ldr r1, =0x56000054
ldr r0, =0 /* mov r0, #0 */
str r0, [r1]
用C语言表示
unsigned int *pGPFDAT = (unsigned int *)0x56000054;
*pGPFDAT = 0;
3、详解GPFUP(0x56000058)
GPFUP用于是否禁用上拉功能,该功能现在不需要,所以不用配置。
二、点亮LED功能实现
1、用汇编点亮
.text
.global _start
_start:
/* 配置GPF4为输出引脚
* 把0x100写到地址0x56000050
*/
ldr r1, =0x56000050
ldr r0, =0x100 /* mov r0, #0x100 */
str r0, [r1]
/* 设置GPF4输出高电平
* 把0写到地址0x56000054
*/
ldr r1, =0x56000054
ldr r0, =0 /* mov r0, #0 */
str r0, [r1]
/* 死循环 */
halt:
b halt
2、用C语言点亮
//main.c
int main()
{
unsigned int *pGPFCON = (unsigned int *)0x56000050;
unsigned int *pGPFDAT = (unsigned int *)0x56000054;
/* 配置GPF4为输出引脚 */
*pGPFCON = 0x100;
/* 设置GPF4输出0 */
*pGPFDAT = 0;
return 0;
}
//start.S
.text
.global _start
_start:
/* 设置内存: sp 栈 */
ldr sp, =4096 /* nand启动 */
// ldr sp, =0x40000000+4096 /* nor启动 */
/* 调用main */
bl main
halt:
b halt
分析使用汇编编写生成的led.dis
分析使用C语言编写生成的led.dis
三、两个LED交换闪烁
1、用C语言编写
/* volatile:防止编译器自作聪明,自动优化掉这个不常用的方法 */
void delay(volatile int d)
{
while (d--);
}
int led_on(int which)
{
unsigned int *pGPFCON = (unsigned int *)0x56000050;
unsigned int *pGPFDAT = (unsigned int *)0x56000054;
/* start.S中如果r0传入值为4,点亮GPF4, 值为5,点亮GPF5*/
if (which == 4)
{
/* 配置GPF4为输出引脚 */
*pGPFCON = 0x100;
}
else if (which == 5)
{
/* 配置GPF5为输出引脚 */
*pGPFCON = 0x400;
}
/* 设置GPF4/5输出0 */
*pGPFDAT = 0;
return 0;
}
2、编写start.S
.text
.global _start
_start:
/* 设置内存: sp 栈 */
ldr sp, =4096 /* nand启动 */
// ldr sp, =0x40000000+4096 /* nor启动 */
/* 在ARM寄存器中,r0,r1,r2,r3是用于传参,返回结果的寄存器,可以将值赋给它们 */
mov r0, #4
bl led_on
ldr r0, =100000
bl delay
mov r0, #5
bl led_on
halt:
b halt
四、三个LED循环点亮
1、用C语言编写
void delay(volatile int d)
{
while (d--);
}
int main(void)
{
volatile unsigned int *pGPFCON = (volatile unsigned int *)0x56000050;
volatile unsigned int *pGPFDAT = (volatile unsigned int *)0x56000054;
int val = 0; /* val: 0b000, 0b111 */
int tmp;
/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
*pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));
*pGPFCON |= ((1<<8) | (1<<10) | (1<<12));
/* 循环点亮 */
while (1)
{
tmp = ~val;
tmp &= 7;
*pGPFDAT &= ~(7<<4);
*pGPFDAT |= (tmp<<4);
delay(100000);
val++;
if (val == 8)
val =0;
}
return 0;
}
2、编写start.S
void delay(volatile int d)
{
while (d--);
}
int main(void)
{
volatile unsigned int *pGPFCON = (volatile unsigned int *)0x56000050;
volatile unsigned int *pGPFDAT = (volatile unsigned int *)0x56000054;
int val = 0; /* val: 0b000, 0b111 */
int tmp;
/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
*pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));
*pGPFCON |= ((1<<8) | (1<<10) | (1<<12));
/* 循环点亮 */
while (1)
{
tmp = ~val;
tmp &= 7;
*pGPFDAT &= ~(7<<4);
*pGPFDAT |= (tmp<<4);
delay(100000);
val++;
if (val == 8)
val =0;
}
return 0;
}
五、按键点亮LED
1、用C语言编写
void delay(volatile int d)
{
while (d--);
}
int main(void)
{
volatile unsigned int *pGPFCON = (volatile unsigned int *)0x56000050;
volatile unsigned int *pGPFDAT = (volatile unsigned int *)0x56000054;
int val = 0; /* val: 0b000, 0b111 */
int tmp;
/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
*pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));
*pGPFCON |= ((1<<8) | (1<<10) | (1<<12));
/* 循环点亮 */
while (1)
{
tmp = ~val;
tmp &= 7;
*pGPFDAT &= ~(7<<4);
*pGPFDAT |= (tmp<<4);
delay(100000);
val++;
if (val == 8)
val =0;
}
return 0;
}
2、编写start.S(同上)