×
单片机 > 单片机程序设计 > 详情

基于S3C6410的ARM11学习(九) 点亮led

发布时间:2022-08-15 发布时间:
|

之前已经对S3C6410的核心初始化完成了,但是这个也只是完成了,但是程序到底对不对了,还需要验证。最简单的验证方法是什么了,就是点亮led。如果在核心初始化完成后,我们写程序去点亮了led,就说明初始化代码是没有问题。


下面就要来点亮led了。这个时候就和开发板的原理图有关系了。我用的是OK6410的开发板,打开对应原理图。

找到4个灯,是共阳接法的。所以要点亮对应的灯,就要使led的负端为低电平。在看看各个led负端端口对应的S3C6410的哪个IO。

从核心板的原理图可以看出,4个LED是接在GPM0-3这四个管脚上的。


有了这个信息,我们只要去控制这四个管脚输出不同的电平,就能实现led的亮灭了。


打开6410的手册。直接看GPIO这一章。

表中列出了所有的GPIO,总共分为17组,从A-Q。每一组有不同的管脚数。控制IO功能是通过GPxCON寄存器来控制的。控制IO管脚上数据是通过GPxDAT来控制的。我们这里就以GPM为例说明。

上图说明GPM的IO操作有3个寄存器。


先看第一个寄存器,GPMCON

GPM组共有6个IO管脚。所以这个寄存器中,分成了6组,每一组控制对应的IO的功能。这里,我们是要使GPM0-3为输出。所以低16位就要设置为16’b0001_0001_0001_0001。

这样,就将GPM0-3设置为输出了。

在看第二个寄存器,GPMDAT。

手册也说得比较清楚,当IO为输入的时候,记录的是IO脚上的电平。当作为输出的时候,记录的是IO上输出的电平。所以当我们要让GPM0-3都输出低电平的话,那么这个寄存器的后4位就要写入4’b0000。

第三个寄存器,GPMPUD

这个是设置IO管脚上下拉电阻的。


以上三个寄存器就是IO的基本寄存器了。每一组的IO都有上诉的3个寄存器。


下面我们就要来写程序了。这里,我写的是流水灯,初始,4个灯为亮灭亮灭,每隔一段时间,灯的状态就翻转一次,


流程:

1、设置对应IO为输出

2、设置IO输出值

3、每隔一段时间对IO输出值取反


下面就是对应的程序了,将流水灯写成一个函数,在reset中调用。

1、先定义GPMCOM和GPMDAT地址。

2、将r0的值设置为0x1111。这个值之前分析过,将GPM0-3设置为输出的值

3、将GPMCON地址装载到r1寄存器

4、将r0的值写入到r1寄存器代表的寄存器中,这样就配置GPM0-3为输出

5、将r0的值设置为0x5。这个用来配置GPM0-3输出的值

6、将GPMDAT地址装载到r1寄存器

7、将r0的值写入到r1寄存器代表的寄存器中,这样就配置GPM0-3输出值为4’b0101

8、将lr的值保存在r4寄存器中。因为这个时候lr寄存器保存的是调用light_led函数处的下一条指令。在这个函数中,后面又会调用其他函数,会破坏lr的值,这样就返回不到调用light_led的位置了。所以这样要先备份一下lr的值。


9、定义a1标号,用于后面的跳转,实现无限循环

10、调用delay函数

11、将r0值取反,r0的值就是IO输出的值

12、将r0的值写入到输出寄存器去,就改变了IO的输出值

13、在跳转到a1标号,实现无限循环

14、函数返回

15、定义delay函数,将r2的值设置为600000,这个值随意设,但是不能设置太小,不然没有灯翻转效果。太大也不行,难得等

16、定义delay_1标签,用于在delay函数中跳转

17、将r2的值减1

18、比较r2和10的大小

19、 如果r2大于10的话,跳转到delay_1处,说明延时还没有结束,继续执行延时,也就是继续减r2寄存器。否则往下执行

20、 delay函数返回


用汇编来写,要麻烦一些,要定义一些标签,用来跳转。


这样,就完成了点亮流水灯的代码了。下面在reset中调用该函数

这样,就完成了整个程序的设计了。将该程序,编译链接下载到开发板中,运行,就会看到led在不停的闪烁了。


对比STM32,操作可就要麻烦一些了。

首先看下系统结构,看看GPIO是挂在什么总线上的。因为之前说过,STM32是有外设门控时钟的。要使用某外设,就必须要打开对应外设的时钟。这是和ARM11很不一样的一点。

GPIO是挂在APB2总线上的,所以我们打开时钟的时候要去打开APB2上对应GPIO时钟。图中可以知道,GPIO是分为7组的。从A-G。


到GPIO章节去看。

功能描述就说明了,对应每个GPIO端口,有哪些寄存器来控制。STM32是有7个寄存器来进行控制。


STM32的GPIO比S3C6410的GPIO要复杂多了,因为GPIO可以配置为8种模式。

下面是GPIO的基本结构

8种模式中,对推挽式输出和推挽式复用输出说明一下。这两个的输出结构都是一样的,使用CMOS的结构。但是不一样的是不同功能所使用模式不一样。推挽式输出是IO端口作为普通输出时的模式,而推挽式复用输出是IO作为特殊功能时作为输出的模式,比如有的IO有串口输出功能,当使用串口输出功能的时候,就要把IO的模式设置为推挽式复用输出。


输入的话,就没有什么好说的,从名字也可以看的出来。注意的是模拟输入,当使用芯片的内部AD时,IO是要设置为模拟输入的。


下面就要看看各个寄存器

1、GPIOx_CRL寄存器

这个是设置GPIO组的低8位的IO功能。每4位对应一个IO。高两位是配置IO的模式。低两个是配置IO作为输入还是输出,以及作为输出的最大速度是多少。


2、GPIOx_CRH寄存器

和GPIOx_CRL寄存器一样的功能,只不过是配置的高8位IO的功能。


3、GPIOx_IDR寄存器

从描述中得到,这个寄存器保存的IO的状态,其实就是IO上的电平。而且这个寄存器只能读。当IO作为输入的时候,我们来读这个寄存器就知道IO上的电平了。


4、GPIOx_ODR寄存器

这个寄存器就是设置IO的输出了。低16位,每一位对应一个IO。当IO作为输出,可以往这个寄存器写值,就实现了IO输出了。


5、GPIOx_BSRR寄存器

这个寄存器,就是对输出值影响的。可以对输出清零,也可以对输出置1.


6、GPIOx_BRR寄存器

看描述就知道功能了


7、GPIOx_LCKR寄存器

STM32对IO加了一个锁的功能,就是可以将IO给锁起来,这样就不能对IO进行改变了。这个功能就是由这个寄存器来设置的。要锁某个IO的话,先将对应IO位的值设置为1,锁定端口配置,然后往16位写入特定的序列,就实现了IO的锁的功能了。在系统复位前,这锁功能一直有。


知道了对应相关的寄存器了,就知道怎么使用STM32的管脚来控制流水灯了。


流程

1、打开对应IO的时钟使能

2、配置CRL或CRH,使IO作为输出,模式就推挽式输出,最大速度是50M。

3、配置ODR寄存器,使寄存器输出我们想要的值


以配置GPIOA0-3为例说明。


首先打开GPIOA时钟。这个在RCC_APB2ENR寄存器中

第2位控制GPIOA的时钟使能。那么就把这一位置1就好了。但是怎么操作这个寄存器了。当然,我们可以向S3C6410一样,使用指针,去指向这个寄存器的地址,然后再对这个地址操作。但是,官方库已经给我们定义好了这些寄存器了,我们只要直接使用就好了。


在官方给的库(V3.5)中,有两个文件夹,一个inc,一个src

inc里面就是一些头文件,src里面就是具体的函数实现。库将每个外设都封装好了一个头文件和一个c文件。里面就定义了各个外设的寄存器,以及一些库函数,使用这些库函数就可以直接操作这些外设寄存器,而不用和底层的寄存器打交道了。因为STM32的寄存器实在是太多了,每次操作都查表的话,那可是很累的。而且直接操作寄存器的话,代码不直观,不知道配置到底是什么作用的。


这里,我们先用寄存器来进行操作。然后再用库函数来进行操作。在对比

寄存器版本:

寄存器版本的话就和inc和src下面的库文件没有多大关系了。直接打开stm32f10x.h,这个是在官方提供的库CMSIS目录下。

这个头文件定义了stm32f10x系列的所有寄存器对应的地址,相当于51单片机的reg51.h。

这里定义RCC的结构体,里面包含了RCC的各个寄存器。我们这里要用的就是其中的APB2ENR寄存器。因为这个寄存器里面有对GPIOA的时钟有效设置。在STM32中,对寄存器定义都是放在对应功能的结构体中去了,因为这些寄存器是严格4字节对齐的,所以只要放在结构体中,然后定义结构体的首地址,那么后面每个寄存器的地址也就都知道了。上面就定义RCC的结构体。这个是管理时钟和复位功能的。


在去找RCC的地址

这样,我们就可以直接访问了。


使用RCC->APB2ENR就可以访问RCC下的APB2ENR寄存器了。之前说,要把这个寄存器的第二位置为1.所以

RCC->APB2ENR = 0x4;

配置GPIO

同样,也是先去找GPIO结构体。

里面就有上面这个结构体。在STM32中,对外设的寄存器定义都是放在结构体中去了,因为这些寄存器是严格4字节对齐的,所以只要放在结构体中,然后定义结构体的首地址可以知道所有寄存器地址。上面就定义GPIO的结构体。


然后再去找GPIOA,因为我们要对这一组GPIO操作。


我从里面把关键的弄出来了

先定义了外设的基地址,然后再定义APB2的基地址,因为GPIO都是挂在APB2总线上的。然后不同的GPIO组的地址就是APB2基地址加上偏移地址就得了。然后再将这个GPIO组的基地址强制转化为GPIO结构体的首地址。这样不就知道了GPIO组的每

[1] [2]
S3C6410ARM11点亮led

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项