tiny4412开发板GPIO试验

2020-03-25来源: eefocus关键字:tiny4412  开发板  GPIO试验

GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平、或者通过它们读入引脚的状态——是高电平还是低电平。


三星Exynos4412,它有304个 GPIO,分为GPA0、GPA1、GPB、GPC0、GPC1等共37组。可以通过设置寄存器来确定某个引脚用于输入、输出还是其它特殊功能。比如可以设置GPC0、GPC1作为一般的输入引脚、输出引脚,或者用于AC97、SPDIF、I2C、SPI口。


GPIO的操作是所有硬件操作的基础,由此扩展开来可以了解所有硬件的操作,这是底层开发人员必须掌握的。


Exynos4412芯片的GPIO寄存器:


既然一个引脚可以用于输入、输出或其它特殊功能,那么一定有寄存器用来选择这些功能;对于输入,一定可以通过读取某个寄存器来确定引脚的电平是高还是低;对于输出,一定可以通过写入某个寄存器来让这个引脚输出高电平或低电平;对于其它特殊功能,则有另外的寄存器来控制它——这些特殊功能现在先不关注。


如上推测,对于这几组GPIO引脚,它们的寄存器是相似的:GPXXCON用于选择引脚功能,GPXXDAT用于读/写引脚数据;另外,GPXXPUD用于确定是否使用内部上拉/下拉电阻。


GPXXCON寄存器:


从寄存器的名字即可看出,它用于"配置"(Configure)——选择引脚的功能。该寄存器中,使用4位来配置1个引脚。比如下图1:

图1. GPIO配置寄存器


当GPA0CON的bit[31:28]值为0b0000时,引脚GPA0被设置为输入引脚;

当GPA0CON的bit[31:28]值为0b0001时,引脚GPA0被设置为输出引脚;

当GPA0CON的bit[31:28]值为0b0010时,引脚GPA0被设置为特殊功能UART引脚;

当GPA0CON的bit[31:28]值为0b0011时,引脚GPA0被设置为特殊功能I2C引脚;

当GPA0CON的bit[31:28]值为0b1111时,引脚GPA0被设置为中断引脚。

GPXXDAT寄存器:


用于读/写引脚:当引脚被设为输入时,读此寄存器可知相应引脚的电平状态是高还是低;当引脚被设为输出时,写此寄存器相应位可令此引脚输出高电平或低电平。


GPXXPUD寄存器:


使用2位来控制1个引脚:值为0b00时,相应引脚无内部上拉/下拉电阻;值为0b01时,使用内部下拉电阻;值为0b11时,使用内部上拉电阻;0b10为保留值。


所谓上拉电阻、下拉电阻,如图2所示:

图2. 上拉电阻和下拉电阻


上拉电阻、下拉电阻的作用在于,当GPIO引脚处于第三态(既不是输出高电平,也不是输出低电平,而是呈高阻态,即相当于没接芯片)时,它的电平状态由上拉电阻、下阻电阻确定。


怎样使用软件来访问硬件:


单引脚的操作无外乎三种:输出高低电平、检测引脚状态、中断。对某个引脚的操作一般通过读写寄存器来完成。


比如对于图3的电路,可以设置GPM4CON寄存器将GPM4_0、GPM4_1、GPM4_2和GPM4_3设为输出功能,然后写GPM4DAT寄存器的相应位使得这4个引脚输出高电平或低电平:输出低电平时,相应的LED点亮;输出高电平时,相应的LED熄灭。


还可以设置GPX3CON寄存器将GPX3_2、GPX3_3、GPX3_4、GPX3_5设为输入功能,然后通过读出GPX3DAT寄存器并判断bit2、bit3、bit4、bit5是0还是1来确定按键是否被按下:按键被按下时,相应引脚电平为低,相应位为0;否则为1。


那么,怎么访问这些寄存器呢?通过软件,读写它们的地址。比如,Exynos4412的GPM4CON、GPM4DAT寄存器地址分别是0x110002E0、0x110002E4,可以通过如下的指令让GPM4_0输出低电平,点亮LED1:


#define GPM4CON (*(volatile unsigned long *)0x110002E0)

#define GPM4DAT (*(volatile unsigned long *)0x110002E4)

#define GPM40_OUT (1<<0)

#define GPM40_MSK (0xf<<0)

GPM4CON &= ~GPM40_MSK; //GPM4_0引脚对应的4位清零(因为我们不知道它原来的值是多少,清零最可靠)

GPM4CON |= GPM40_OUT; //GPM4_0引脚设为输出

GPM4DAT &= ~(1<<0); //GPM4_0输出低电平

图3. LED与按键连线图


以某种协议的接口访问硬件:


比如UART、I2C、SPI等接口,我们只需要根据协议要求做好相关设置,然后把数据填入某个寄存器,这类接口部件就会把数据按某种格式发送出去。


如图4所示,以UART为例:设置好UART的波特率等格式后,把要发送的数据写入UART的寄存器,UART控制器就会把数据逐位发送出去。

图4. 协议类接口示例UART


GPIO操作实例:LED和按键:


从这节开始,将涉及在单板上运行程序了,下面用几个例子由简到繁地介绍。LED和按键与处理器的电路连接如图3所示。


本小节有3个实例,通过读写GPIO寄存器来驱动LED、获得按键状态。先使用汇编程序编写一个简单的点亮LED的程序,然后使用C语言实现了更复杂的功能。


示例1:使用汇编代码点亮一个LED


只是简单地点亮发光二极管LED1。本实例的目的是让读者对开发流程有个基本概念。


主要有三个文件,首先,是led.S文件,里面全是汇编语言来完成的。已经做了详细的注释,不再讲解。


.text //表示下面的代码是text段

.global _start //定义个全局标号

_start:

//设置GPM4_0为输出引脚

ldr r0, =0x110002E0 //将0x110002E0数字保存的R0寄存器中

ldr r1, [r0] //将R0中保存的0x110002E0地址中的数据取出来,保存到R1寄存器

bic r1, r1, #0xF //将R1寄存器中的数据低四位清零

orr r1, r1, #0x01 //将R1寄存器中的数据bit0置1

str r1, [r0] //将R1寄存器中的数据保存到R0寄存器中的数据表示的地址中

//设置GPM4_0输出低电平

ldr r0, =0x110002E4 //将0x110002E4数字保存的R0寄存器中

ldr r1, [r0] //将R0中保存的0x110002E4地址中的数据取出来,保存到R1寄存器

bic r1, r1, #0x1 //将R1寄存器中的数据bit0清零

str r1, [r0] //将R1寄存器中的数据保存到R0寄存器中的数据表示的地址中

halt: //死循环

b halt

值得注意的是:要修改寄存器的某些位时,最好先把原值读出并修改这些位,再把值写回去。寄存器里每位都有它的作用,这样做可以避免影响到其他位。


下面的是链接脚本文件leds.lds中的内容;很简单,如果有不明白的可以网上查询。


SECTIONS {

. = 0x02023400; //链接地址,也就是说,希望程序运行在此地址

.text : { *(.text) } //代码段

.rodata ALIGN(4) : {*(.rodata)} //只读数据段

.data ALIGN(4) : { *(.data) } //数据段

.bss ALIGN(4) : { *(.bss) *(COMMON) } //bss段

}

最后,介绍Makefile文件的内容:


led.bin : led.S

arm-linux-gcc -c -o led.o led.S #预处理、编译、汇编,不链接

arm-linux-ld -Tleds.lds -g led.o -o led.elf #链接

arm-linux-objcopy -O binary -S led.elf led.bin #将ELF格式文件转换为BIN文件

arm-linux-objdump -D led.elf > led.dis #反汇编

clean:

rm *.o *.elf *.dis *.bin

make指令比较第1行中文件led.bin和文件led.S的时间,如果led.S的时间比led.bin的时间新(led_on.bin未生成时,此条件默认成立),则执行第2~5行的命令重新生成led.bin及其他文件。也可以不用指令make,而直接一条一条地执行2~5行的指令——但是这样效率比较低。


第2行的指令是编译,第3行是连接,第4行是把ELF格式的可执行文件led.elf转换成二进制格式文件led.bin,第5行是得到它的反汇编文件(目前没用到该文件)。


执行"make clean"时强制执行第7行的删除命令。


注意:Makefile文件中相应的命令行前一定要有一个制表符(TAB)。


如果对Makefile中每句是详细意思,请参考交叉编译工具链的使用。


现在,来介绍将led.bin文件烧写到SD卡中,然后插入到开发板的SD卡槽中,设置启动模式,然后开启电源运行。


把SD卡接入读卡器,让VMware软件位于窗口最前面,然后把读卡器接入电脑。


点击VMware菜单"VM"->"Removable Devices",找到新出现的USB存储设备,点击"Connect"。


注意:如果菜单里没有新的设备出现,原因是VMware的USB服务未启动。可用以下方式启动:打开"控制面板"->"系统和安全"->"管理工具"->"服务",找到"VMware USB Arbitration Service",双击启动它。然后重启VMware软件。


然后执行以下命令,一般最后一个"不带数字的"设备节点就是SD卡的设备名:


$ ls /dev/sd*

输出示例:

brw-rw---- 1 root disk 8,  0 Nov 18 09:22 /dev/sda

brw-rw---- 1 root disk 8,  1 Nov 18 09:22 /dev/sda1

brw-rw---- 1 root disk 8,  2 Nov 18 09:22 /dev/sda2

brw-rw---- 1 root disk 8,  5 Nov 18 09:22 /dev/sda5

brw-rw---- 1 root disk 8, 16 Nov 18 17:42 /dev/sdb

brw-rw---- 1 root disk 8, 17 Nov 18 17:42 /dev/sdb1

在上面的输出示例中,/dev/sdb就是该卡的设备名。


首先,将led.bin文件拷贝到sd_fusing.sh文件的目录下,也就是同一个目录。执行如下命令将led.bin写入SD卡:


$ sudo sd_fusing.sh /dev/sdb led.bin

注意看该命令的输出信息,若有"source file image is fused successfully."即表示烧写成功。否则请根据错误信息解决。


注意:sd_fusing.sh的作用后面会详细讲解。


把SD卡取下接到开发板上,开发重新上电即可看到LED1灯被点亮了。


汇编语言可读性太差,这次用C语言来实现了同样的功能,而以后的实验也尽量用C语言实现。


示例2:使用C语言代码点亮一个LED


C语言程序执行的第一条指令,并不在main函数中。生成一个C程序的可执行文件时,编译器通常会在我们的代码中加上几个被称为启动文件的代码——crt1.o、crti.o、crtend.o、crtn.o等,它们是标准库文件。这些代码设

[1] [2]
关键字:tiny4412  开发板  GPIO试验 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic492495.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:arm的PWM模块脉宽调制及超声波系统设计
下一篇:ARM指令adr和ldr的区别

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

tiny4412开发板时钟操作示例
在上一节总我们介绍了《Exynos4412芯片的时钟管理单元》,有了上一节的基础知识我们就可以写程序操作CPU的时钟了。通过操作led来感受时钟速率的变化。本文总共有三个示例,第一个是写一个LED循环点亮的程序;第二个是将iROM中设置的时钟禁止掉,观察LED变化速率;第三个就是设置CPU的时钟速率为1.4GHz,观察LED的变化速率。第一个程序很简单,有两个文件start.S和main.c。其中,start.Sz文件中设置栈,然后跳转到C函数中执行。在main.c中设置LED的亮灭。首先,来看start.S内容:.text.global _start_start: ldr sp, =0x02027400 //设置栈 bl
发表于 2020-03-26
tiny4412开发板icache操作程序
首先,来介绍关于cache的概念。cache的作用:基于程序访问的局限性,在主存和CPU通用寄存器之间设置了一个高速的、容量相对较小的存储器,把正在执行的指令地址附近的一部分指令或数据从主存调入这个存储器,供CPU在一段时间内使用,这对提高程序的运行速度有很大的作用。这个介于主存和CPU之间的高速小容量存储器称作高速缓存存储器(Cache)。启用Cache后,CPU读取数据时,如果Cache中有这个数据的复本则直接返回,否则从主存中读入数据,并存入Cache中,下次再使用(读/写)这个数据时,可以直接使用Cache中的复本。启用Cache后,CPU写数据时有写穿式和回写式两种方式。(1)写穿式(Write Through)任一从CP
发表于 2020-03-25
tiny4412开发板的串口介绍与操作
UART原理说明:通用异步收发器简称UART,即"Universal Asynchronous Receiver Transmitter",它用来传输串行数据:发送数据时,CPU将并行数据写入UART,UART按照一定的格式在一根电线上串行发出;接收数据时,UART检测另一根电线上的信号,将串行收集放在缓冲区中,CPU即可读取UART获得这些数据。UART之间以全双工方式传输数据,最精简的连线方法只有三根电线:TxD用于发送数据,RxD用于接收数据,Gnd用于给双方提供参考电平,连线如图1所示:图1. UART连线图UART使用标准的TTL/CMOS逻辑电平(0~5V、0~3.3V、0~2.5V或0~1.8V四种
发表于 2020-03-25
tiny4412开发板的串口介绍与操作
tiny4412裸机程序——代码重定位
。链接地址是程序的链接地址,即程序运行时应该位于的运行地址。编译程序时,可以在链接脚本中指定程序的链接地址。对于tiny4412而言,前面我们已经说过:启动时BL1只会从sd等启动设备中拷贝14K的代码到iRAM中,那么当我们的程序超过14K怎么办?那就需要我们在前14K的代码中将整个程序完完整整地拷贝到LPDDR等其他更大存储空间,然后再跳转到LPDDR中继续运行我们的代码,这个拷贝然后跳转的过程就叫重定位。本章中讲解学习如何重定位,但是并不会涉如何使用到LPDDR,而是简单地将代码从iRAM的0x02023400处拷贝到iRAM的0x02026400处,然后跳转到0x02026400处继续运行我们的代码。程序文件介绍
发表于 2020-03-25
tiny4412裸机程序之位置无关码
在上篇文章中,将代码的.text、.data、.rodata段重定位到了0x02026400位置处去执行点亮LED的操作。但是,在链接脚本里指定的链接地址是0x02026400,那么为什么在重定位之前的代码能够在0x02023400地址处可以开始执行?就是因为前面使用的是位置无关码。写介绍介个概念:链接地址:链接脚本里指定的,理论上程序运行时所处的地址。在编译时,编译器会根据链接地址来翻译位置有关码。加载地址(运行地址):程序运行时,实际所处的地址。位置无关码,位置有关码,是相对于一条指令的正常目的来说的。比如ldr r0, =xx,它的正常目的是取得标号处的地址,对于这个目的,它是位置有关码,运行的地址不对就获取不到正确的标号地址
发表于 2020-03-25
tiny4412裸机程序之位置无关码
ARM与FPGA沟通的桥梁—米尔PYNQ开发板
Python库和FPGA硬件库进行功能的开发,快速高效。 为适应市场需求发展,米尔近期基于热销的Z-turn Board 推出了PYNQ版本,全面支持PYNQ开发。 Z-Turn Board 是米尔科技Zynq7000平台的力作,设计特征鲜明,即是核心板又是开发板,易开发且易嵌入应用产品,性价比高,已大量应用于工控,IOT,视觉等领域。此次Z-Turn Board升级PYNQ版本后,将为人工智能,ADAS,机器视觉等领域的开发者带来福音。  Z-TURN PYNQ开发例程: Python人脸识别    
发表于 2020-03-25
ARM与FPGA沟通的桥梁—米尔PYNQ开发板
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved