1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741
4)关注正点原子公众号,获取最新资料更新
在上一章使用C语言编写LED灯驱动的时候,每个寄存器的地址我们都需要写宏定义,使用起来非常的不方便。我们在学习STM32的时候,可以使用“GPIOB->ODR”这种方式来给GPIOB的寄存器ODR赋值,因为在STM32中同属于一个外设的所有寄存器地址基本是相邻的(有些会有保留寄存器)。因此我们可以借助C语言里面的结构体成员地址递增的特点来将某个外设的所有寄存器写入到一个结构体里面,然后定义一个结构体指针指向这个外设的寄存器基地址,这样我们就可以通过这个结构体指针来访问这个外设的所有寄存器。同理,I.MX6U也可以使用这种方法来定义外设寄存器,本章我们就模仿STM32里面的寄存器定义方式来编写I.MX6U的驱动,通过本章的学习也可以对STM32的寄存器定义方式有一个深入的认识。
11.1模仿STM32寄存器定义 11.1.1 STM32寄存器定义简介 为了开发方便,ST官方为STM32F103编写了一个叫做stm32f10x.h的文件,在这个文件里面定义了STM32F103所有外设寄存器,我们可以使用其定义的寄存器来进行开发,比如我们可以用如下代码来初始化一个GPIO:
GPIOE->CRL&=0XFF0FFFFF;
GPIOE->CRL|=0X00300000; //PE5推挽输出
GPIOE->ODR|=1GPIO1_IO03”来访问GPIO1_IO03的IO复用寄存器了。同样的,其他的外设寄存器都可以通过这三步来定义。 11.2 硬件原理分析 本章使用到的硬件资源和第八章一样,就是一个LED0。 11.3实验程序编写 本实验对应的例程路径为:开发板光盘-> 1、裸机例程->3_ledc_stm32。 创建VSCode工程,工作区名字为“ledc_stm32”,新建三个文件:start.S、main.c和imx6ul.h。其中start.S是汇编文件,start.S文件的内容和第十章的start.S一样,直接复制过来就可以。main.c 和imx6ul.h是C文件,完成以后如图11.3.1所示:
图11.3.1工程文件目录 文件imx6ul.h用来存放外设寄存器定义,在imx6ul.h中输入如下代码:
示例代码11.2.1 imx6ul.h文件代码
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : imx6ul.h
作者 : 左忠凯
版本 : V1.0
描述 : IMX6UL相关寄存器定义,参考STM32寄存器定义方法
其他 : 无
日志 : 初版V1.0 2019/1/3 左忠凯创建
**************************************************************/
/*
* 外设寄存器组的基地址
*/
1 #define CCM_BASE (0X020C4000)
2 #define CCM_ANALOG_BASE (0X020C8000)
3 #define IOMUX_SW_MUX_BASE (0X020E0014)
4 #define IOMUX_SW_PAD_BASE (0X020E0204)
5 #define GPIO1_BASE (0x0209C000)
6 #define GPIO2_BASE (0x020A0000)
7 #define GPIO3_BASE (0x020A4000)
8 #define GPIO4_BASE (0x020A8000)
9 #define GPIO5_BASE (0x020AC000)
10
11/*
12 * CCM寄存器结构体定义,分为CCM和CCM_ANALOG
13 */
14typedefstruct
15{
16volatileunsignedint CCR;
17volatileunsignedint CCDR;
18volatileunsignedint CSR;
……
46volatileunsignedint CCGR6;
47volatileunsignedint RESERVED_3[1];
48volatileunsignedint CMEOR;
49} CCM_Type;
50
51typedefstruct
52{
53volatileunsignedint PLL_ARM;
54volatileunsignedint PLL_ARM_SET;
55volatileunsignedint PLL_ARM_CLR;
56volatileunsignedint PLL_ARM_TOG;
……
110volatileunsignedint MISC2;
111volatileunsignedint MISC2_SET;
112volatileunsignedint MISC2_CLR;
113volatileunsignedint MISC2_TOG;
114} CCM_ANALOG_Type;
115
116/*
117 * IOMUX寄存器组
118 */
119typedefstruct
120{
121volatileunsignedint BOOT_MODE0;
122volatileunsignedint BOOT_MODE1;
123volatileunsignedint SNVS_TAMPER0;
……
241volatileunsignedint CSI_DATA04;
242volatileunsignedint CSI_DATA05;
243volatileunsignedint CSI_DATA06;
244volatileunsignedint CSI_DATA07;
245}IOMUX_SW_MUX_Type;
246
247typedefstruct
248{
249volatileunsignedint DRAM_ADDR00;
250volatileunsignedint DRAM_ADDR01;
……
419volatileunsignedint GRP_DDRPKE;
420volatileunsignedint GRP_DDRMODE;
421volatileunsignedint GRP_DDR_TYPE;
422}IOMUX_SW_PAD_Type;
423
424/*
425 * GPIO寄存器结构体
426 */
427typedefstruct
428{
429volatileunsignedint DR;
430volatileunsignedint GDIR;
431volatileunsignedint PSR;
432volatileunsignedint ICR1;
433volatileunsignedint ICR2;
434volatileunsignedint IMR;
435volatileunsignedint ISR;
436volatileunsignedint EDGE_SEL;
437}GPIO_Type;
438
439
440/*
441 * 外设指针
442 */
443 #define CCM ((CCM_Type *)CCM_BASE)
444 #define CCM_ANALOG ((CCM_ANALOG_Type *)CCM_ANALOG_BASE)
445 #define IOMUX_SW_MUX ((IOMUX_SW_MUX_Type *)IOMUX_SW_MUX_BASE)
446 #define IOMUX_SW_PAD ((IOMUX_SW_PAD_Type *)IOMUX_SW_PAD_BASE)
447 #define GPIO1 ((GPIO_Type *)GPIO1_BASE)
448 #define GPIO2 ((GPIO_Type *)GPIO2_BASE)
449 #define GPIO3 ((GPIO_Type *)GPIO3_BASE)
450 #define GPIO4 ((GPIO_Type *)GPIO4_BASE)
451 #define GPIO5 ((GPIO_Type *)GPIO5_BASE)
在编写寄存器组结构体的时候注意寄存器的地址是否连续,有些外设的寄存器地址可能不是连续的,会有一些保留地址,因此我们需要在结构体中留出这些保留的寄存器。比如CCM的CCGR6寄存器地址为0X020C4080,而寄存器CMEOR的地址为0X020C4088。按照地址顺序递增的原理,寄存器CMEOR的地址应该是0X020C4084,但是实际上CMEOR的地址是0X020C4088,相当于中间跳过了0X020C4088-0X020C4080=8个字节,如果寄存器地址连续的话应该只差4个字节(32位),但是现在差了8个字节,所以需要在寄存器CCGR6和CMEOR直接加入一个保留寄存器,这个就是“示例代码11.3.1”中第47行RESERVED_3[1]的来源。如果不添加保留为来占位的话就会导致寄存器地址错位!
main.c文件中输入如下所示内容:
示例代码11.3.2 main.c文件代码
1 #include "imx6ul.h"
2
3/*
4 * @description : 使能I.MX6U所有外设时钟
5 * @param : 无
6 * @return : 无
7 */
8void clk_enable(void)
9{
10 CCM->CCGR0 =0XFFFFFFFF;
11 CCM->CCGR1 =0XFFFFFFFF;
12 CCM->CCGR2 =0XFFFFFFFF;
13 CCM->CCGR3 =0XFFFFFFFF;
14 CCM->CCGR4 =0XFFFFFFFF;
15 CCM->CCGR5 =0XFFFFFFFF;
16 CCM->CCGR6 =0XFFFFFFFF;
17}
18
19/*
20 * @description : 初始化LED对应的GPIO
21 * @param : 无
22 * @return : 无
23 */
24void led_init(void)
25{
26/* 1、初始化IO复用 */
27 IOMUX_SW_MUX->GPIO1_IO03 =0X5;/* 复用为GPIO1_IO03 */
28
29
30/* 2、配置GPIO1_IO03的IO属性
31 *bit 16:0 HYS关闭
32 *bit [15:14]: 00 默认下拉
33 *bit [13]: 0 kepper功能
34 *bit [12]: 1 pull/keeper使能
35 *bit [11]: 0 关闭开路输出
36 *bit [7:6]: 10 速度100Mhz
37 *bit [5:3]: 110 R0/6驱动能力
38 *bit [0]: 0 低转换率
39 */
40 IOMUX_SW_PAD->GPIO1_IO03 =0X10B0;
41
42
43/* 3、初始化GPIO */
44 GPIO1->GDIR =0X0000008;/* GPIO1_IO03设置为输出 */
45
46/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
47 GPIO1->DR &=~(1
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?