首先我们需要明白的是:寄存器是操控硬件的API接口。我们如果想操控LED是通过GPIO来间接操控的,实质是操控SoC的GPIO的的寄存器,从而控制LED这个硬件工作。
1 分析硬件工作原理(物理特性)
LED本身有2个接线点,一个是LED的正极,一个是LED的负极。LED这个硬件的功能就是点亮或者不亮,物理上想要点亮一颗LED只需要给他的正负极上加正电压即可。
2 分析原理图
我们可以看到,4颗LED的接法是:正极接3.3V,负极接了SoC上的一个引脚(GPIO),具体详细接法是:
D22:GPJ0_3
D23:GPJ0_4
D24:GPJ0_5
D25:PWMTOUT1(GPD0_1)
要让LED亮起来必须要在led的正负极形成一个电压差。
以D22为例,由于与LED的正极(D22)已经与VDD_IO相连,说明我们只需要将LED的负极(GPJ0_3)设置为低电平,即可形成电压差,从而驱动LED点亮。【注意:LED负极多了一个470R的电阻,原因是当LED通电瞬间,瞬时电流会很大,这个电阻存在的意义就是让LED通电时的瞬时电流降低,从而达到保护LED的作用】
3 分析数据手册、找到相关的SFR (这里用到GPJ0CON和GPJ0DAT两个寄存器)
找到GPJ0对应的部分,因为我们需要点亮GPJ0_3~GPJ0_5,所以需要将GPJ0CON[3]、GPJ0CON[4]、GPJ0CON[5]设置为输出状态。由下表可知,也就是设置对应的bit位为:0001
还有一个问题就是要注意查看GPJ0CON这个寄存器的地址:0xE020_0240
对于GPJ0DAT, (GPJ0 data)。上面描述的解析是:当引脚配置为input/output模式时,寄存器的相应位和引脚的电平高低相对应。也就是当GPJ0DAT这个寄存器对应的bit等于1,意味着这个位是高电平;当GPJ0DAT这个寄存器对应的bit等于0,意味着这个位是低电平;
4 写代码设置寄存器得到想要的效果
/*说明:这小段程序来自朱老师物联网大讲堂*/
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
_start:
// 第一步:把所有引脚都设置为输出模式,代码不变
ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数
ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令
str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去
// 点亮LED1,其他熄灭
ldr r0, =((0<<3) | (1<<4) | (1<<5))
ldr r1, =GPJ0DAT
str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
程序解读:操控GPJ0CON寄存器:
ldr r0, =0x11111111 注意标红的三位1,这三个1是16进制的(0x1=0b0001),这样就已经将GPJ0CON[3]、GPJ0CON[4]、GPJ0CON[5]设置为输出状态。
程序解读:操控GPJ0DAT寄存器,点亮nLED1
ldr r0, =((0<<3) | (1<<4) | (1<<5))
意思是(0<<3),把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮。用下图来表述就是只要GPJ0DAT寄存器中GPJ0_3这一个bit对应的位置是0(低电平),即可点亮LED1。
【关于SFR 的补充】
SoC中有2类寄存器:通用寄存器和SFR
通用寄存器(ARM中有37个):是CPU的组成部分,CPU的很多活动都需要通用寄存器的支持和参与。
SFR(special function register,特殊功能寄存器):不在CPU中,而存在于CPU的外设中,我们通过访问外设的SFR来编程操控这个外设,这就是硬件编程控制的方法。
备注:这两个寄存器的说明资料来自朱老师物联网大讲堂