博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一步一步点亮Led
阅读量:4324 次
发布时间:2019-06-06

本文共 4782 字,大约阅读时间需要 15 分钟。

1.了解物理特性

点亮LED的关键在于电压差

2.查阅原理图了解板载LED的硬件接法

方法:可以利用PDF文档的搜索功能(搜索LED即可,在底板搜索)

可知:有4颗正极接3.3V,负极分别接SoC上面的引脚(即引脚低电平亮),另外一个开机常亮。

3个SoC引脚是知道的,另外在核心板上查看pwmtout1可知引脚为GPD0_1,如下图

GPD0表示端口号,后面的1是引脚号

3.查阅数据手册

当我们想要编程操控GPIO来操作LED时,需要通读一下数据手册关于GPIO的部分

我们要操作的硬件为LED, 通过GPIO间接控制,实际要操作的设备是GPIO。

3.1、GPJ0相关的寄存器如下

其中,最主要的寄存器有:GPJ0_DAT, GPJ0CON

3.2、以下为GPJ0CON寄存器:

GPJ0这个端口的第一个引脚GPJ0_0对应寄存器GPJ0_CON的bit0~bit3, 点亮LED时应该将这个引脚配置成output模式。

3.3、GPJ0DAT寄存器介绍

GPJ0DAT[7:0]后面的7:0表示GPJ0对应的0~7引脚,后面的BIT[7:0]表示GPJ0DAT寄存器的bit0~bit7,从这里可以知道,
GPJ0端口的每一个引脚分别对应GPJODAT寄存器的每一个bit位。
 
3.4、总结
根据以上,我们就知道如何点亮LED
(1)操控GPJ0CON寄存器,选中为output模式。
(2)操控GPJ0DAT寄存器,选择相应位为低电平。
 
4.一步一步点亮le
4.1、点亮led灯
1 _start: 2     // 第一步:把0x11111111写入0xE0200240(GPJ0CON)位置 3     ldr r0, =0x11111111            // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 4     ldr r1, =0xE0200240            // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 5     str r0, [r1]                // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去 6  7     // 第二步:把0x0写入0xE0200244(GPJ0DAT)位置 8     ldr r0, =0x0 9     ldr r1, =0xE020024410     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮11 12 flag:                            // 这两行写了一个死循环。因为裸机程序是直接在CPU上运行的,CPU会13     b flag                        // 逐行运行裸机程序直到CPU断电关机。如果我们的程序所有的代码都14                                 // 执行完了CPU就会跑飞(跑飞以后是未定义的,所以千万不能让CPU15                                 // 跑飞),不让CPU跑飞的办法就是在我们整个程序执行完后添加死循环
View Code

4.2、改进代码1

1 #define GPJ0CON    0xE0200240 2 #define GPJ0DAT    0xE0200244 3  4 .global _start                    // 把_start链接属性改为外部,这样其他文件就可以看见_start了 5 _start: 6     // 第一步:把所有引脚都设置为输出模式,代码不变 7     ldr r0, =0x11111111            // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 8     ldr r1, =GPJ0CON            // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 9     str r0, [r1]                // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去10 11     // 第二步:把中间LED(GPJ0_4)的输出设置为0,其余两颗设置为1,剩下的其他位不管12     ldr r0, =0x2813     ldr r1, =GPJ0DAT14     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮15 16     b .                            // .代表当前这一句指令的地址,这个就是高大上的死循环
View Code

上述代码改进:

(1)用宏定义来替换地址的数字

(2)用b .来替换以前的死循环

(3)加上.global _start(将_start的链接属性改为外部链接)

改变:代码把4.1中点亮的led改为点亮中间的led。

4.3、改进代码2

在4.2中的缺陷:需要人为的计算0x28这个特定值,而且可读性不好。

解决方案:在写代码时用位运算让编译器帮我们计算特定值。
1 #define GPJ0CON    0xE0200240 2 #define GPJ0DAT    0xE0200244 3  4 .global _start                    // 把_start链接属性改为外部,这样其他文件就可以看见_start了 5 _start: 6     // 第一步:把所有引脚都设置为输出模式,代码不变 7     ldr r0, =0x11111111            // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 8     ldr r1, =GPJ0CON            // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 9     str r0, [r1]                // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去10 11     // 第二步:把中间LED(GPJ0_4)的输出设置为0,其余两颗设置为1,剩下的其他位不管12     //ldr r0, =((1<<3) | (1<<5))    // 等效于0b00101000,即0x2813     ldr r0, =((1<<3) | (0<<4) | (1<<5))    // 清清楚楚的看到哪个灭,哪个是亮14     ldr r1, =GPJ0DAT15     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮16 17     b .                            // .代表当前这一句指令的地址,这个就是高大上的死循环
View Code

4.4、改进代码3

加上延时函数和一些功能

1 #define GPJ0CON    0xE0200240 2 #define GPJ0DAT    0xE0200244 3  4 .global _start                    // 把_start链接属性改为外部,这样其他文件就可以看见_start了 5 _start: 6     // 第一步:把所有引脚都设置为输出模式,代码不变 7     ldr r0, =0x11111111            // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 8     ldr r1, =GPJ0CON            // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 9     str r0, [r1]                // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去10 11     // 要实现流水灯,只要在主循环中实现1圈的流水显示效果即可12 flash:13     // 第1步:点亮LED1,其他熄灭14     //ldr r0, =((0<<3) | (1<<4) | (1<<5))    // 清清楚楚的看到哪个灭,哪个是亮15     ldr r0, =~(1<<3)16     ldr r1, =GPJ0DAT17     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮18     // 然后延时19     bl delay                    // 使用bl进行函数调用20     21     // 第2步:点亮LED2,其他熄灭    22     ldr r0, =~(1<<4)23     ldr r1, =GPJ0DAT24     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮25     // 然后延时26     bl delay                    // 使用bl进行函数调用27     28     // 第3步:点亮LED3,其他熄灭    29     ldr r0, =~(1<<5)30     ldr r1, =GPJ0DAT31     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮32     // 然后延时33     bl delay                    // 使用bl进行函数调用34     35     b flash36 37 38 // 延时函数:函数名:delay39 delay:40     ldr r2, =900000041     ldr r3, =0x042 delay_loop:    43     sub r2, r2, #1                //r2 = r2 -144     cmp r2, r3                    // cmp会影响Z标志位,如果r2等于r3则Z=1,下一句中eq就会成立45     bne delay_loop46     mov pc, lr                    // 函数调用返回
View Code

关键知识点:

(1)B常用于不返回的跳转,比如跳到某个标号处,BL则用于子程序跳转(要返回,返回地地存于LR)

(2)在子函数中一般用mov pc, lr 这句指令来用于调用返回

(3)在延时函数中 

cmp r2, r3     // cmp会影响Z标志位,如果r2等于r3则Z=1,下一句中eq就会成立

bne delay_loop

ne为条件后缀,成立则执行这条指令

 

/********************************************************

 * 以上知识来自于朱老师物联网大讲堂

 *******************************************************/

 

转载于:https://www.cnblogs.com/zou27/p/5022460.html

你可能感兴趣的文章
iOS 打包
查看>>
.NET Core中的数据保护组件
查看>>
华为云软件开发云:容器DevOps,原来如此简单!
查看>>
MyEclipse 快捷键(转载)
查看>>
03链栈_LinkStack--(栈与队列)
查看>>
会滚段
查看>>
MANIFEST.MF的用途(转载)
查看>>
react高阶组件
查看>>
Android 高手进阶,自己定义圆形进度条
查看>>
Objective-C路成魔【2-Objective-C 规划】
查看>>
Java之旅(三)--- JSTL和EL表情
查看>>
正则匹配
查看>>
单利模式
查看>>
病毒表-相信对大家都有帮助-病毒词典
查看>>
ios 8 联系人ABPeoplePickerNavigationController
查看>>
列表、字典、append
查看>>
关于JAVA IO流的学习
查看>>
C#使用Json.Net遍历Json
查看>>
软工个人项目之词频统计
查看>>
Alpha 冲刺 (7/10)
查看>>