GPIO学习笔记

Gpio实验

一 用汇编点亮一个led

1 看原理图 GPK4=0 ,led亮GPK4=1,led灭

2 怎么让GPK4输出高低电平 (看芯片手册,操作寄存器实现)

配置功能:输入/输出/其他

设置其输出高/低电平

3 查看用户手册

GPK4[19:16]

0000 = Input 0001 = Output

0010 = Host I/F DATA[4] 0011 = HSI TX READY

0100 = Reserved 0101 = DATA_CF[4]

0110 = Reserved 0111 = Reserved

GPKDAT 在第4位写写0就对应GPK4

GPK[15:0] [15:0]

When the port is configured as input port, the correspondingbit is the pin state.

When the port is configured as output port, the pin state isthe same as the

corresponding bit. When the port is configured as functionalpin, the undefined

value will be read.

Register Address R/W Description ResetValue

GPKCON0 0x7F008800 R/WPortK Configuration Register 00x22222222

GPKCON1 0x7F008804 R/W PortK Configuration Register 10x22222222

GPKDAT 0x7F008808R/W Port K Data Register Undefined

GPKPUD 0x7F00880C R/W Port K Pull-up/downRegister 0x55555555

协处理器

查看arm11芯片手册:

Cpu 访问的地址:内存0-0x6fff ffff

外设0x7000 0000-0x7fff ffff

c15 0 c2 4 Peripheral Port Memory

Remap

R/W, B, X R/W 0x00000000 page3-174

CRn Op1 CRm Op2 Register oroperation S type

NS

type

Reset

value

Page

b10011 = 256MB

For example:

MRC p15, 0, <Rd>, c15, c2,4 ; Read Peripheral Port Memory Remap Register

MCR p15, 0, <Rd>, c15, c2,4 ; Write Peripheral Port Memory Remap Register

查看6410用户手册

Register AddressR/W Description Reset Value

WTCON 0x7E004000 R/W Watchdogtimer control register 0x8021

示例代码如下:

start.S文件

.globl _start

_start:

/*硬件的相关设置:把外设的基地址告诉cpu*/

ldr r0,=0x70000000 @伪汇编指令

orrr0,r0,#0x13 @按位逻辑或操作

mcrp15,0,r0,c15,c2,4 @b10011 = 256MB ,arm寄存器到协处理寄存器的数据传输

/*关闭看门狗*/

/*往往WTCON(0x7E004000)写0*/

ldrr0,=0x7E004000 @字数据读取指令

mov r1,#0@数据传送指令

strr1,[r0] @将寄存器中数据写入到内存单元

/*设置GPKCON GPK4作为输出引脚*/

ldr r1,=0x7F008800 @gpkcon的地址

movr0,#0x10000000 @设为输出引角

strr0,[r1] @将寄存器数据写入到内存单元

/*设置GPKDAT让GPK4输出0*/

ldr r1,=0x7F008808 @gpkdat的地址

mov r0,#0

str r0,[r1]

halt:

b halt

Makefile文件

1 Windows下的makefile文件

all : led.bin

led.bin:start.o

arm-elf-ld -Ttext 0 -o led.elf start.o

arm-elf-objcopy -O binary led.elf led.bin

arm-elf-objdump -D led.elf > led.dis

start.o :start.S

arm-elf-gcc -o start.o start.S -c

clean:

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

2 Linux下的makefile文件

led.bin: start.o

@-Ttext 0 表示代码段的地址为0

@nandFlash前4k数据会放到sram中,cpu从0地址开始读取

arm-linux-ld-Ttext 0 -o led.elf start.o

@输出二进制文件

arm-linux-objcopy -O binary led.elf led.bin

arm-linux-objdump -D led.elf > led.dis

start.o : start.S

arm-linux-gcc-o start.o start.S -c

clean:

rm *.o led.elfled.bin led.dis

编译 make

将编译好的文件烧写到开发板的两种方法:

1 led_on.bin烧写到nandflash,如同烧写linux类似,led_on.bin放到images目录下

修改friendlyARM.ini

Action=install

OS=UserBin

UserBin-Image=led_on.bin

2 使用openjtag烧写

a进入应用目录D:\c_porjects\6410\1th_led,执行make命令编译程序

b 开发板烧写的是linux系统,

c打开openODC程序指定开发板型号,设定工作目录,然后点击connect

此时可能有很多警告提示,先设为SD卡启动(不需插SD卡),再点connect,正常后直接

带电拔到NAND启动

d 点击tellnet,执行以下命令

:如果点击telnet没有反应,可以在windows命令窗口执行如下命令:

Telnet 127.0.0.1 4444

二 点亮四个led灯,示例代码如下:

start.S文件

.globl _start

_start:

/*硬件相关设置*/

ldrr0,=0x70000000

orr r0,r0,#0x13

mcr p15,0,r0,c15,c2,4

/*关闭看门狗*/

ldrr0,=0x7e004000

mov r1,#0

str r1,[r0]

/*设置GPKCON GPK4/5/6/7作为输出*/

ldrr1,=0x7F008800

ldrr0,=0x11110000

str r0,[r1]

/*设置GPKDAT让GPK4输出0*/

ldrr1,=0x7F008808

mov r0,#0

loop:

str r0,[r1]

add r0,r0,#1

cmp r0,#16

moveq r0,#0

bl delay

b loop

delay:

movr2,#0x10000000

delay_loop:

sub r2,r2,#1

cmp r2,#0

bne delay_loop

mov pc,lr

halt:

b halt

Makefile文件同上

三 用c语言来实现点灯

1 硬件相关设置

2 调用c函数

示例代码如下:

void delay(){

volatile inti=0x10000;

while (i--);

}

int main(){

int i=0;

//volatile作用是不让编译器不要优化变量

volatileunsigned long *gpkcon = (volatile unsigned long *)0x7F008800;

volatileunsigned long *gpkdat = (volatile unsigned long *)0x7F008808;

*gpkcon=0x11110000;

while(1){

*gpkdat=i;

i++;

if(i==16)

i=0;

delay();

}

return 0;

}

启动文件,示例代码如下:

.globl _start

_start:

/*硬件相关设置*/

ldrr0,=0x70000000

orrr0,r0,#0x13

mcr p15,0,r0,c15,c2,4

/*关看门狗*/

ldrr0,=0x7E004000

mov r1,#0

str r1,[r0]

/*设置栈*/

ldr sp,=8*1024

bl main @跳转到main处执行,并将返回地址保存到LR寄存器(R14link @register链接寄存器)中

Halt:

Bhalt

Makefile文件内容如下:

led.bin: start.o led.o

arm-linux-ld-Ttext 0 -o led.elf start.o led.o

arm-linux-objcopy -O binary led.elf led.bin

arm-linux-objdump -D led.elf > led.dis

start.o : start.S

arm-linux-gcc-o start.o start.S -c

led.o:led.c

arm-linux-gcc-o led.o led.c -c

clean:

rm *.o led.elfled.bin led.dis

编译 make

烧写到开发板,方法同上

查看反汇编程序 led.dis,文件内容如下:

led.elf: fileformat elf32-littlearm

Disassembly of section .text:

00000000 <_start>:

//关看门狗

0: e3a00207 mov r0, #1879048192 ;0x70000000

4: e3800013 orr r0, r0, #19 ;0x13

8: ee0f0f92 mcr 15, 0, r0, cr15, cr2, {4}

c: e59f0010 ldr r0, [pc, #16] ;24 <halt+0x4>

10: e3a01000 mov r1, #0 ;0x0

14: e5801000 str r1, [r0]

//设置栈

18: e3a0da02 mov sp, #8192 ;0x2000

1c: eb00000e bl 5c <main>

00000020 <halt>:

20: eafffffe b 20 <halt>

24: 7e004000 .word 0x7e004000

00000028 <delay>:

28: e1a0c00d mov ip, sp

//将四个寄存器保存到栈中

2c: e92dd800 push {fp, ip, lr, pc}

30: e24cb004 sub fp, ip, #4 ;0x4

34: e24dd004 sub sp, sp, #4 ;0x4

38: e3a03801 mov r3, #65536 ;0x10000

3c: e50b3010 str r3, [fp, #-16]

40: e51b3010 ldr r3, [fp, #-16]

44: e2433001 sub r3, r3, #1 ;0x1

48: e50b3010 str r3, [fp, #-16]

4c: e51b3010 ldr r3, [fp, #-16]

50: e3730001 cmn r3, #1 ;0x1

54: 1afffff9 bne 40 <delay+0x18>

//从栈中恢复寄存器

58: e89da808 ldm sp, {r3, fp, sp, pc}

0000005c <main>:

5c: e1a0c00d mov ip, sp

60: e92dd800 push {fp, ip, lr, pc}

64: e24cb004 sub fp, ip, #4 ;0x4

68: e24dd00c sub sp, sp, #12 ;0xc

6c: e3a03000 mov r3, #0 ;0x0

70: e50b3018 str r3, [fp, #-24]

74: e3a0347f mov r3, #2130706432 ;0x7f000000

78: e2833b22 add r3, r3, #34816 ;0x8800

7c: e50b3014 str r3, [fp, #-20]

80: e3a0347f mov r3, #2130706432 ;0x7f000000

84: e2833b22 add r3, r3, #34816 ;0x8800

88: e2833008 add r3, r3, #8 ;0x8

8c: e50b3010 str r3, [fp, #-16]

90: e51b2014 ldr r2, [fp, #-20]

94: e3a03411 mov r3, #285212672 ;0x11000000

98: e2833811 add r3, r3, #1114112 ; 0x110000

9c: e5823000 str r3, [r2]

a0: e51b2018 ldr r2, [fp, #-24]

a4: e51b3010 ldr r3, [fp, #-16]

a8: e5832000 str r2, [r3]

ac: e51b3018 ldr r3, [fp, #-24]

b0: e2833001 add r3, r3, #1 ;0x1

b4: e50b3018 str r3, [fp, #-24]

b8: e51b3018 ldr r3, [fp, #-24]

bc: e3530010 cmp r3, #16 ;0x10

c0: 1a000001 bne cc <main+0x70>

c4: e3a03000 mov r3, #0 ;0x0

c8: e50b3018 str r3, [fp, #-24]

cc: ebffffd5 bl 28 <delay>

d0: eafffff2 b a0 <main+0x44>

Disassembly of section .comment:

00000000 <.comment>:

0: 43434700 movtmi r4, #14080 ;0x3700

4: 4728203a undefined

8: 2029554e eorcs r5, r9, lr, asr #10

c: 2e322e34 mrccs 14, 1, r2, cr2, cr4, {1}

10: Address 0x00000010 is out of bounds.

Disassembly of section .ARM.attributes:

00000000 <_stack-0x80000>:

0: 00000f41 andeq r0, r0, r1, asr #30

4: 61656100 cmnvs r5, r0, lsl #2

8: 01006962 tsteq r0, r2, ror #18

c: 00000005 andeq r0, r0, r5

四 轮流点亮led灯,启动文件和makefile文件与上面相同

示例代码如下:

/*初始化led寄存器指针*/

#define gpkcon (*(volatile unsigned long *)0x7F008800)

#define gpkdat (*(volatile unsigned long *)0x7F008808)

#define gpk4_out (1<<(4*4))

#define gpk5_out (1<<(5*4))

#define gpk6_out (1<<(6*4))

#define gpk7_out (1<<(7*4))

void delay(volatile unsigned long dly)

{

for(;dly>0;dly--);

}

int main(void)

{

int i = 0;

/*初始化gpk4,5,6,7 */

//*gpkcon =0x11110000;

gpkcon=gpk4_out|gpk5_out|gpk6_out|gpk7_out;

while (1)

{

delay(30000);

gpkdat = (~(i<<4));

if (++i == 16)

{

i= 0;

}

}

return 0;

}

五 按键按制led灯

查看原理图

Eint0 Eint1 Eint2 Eint3对应按键k1 k2 k3 k4

对应的寄存器为 GPN0-3

查看芯片手册

配置key为输入,led为输出

读key值,根据值来设置led引脚

Led.c示例代码如下,启动文件同以上两个程序

/*初始化led寄存器指针*/

#define gpkcon (*(volatile unsigned long *)0x7F008800)

#define gpkdat (*(volatile unsigned long *)0x7F008808)

#define gpk4_out (1<<(4*4))

#define gpk5_out (1<<(5*4))

#define gpk6_out (1<<(6*4))

#define gpk7_out (1<<(7*4))

#define gpk4_msk (15<<(4*4))

#define gpk5_msk (15<<(5*4))

#define gpk6_msk (15<<(6*4))

#define gpk7_msk (15<<(7*4))

/*初始化key寄存器指针*/

#define gpncon (*(volatile unsigned long *)0x7F008830)

#define gpndat (*(volatile unsigned long *)0x7F008834)

#define gpn0_in (0<<(0*2))

#define gpn1_in (0<<(1*2))

#define gpn2_in (0<<(2*2))

#define gpn3_in (0<<(3*2))

#define gpn0_msk (3<<(0*2))

#define gpn1_msk (3<<(1*2))

#define gpn2_msk (3<<(2*2))

#define gpn3_msk (3<<(3*2))

int main(void)

{

unsigned longdwDat;

/*初始化gpk4,5,6,7 四根引脚设为输出*/

//*gpkcon =0x11110000;

gpkcon &= ~(gpk4_msk | gpk5_msk | gpk6_msk| gpk7_msk);

gpkcon |= gpk4_out | gpk5_out | gpk6_out |gpk7_out;

//gpkcon=gpk4_out|gpk5_out|gpk6_out|gpk7_out;

/*初始化keygpn 0,1,2,3 四根引脚设为输入*/

gpncon &=~(gpn0_msk | gpn1_msk | gpn2_msk | gpn3_msk);

gpncon |= gpn0_in | gpn1_in | gpn2_in |gpn3_in;

while (1)

{

//如果kn为0(表示按下),则令led为0(点亮)

//读取gpk管脚电平状态

dwDat=gpndat;

if(dwDat & (1<<0)){ //s1没有按下

gpkdat|= (1<<4); //led1灭

}else{

gpkdat&= ~(1<<4);//led1亮

}

if(dwDat & (1<<1)){ //s1没有按下

gpkdat|= (1<<5); //led2灭

}else{

gpkdat&= ~(1<<5);//led2亮

}

if(dwDat & (1<<2)){ //s1没有按下

gpkdat|= (1<<6); //led3灭

}else{

gpkdat&= ~(1<<6);//led3亮

}

if(dwDat & (1<<3)){ //s1没有按下

gpkdat|= (1<<7); //led4灭

}else{

gpkdat&= ~(1<<7);//led4亮

}

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值