JZ2440 第5章 GPIO接口

2024-03-06 21:58
文章标签 接口 gpio jz2440

本文主要是介绍JZ2440 第5章 GPIO接口,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本章目标:

掌握嵌入式开发的步骤:编程、编译、烧写程序、运行
通过GPIO的操作了解软件如何控制硬件

5.1 GPIO硬件介绍

S3C2440A有130个多功能输入/输出口引脚,分为A~J共9组:GPA、GPB、...、GPH、GPJ。

5.1.1 管脚相关的寄存器

对于这几组GPIO引脚,它们的寄存器是相似的:
① GPxCON:用于选择管脚功能;
x为A、B、...、H、J 
PORTA与PORTB~PORTJ在功能选择上有所不同,GPACON中每一位对应一根引 脚(共23根引脚)。
     当某位被设为0时,对应的引脚为输出引脚;
     当某位被设为1时,对应的引脚为地址线或用于地址 控制,此时GPADAT无用。
一般而言,GAPCON通常被设为全1,以方便访问外部存储器件。本章不使用PORTA。
PORTB~PORTJ在寄存器操作方面完全相同。GPxCON中每两位控制一根引脚。
00:表示输入、01:表示输出、10:表示特殊功能、11:表示保留不用。
② GPxDATA:用于读写管脚数据;
x为A、B、...、H、J
当引脚被设为输入时,读此寄存器可知对应引脚的电平状态是高还是低;
当引脚被设为输出时,写此寄存器对应位,可令此引脚输出高电平或低电平。
③ GPxUP    :用于确定是否使用内部上拉电阻。
x为B、...、H、J,没有GPAUP寄存器。
某位为1时,相应引脚无内部上拉电阻;某位为0时,相应引脚使用内部上拉电阻

5.1.2 怎么使用软件来访问硬件

1.访问单个引脚
操作种类:输出高/低电平、检测引脚状态、中断。
如下图所示,JZ2440原理图中LED和按键的连接。

可以设置GPFCON寄存器将GPF4、GPF5、GPF6设为输出功能,然后写GPFDAT寄存器的
相应位使得这3个引脚输出高电平或低电平。
还可以设置GPFCON寄存器将GPF0、GPF2、GPG3、GPG11设置为输入功能,然后通过读
出GPFDAT/GPGDAT寄存器并判断相应位电平状态来确定各个按键是否按下。
访问寄存器的方法:通过软件,读写它们的地址。
比如,S3C2440的GPBCON、GPBDAT寄存器地址是0x5600 0010、0x56000014,可以通
过如下指令让GPF4输出低电平,点亮LED(D10)。
#define GPFCON (*(volatile unsigned long *) 0x56000050)
#define GPFDAT (*(volatile unsigned long *) 0x56000054)
#define GPF4_out    (1 << 4*2)
GPFCON = GPF4_out;      //GPF4引脚设为输出
GPFDAT &= ~(1 << 4);    //GPF4输出低电平

5.2 GPIO操作实例:LED和按键

5.2.1 硬件设计

     如上图所示。

5.2.2 程序设计及代码详解

本小节有3个实例,通过读写GPIO寄存器来驱动LED、获取按键状态。先使用汇编程序编写
一个简单的点亮LED的程序,然后使用C语言实现了更复杂的功能。
    1.实例1:使用汇编代码点亮1个LED
源程序为/work/hardware/led_on/led_on.S。它只有7条指令,简单地点亮LED。
实例分为4个步骤:编译源程序、生成可执行程序、烧写程序、运行程序。
先看看源程序:led_on.S: 
1
.text
2
.global _start
3
_start:
4
    LDR R0,=0x56000050     @R0设为GPFCON寄存器
5
    MOV R1, #0x00000100    @0b 01 0000 0000
6
    STR R1,[R0]            @设置GPF4为输出口,位[9:8] = 01
7
    LDR R0,=0x56000054     @R0设置GPFDAT寄存器
8
    MOV R1, #0x0000000     @此值改为0x00000010(0001 0000)可以让LED全熄灭
9
    STR R1,[R0]            @GPF4输出0,点亮LED
10
MAIN_LOOP:
11
    B MAIN_LOOP
Makefile内容如下:
1
led_on.bin:led_on.S                                        @make指令比较led_on.bin和led_on.S的时间,决定是否执行下面的命令
2
    arm-linux-gcc -g -c -o led_on.o led_on.S               @编译
3
    arm-linux-ld -Ttext 0x0000 -g led_on.o -o led_on_elf   @链接
4
    arm-linux-objcopy -O binary -S led_on_elf led_on.bin   @把ELF格式的可执行文件led_on_elf转换成二进制格式文件led_on.bin
5
clean:
6
    rm -f led_on.bin led_on_elf *.o
注意:Makefile文件中相应的命令行前一定要有一个制表符
    2.实例2:使用C语言代码点亮1个LED
源程序为/work/hardware/led_on_c目录下。
C语言执行的第一条指令并不在main函数中。生成一个C程序的可执行文件时,编译器通常会在我们
的代码中加上几个被称为启动文件的代码——crtl.o、crti.o、crtend.o、crtn.o等,它们是标准库文件。
这些代码设置C程序的堆栈等,然后调用main函数。它们依赖于操作系统,在裸板上这些代码无法执行,
需要自己写一个。
这段代码很简单,只有6条指令。自己编写的crt0.S文件内容如下:
1
@************************************
2
@File:crt0.S
3
@功能:通过它转入C程序
4
@************************************
5
.text
6
.global _start
7
_start:
8
    ldr r0, =0x56000010    @WATCHDOG寄存器地址
9
    mov r1, #0x0
10
    str r1, [r0]           @写入0,禁止WATCHDOG
11
    
12
    ldr sp, =1024*4        @设置堆栈,注意不能大于4k,因为现在可用内存只有4kB
13
                           @NAND Flash中的代码在复位后会移到内部ram(只有4kB)
14
    bl main
15
halt_loop:
16
    b  halt_loop
上面设置堆栈指针后,就可以调用C函数main了。C函数执行前,必须设置栈。
现在可以很容易写出控制LED的程序了。main函数在led_on_c.c文件中,代码如下:
1
#define GPFCON (*(volatile unsigned long *) 0x56000050)
2
#define GPFDAT (*(volatile unsigned long *) 0x56000054)
3
#define GPF4_out    (1 << 4*2)
4
5
int main()
6
{
7
    GPFCON = GPF4_out;    //GPF4引脚设为输出
8
    GPFDAT &= ~(1 << 4);    //GPF4输出低电平
9
    
10
    return 0;
11
}
最后来看看Makefile:
1
led_on_c.bin:crt0.S led_on_c.c
2
    arm-linux-gcc -g -c -o crt0.o crt0.S
3
    arm-linux-gcc -g -c -o led_on_c.o led_on_c.c
4
    arm-linux-ld -Ttext 0x0000000 -g crt0.o led_on_c.o -o led_on_c_elf
5
    arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin
6
    arm-linux-objdump -D -m arm led_on_c_elf > led_on_c.dis
7
clean:
8
    rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o
操作步骤如下:
(1)进入led_on_c目录后,执行如下命令可生成可执行文件led_on_c.bin;
$make
(2)使用dnw把led_on_c.bin写入NAND Flash;
(3)把开发板拨为NAND启动,给开发板上电,可看见LED被点亮。
2.实例3:使用按键来控制LED 
目录/work/hardware/key_led中的程序功能为:当K1~K3中某个按键被按下时,点亮D10~D12
(v2版电路板只有3个灯)中相应的LED。
key_led.c代码如下:
1
#define GPFCON      (*(volatile unsigned long *)0x56000050)
2
#define GPFDAT      (*(volatile unsigned long *)0x56000054)
3
4
#define GPGCON      (*(volatile unsigned long *)0x56000060)
5
#define GPGDAT      (*(volatile unsigned long *)0x56000064)
6
7
/*
8
 * LED1,LED2,LED4对应GPF4、GPF5、GPF6
9
 */
10
#define GPF4_out    (1<<(4*2))
11
#define GPF5_out    (1<<(5*2))
12
#define GPF6_out    (1<<(6*2))
13
14
#define GPF4_msk    (3<<(4*2))
15
#define GPF5_msk    (3<<(5*2))
16
#define GPF6_msk    (3<<(6*2))
17
18
/*
19
 * S2,S3,S4对应GPF0、GPF2、GPG3
20
 */
21
#define GPF0_in     (0<<(0*2))
22
#define GPF2_in     (0<<(2*2))
23
#define GPG3_in     (0<<(3*2))
24
25
#define GPF0_msk    (3<<(0*2))
26
#define GPF2_msk    (3<<(2*2))
27
#define GPG3_msk    (3<<(3*2))
28
29
int main()
30
{
31
        unsigned long dwDat;
32
        // LED1,LED2,LED4对应的3根引脚设为输出
33
        GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
34
        GPFCON |= GPF4_out | GPF5_out | GPF6_out;
35
        
36
        // S2,S3对应的2根引脚设为输入
37
        GPFCON &= ~(GPF0_msk | GPF2_msk);
38
        GPFCON |= GPF0_in | GPF2_in;
39
40
        // S4对应的引脚设为输入
41
        GPGCON &= ~GPG3_msk;
42
        GPGCON |= GPG3_in;
43
44
        while(1){
45
            //若Kn为0(表示按下),则令LEDn为0(表示点亮)
46
            dwDat = GPFDAT;             // 读取GPF管脚电平状态
47
        
48
            if (dwDat & (1<<0))        // S2没有按下
49
                GPFDAT |= (1<<4);       // LED1熄灭
50
            else    
51
                GPFDAT &= ~(1<<4);      // LED1点亮
52
                
53
            if (dwDat & (1<<2))         // S3没有按下
54
                GPFDAT |= (1<<5);       // LED2熄灭
55
            else    
56
                GPFDAT &= ~(1<<5);      // LED2点亮
57
    
58
            dwDat = GPGDAT;             // 读取GPG管脚电平状态
59
            
60
            if (dwDat & (1<<3))         // S4没有按下
61
                GPFDAT |= (1<<6);       // LED3熄灭
62
            else    
63
                GPFDAT &= ~(1<<6);      // LED3点亮
64
    }
65
66
    return 0;
67
}
操作步骤如下:
(1)进入key_led目录后,执行make命令,即可生成可执行文件key_led.bin;
(2)使用dnw把key_led.bin写入NAND Flash;
(3)把开发板拨为NAND启动,给开发板上电,可看见LED被点亮。

5.2.3 实例测试

在烧写程序是要烧到NAND Flash中去的原因:2440中有被称为“Steppingstone”的
4KB内部RAM,当选择从NAND Flash 启动CPU时,CPU会通过内部的硬件将NAND 
Flash开始的4KB字节数据复制到这4KB的内部RAM中(此时,内部RAM的起始 地址为0),
然后跳到地址0开始执行。
NOR Flash虽然可以像内存一样进行读操作,但不能像内存一样进行写操作,所以从
NOR Flash启动时,一般先在代码的 开始部分使用汇编指令初始化外接的内存器件(外存),
然后将代码复制到外存中,最后跳到外存中继续执行。
对于小程序,一般将它烧入NAND Flash中,借助CPU内部RAM直接运行。
附:代码:
链接: https://pan.baidu.com/s/1kV24a9L 密码: tfab

这篇关于JZ2440 第5章 GPIO接口的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/781491

相关文章

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Java中的Closeable接口及常见问题

《Java中的Closeable接口及常见问题》Closeable是Java中的一个标记接口,用于表示可以被关闭的对象,它定义了一个标准的方法来释放对象占用的系统资源,下面给大家介绍Java中的Clo... 目录1. Closeable接口概述2. 主要用途3. 实现类4. 使用方法5. 实现自定义Clos

java对接第三方接口的三种实现方式

《java对接第三方接口的三种实现方式》:本文主要介绍java对接第三方接口的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录HttpURLConnection调用方法CloseableHttpClient调用RestTemplate调用总结在日常工作

Java 的 Condition 接口与等待通知机制详解

《Java的Condition接口与等待通知机制详解》在Java并发编程里,实现线程间的协作与同步是极为关键的任务,本文将深入探究Condition接口及其背后的等待通知机制,感兴趣的朋友一起看... 目录一、引言二、Condition 接口概述2.1 基本概念2.2 与 Object 类等待通知方法的区别

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

Java对接Dify API接口的完整流程

《Java对接DifyAPI接口的完整流程》Dify是一款AI应用开发平台,提供多种自然语言处理能力,通过调用Dify开放API,开发者可以快速集成智能对话、文本生成等功能到自己的Java应用中,本... 目录Java对接Dify API接口完整指南一、Dify API简介二、准备工作三、基础对接实现1.

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接