第四章 LED程序
4.1 硬件知识_LED原理图
当我们学习C语言的时候,我们会写个Hello程序。
那当我们写ARM程序,也该有一个简单的程序引领我们入门,这个程序就是点亮LED。
我们怎样去点亮一个LED呢?
分为三步:
① 看原理图,确定控制LED的引脚;
② 看主芯片的芯片手册,确定如何设置控制这个引脚;
③ 写程序;
LED样子有很多种,像插脚的,贴片的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1bXLjEth-1642059895488)(https://cdn.jsdelivr.net/gh/DongshanPI/HomeSite-Photos@main/IMX6ULL-BareMetal/LED_Program_image001.jpg)]
它们长得完全不一样,因此我们在原理图中将它抽象出来。
点亮LED需要通电源,同时为了保护LED,加个电阻减小电流。
控制LED灯的亮灭,可以手动开关LED,但在电子系统中,不可能让人来控制开关,通过编程,利用芯片的引脚去控制开关。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9gfUgDAF-1642059895489)(https://cdn.jsdelivr.net/gh/DongshanPI/HomeSite-Photos@main/IMX6ULL-BareMetal/LED_Program_image002.jpg)]
LED的驱动方式,常见的有四种。
方式1:使用引脚输出3.3V点亮LED,输出0V熄灭LED。
方式2:使用引脚拉低到0V点亮LED,输出3.3V熄灭LED。
有的芯片为了省电等原因,其引脚驱动能力不足,这时可以使用三极管驱动。
方式3:使用引脚输出1.2V点亮LED,输出0V熄灭LED。
方式4:使用引脚输出0V点亮LED,输出1.2V熄灭LED。
由此,主芯片引脚输出高电平/低电平,即可改变LED状态,而无需关注GPIO引脚输出的是3.3V还是1.2V。
所以简称输出1或0:
逻辑1–>高电平
逻辑0–>低电平
4.2 普适的GPIO引脚操作方法
GPIO: General-purpose input/output,通用的输入输出口。
4.2.1 GPIO模块一般结构
a. 有多组GPIO,每组有多个GPIO
b. 使能:电源/时钟
c. 模式(Mode):引脚可用于GPIO或其他功能
d. 方向:引脚Mode设置为GPIO时,可以继续设置它是输出引脚,还是输入引脚
e. 数值:对于输出引脚,可以设置寄存器让它输出高、低电平
对于输入引脚,可以读取寄存器得到引脚的当前电平
4.2.2 GPIO寄存器操作
a. 芯片手册一般有相关章节,用来介绍:power/clock
可以设置对应寄存器使能某个GPIO模块(Module)
有些芯片的GPIO是没有使能开关的,即它总是使能的
b. 一个引脚可以用于GPIO、串口、USB或其他功能,
有对应的寄存器来选择引脚的功能
c. 对于已经设置为GPIO功能的引脚,有方向寄存器用来设置它的方向:输出、输入
d. 对于已经设置为GPIO功能的引脚,有数据寄存器用来写、读引脚电平状态
GPIO寄存器的2种操作方法:
原则:不能影响到其他位
- 直接读写:读出、修改对应位、写入
要设置bit n:
代码语言:javascript复制val = data_reg;
val = val | (1<<n);
data_reg = val;
要清除bit n:
代码语言:javascript复制val = data_reg;
val = val & ~(1<<n);
data_reg = val;
- set-and-clear protocol:
set_reg, clr_reg, data_reg 三个寄存器对应的是同一个物理寄存器,
要设置bit n:set_reg = (1<<n);
要清除bit n:clr_reg = (1<<n);
4.2.3 GPIO的其他功能:防抖动、中断、唤醒
后续章节再介绍
4.3 IMX6ULL的GPIO操作方法
CCM: Clock Controller Module (时钟控制模块)
IOMUXC : IOMUX Controller,IO复用控制器
GPIO: General-purpose input/output,通用的输入输出口
4.3.1 IMX6ULL的GPIO模块结构
参考资料:芯片手册《Chapter 26: General Purpose Input/Output (GPIO)》
有5组GPIO(GPIO1~GPIO5),每组引脚最多有32个,但是可能实际上并没有那么多。
GPIO1有32个引脚:GPIO1_IO0~GPIO1_IO31;
GPIO2有22个引脚:GPIO2_IO0~GPIO2_IO21;
GPIO3有29个引脚:GPIO3_IO0~GPIO3_IO28;
GPIO4有29个引脚:GPIO4_IO0~GPIO4_IO28;
GPIO5有12个引脚:GPIO5_IO0~GPIO5_IO11;
GPIO的控制涉及4大模块:CCM、IOMUXC、GPIO模块本身,框图如下:
4.3.2 CCM用于设置是否向GPIO模块提供时钟
参考资料:芯片手册《Chapter 18: Clock Controller Module (CCM)》
GPIOx要用CCM_CCGRy寄存器中的2位来决定该组GPIO是否使能。哪组GPIO用哪个CCM_CCGR寄存器来设置,请看上图红框部分。
CCM_CCGR寄存器中某2位的取值含义如下:
① 00:该GPIO模块全程被关闭
② 01:该GPIO模块在CPU run mode情况下是使能的;在WAIT或STOP模式下,关闭
③ 10:保留
④ 11:该GPIO模块全程使能
GPIO2时钟控制:
GPIO1、GPIO5时钟控制:
GPIO3时钟控制:
GPIO4时钟控制:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ardJzS9m-1642059895491)(https://cdn.jsdelivr.net/gh/DongshanPI/HomeSite-Photos@main/IMX6ULL-BareMetal/LED_Program_image009.jpg)]
4.3.3 IOMUXC:引脚的模式(Mode、功能)
参考资料:芯片手册《Chapter 32: IOMUX Controller (IOMUXC)》。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UIr01QaZ-1642059895492)(https://cdn.jsdelivr.net/gh/DongshanPI/HomeSite-Photos@main/IMX6ULL-BareMetal/LED_Program_image010.jpg)]
对于某个/某组引脚,IOMUXC中有2个寄存器用来设置它:
① 选择功能:
IOMUXC_SW_MUX_CTL_PAD_< PADNAME > :Mux pad xxx,选择某个pad的功能
IOMUXC_SW_MUX_CTL_GRP_< GROUP NAME >:Mux grp xxx,选择某组引脚的功能
某个引脚,或是某组预设的引脚,都有8个可选的模式(alternate (ALT) MUX_MODE)。
[外链图片转存中…(img-xhaAV8W6-1642059895492)]
比如:
[外链图片转存中…(img-gUCiYOLD-1642059895492)]
② 设置上下拉电阻等参数:
IOMUXC_SW_PAD_CTL_PAD_< PAD_NAME >:pad pad xxx,设置某个pad的参数
IOMUXC_SW_PAD_CTL_GRP_< GROUP NAME >:pad grp xxx,设置某组引脚的参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQ9GM7Oc-1642059895492)(https://cdn.jsdelivr.net/gh/DongshanPI/HomeSite-Photos@main/IMX6ULL-BareMetal/LED_Program_image013.jpg)]
比如:
4.3.4 GPIO模块内部
框图如下:
我们暂时只需要关心3个寄存器:
① GPIOx_GDIR:设置引脚方向,每位对应一个引脚,1-output,0-input
② GPIOx_GDIR:设置输出引脚的电平,每位对应一个引脚,1-高电平,0-低电平
③ GPIOx_PSR:读取引脚的电平,每位对应一个引脚,1-高电平,0-低电平