一步一步点亮Led

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, =0xE0200244
10     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
11
12 flag:                            // 这两行写了一个死循环。因为裸机程序是直接在CPU上运行的,CPU会
13     b flag                        // 逐行运行裸机程序直到CPU断电关机。如果我们的程序所有的代码都
14                                 // 执行完了CPU就会跑飞(跑飞以后是未定义的,所以千万不能让CPU
15                                 // 跑飞),不让CPU跑飞的办法就是在我们整个程序执行完后添加死循环

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, =0x28
13     ldr r1, =GPJ0DAT
14     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
15
16     b .                            // .代表当前这一句指令的地址,这个就是高大上的死循环

上述代码改进:

(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,即0x28
13     ldr r0, =((1<<3) | (0<<4) | (1<<5))    // 清清楚楚的看到哪个灭,哪个是亮
14     ldr r1, =GPJ0DAT
15     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
16
17     b .                            // .代表当前这一句指令的地址,这个就是高大上的死循环

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, =GPJ0DAT
17     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
18     // 然后延时
19     bl delay                    // 使用bl进行函数调用
20
21     // 第2步:点亮LED2,其他熄灭
22     ldr r0, =~(1<<4)
23     ldr r1, =GPJ0DAT
24     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
25     // 然后延时
26     bl delay                    // 使用bl进行函数调用
27
28     // 第3步:点亮LED3,其他熄灭
29     ldr r0, =~(1<<5)
30     ldr r1, =GPJ0DAT
31     str r0, [r1]                // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
32     // 然后延时
33     bl delay                    // 使用bl进行函数调用
34
35     b flash
36
37
38 // 延时函数:函数名:delay
39 delay:
40     ldr r2, =9000000
41     ldr r3, =0x0
42 delay_loop:
43     sub r2, r2, #1                //r2 = r2 -1
44     cmp r2, r3                    // cmp会影响Z标志位,如果r2等于r3则Z=1,下一句中eq就会成立
45     bne delay_loop
46     mov pc, lr                    // 函数调用返回

关键知识点:

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

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

(3)在延时函数中

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

bne delay_loop

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

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

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

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

时间: 2024-10-05 08:24:02

一步一步点亮Led的相关文章

STM32F407第一步之点亮LED

STM32F407第一步之点亮LED. 要点亮LED,首先了解一下F4的GPIO模块.首先看一下STM32F4数据手册,GPIO模块的内部结构图 看上去有点复杂,不要怕,慢慢理解就可以了.对外引脚那里二极管就是保护的作用.通过上.下拉对应的开关配置,控制引脚默认状态的电压,开启上拉的时候引脚电压为高电平,开启下拉的时候引脚电压为低电平,这样可以消除引脚不定状态的影响.但是这个不应该用来作为外部的上拉或下拉用,如按键的拉电阻不能用这个内部来作用,如果用可能会引起按键不稳定. GPIO 具有了“推挽

【转】朱兆祺带你一步一步学习嵌入式(连载)

原文网址:http://bbs.elecfans.com/jishu_357014_2_1.html#comment_top  从最初涉及嵌入式Linux开始到现在,深深的知道嵌入式的每一步学习都是举步维艰.从去年11月份开始,我就着手整理各种学习资料,希望推动嵌入式学习的前进贡献自己微不足道的一份力量.从去年到现在,将C语言的学习经验整理成<攻破C语言笔试与机试陷阱及难点>(现在仍在更新),这份资料已经在电子发烧友论坛的单片机论坛连载(http://bbs.elecfans.com/jish

Android 从硬件到应用:一步一步向上爬 6 -- 编写APP测试框架层硬件服务(完)

创建Android Application工程:使用Eclipse的Android插件ADT创建Android工程,工程名称为Gpio,创建完成后将工程目录拷贝到packages/apps/文件夹下,并删除工程目录下的gen文件夹,不删除的话会造成类重复的错误. src/com/android/gpio/Gpio.java: package com.android.gpio; import com.android.gpio.R; import android.app.Activity; impo

驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED

这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 不能再扯了,涉及到linux的驱动开发知识面灰常广,再扯文章就会变得灰常长.首先还是回到led驱动的本身上,自从linux被移植到arm上后,做驱动开发的硬件知识要求有所降低,很多都回归到了软件上,这是系统编程的一大特点,当然 ,也不排除有很多

Android 从硬件到应用:一步一步向上爬 1 -- 从零编写底层硬件驱动程序

硬件平台:TI AM335X Starter Kit 开发源码:TI-Android-ICS-4.0.3-DevKit-EVM-SK-3.0.1.bin 主机系统:Ubuntu 10.04 这次写<Android 从硬件到应用>是想尝试从底层的最简单的GPIO硬件驱动开始,一步一步的向上走,经过硬件抽象层HAL.JNI方法等,最终编写出APP,达到硬件调用的目的,期间会增加一些Android下C程序测试底层驱动的细节.既然是从零编写驱动,那就要脱离源码包里已有的一些api函数,从硬件电路开始.

27.点亮led的操作

Led可以作为我调试程序的工具:在嵌入式系统软件,例如Bootloader和kernel,在开发初期,由于串口等硬件尚未被初始化,因此调试手段相当有限,这时候可以采用Led来作为调试手段. OK6410有关led的原理图: 从上图知道,要让led发光二极管,就是从右到左导通,右边是高电平,所以左边给低电平,二极管就会导通,发光了. 知道原理后,看看OK6410的核心板原理图,查看NLED1-4应该接到核心板的哪些引脚:led的部分截图: 我们从上面的原理图知道,led1-4对应的是GPM0-3.

嵌入式linux驱动开发之点亮led未遂(驱动编程思想之初体验)

有了上两篇文章的基础,我们就可以开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 另外实践很重要,一年多以前就知道了arm,那时整天用单片机的思维去yy着arm,直到前段时间弄来一块arm板,烧上linux系统后才知道,坑呀!根本不是那回事,所以实践是学习计算机类最重要的基本素质,如果整天看书,那基本上

Raspberry PI 系列 —— 裸机点亮LED灯

背景 最近刚买了Raspberry PI B+,配置运行了官方提供的Raspbian系统,折腾了一周Linux系统,感觉没啥意思,于是就试着想了解底层的启动流程,通过几天的研究,发现最底层部分的启动是由官方提供的bootcore.bin和start.elf文件来执行(应该是对硬件设备的初始化,如MMU等),之后由下一部分kernel.img的_start接管.为了真正验证此流程,于是想利用GPIO控制LED灯,几经折腾终于成功点亮LED,现记录于此. 外设地址编码 要想控制GPIO管脚就必须知道

使用寄存器点亮LED——编程实战

stm32的编程和stc89c51还是存在着很多思想上的不同的,在51单片机中,我们点亮LED灯,只用给对应IO高低电平就可以了,而stm32中,就一个简单的GPIO,我们也需要配置好几个寄存器,而且,就算配置好GPIO寄存器,我们还必须有一步不能缺少的操作,那就是开启对应GPIO的时钟.在stm32的编程中,开启对应时钟是必不可少的一个操作,而且,开启时钟的操作必须在配置相应寄存器之前,以GPIO为例,如果我们先配置GPIO的寄存器,不开启时钟或者先配置GPIO寄存器,最后再开启时钟,都不能正