S3C2440裸机------GPIO

目录

 

1.S3C2440GPIO简单介绍

2.JZ2440原理图

3.控制GPF管脚

4.汇编语言点亮GPF4

5.C语言点亮GPF4

6.循环点亮LED

7.按键控制LED

1.S3C2440GPIO简单介绍

GPIO即General-purpose input/output ,这些管脚除了可以用作输入输出外,还可以配置成一些其他的功能,例如I2C,UART等,其实就是管脚复用的思想。

所有的这些管脚主要通过下面的寄存器进行控制,

2.JZ2440原理图

        

从上面的原理图截图中我们可以看到:

1.我们的nLED_1,nLED_2,nLED_4是连接到3.3V电源上的,所以我们的管脚需要输出低电平,LED灯才会亮。

2.我们的nLED_1,nLED_2,nLED_4是连接到s3c2440的GPF4,GPF5,GPF6上面的。

另外,在原理图中还有如下知识点。

3.控制GPF管脚

我们需要控制GPF引脚控制LED灯,下面的问题就是我们怎么让GPF4输出0,

a.首先把该管脚配置为输出引脚,

b.设置它的状态。

然后我们在s3c2440的芯片手册中找到GPF引脚相关的寄存器。

我们通过设置GPFCON寄存器的[9:8]为01将GPF4配置为输出功能。把0000,0001,0000,0000=0x0100写到地址0x56000050上面。

设置PGFDAT[4]为0,则该管脚会输出低电平,此时LED点亮。把0000000=0x00写到地址0x56000054上面。

设置PGFDAT[4]为1,则该管脚会输出高电平,此时LED熄灭。把00010000=0x10写到地址0x56000054上面。

另外有一点需要注意,就是我们的CPU里面有R0,R1,.....R15,这些寄存器我们可以直接访问,而像GPFCON,GPFDAT这些寄存器我们访问的时候要通过地址去访问。

下面开始写程序点亮LED。

4.汇编语言点亮GPF4

/**************************************
*点亮LED, GPF4.
**************************************/

.text
.global _start

_start:

//把0x100写到地址0x56000050上,配置gpf4为输出引脚,

    ldr r1, =0x56000050
	ldr r0,=0x100
	str r0,[r1]


//把0x00写到地址0x56000054上,设置gpf4输出低电平, 
    ldr r1, =0x56000054
	ldr r0,=0x00
	str r0,[r1]
	
	//死循环
halt:
    b halt

然后可以用下面的三行命令进行编译

arm-linux-gcc -c -o led_on.o led_on.S
arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
arm-linux-objcopy -O binary -S  led_on.elf led_on.bin

用命令行敲容易出错,我们把上面的命令写到一个makefile里面:

all:
	arm-linux-gcc -c -o led_on.o led_on.S
	arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
	arm-linux-objcopy -O binary -S  led_on.elf led_on.bin

clean:
	rm *.bin  *.o  *.elf

编译产生bin文件之后,打开windows的命令行,首先进入bin文件所在的目录,然后执行oflash led_on.bin,下载到开发板中即可执行。

5.C语言点亮GPF4

我们编写如下C语言代码控制LED,

int main()
{
    unsigned int *pGPFCON = 0x56000050;
	unsigned int *pGPFDAT = 0x56000054;

	/*配置GPF4为输出引脚*/
	*pGPFCON = 0x100;

	/*配置GPF4输出0*/
	*pGPFDAT = 0;
}

C语言代码写完之后,存在两个问题

1.我们写出了main函数,那么谁来调用这个main函数,

2.main函数中的变量保存在内存中,这个内存地址是多少。

答:我们需要写一段汇编代码,给main函数设置内存,调用main函数。

我们编写如下汇编代码

.text
.global _start
 
_start:
 
     /*设置内存:SP栈*/
     ldr sp, =4096                /*2440设置为nand启动时,片内4K内存地址为0,我们把栈设置这4K内存的顶部,*/
     //led sp, =0x40000000 + 4096 /*nor启动时,片内4K内存的地址是0x40000000,我们同样也把栈设置在4K内存的顶部。 */
 
     /* 调用main函数*/
     bl main	
 
 halt:
     b halt

然后编写makefile文件如下:

all:
	arm-linux-gcc -c -o led.o led.c
	arm-linux-gcc -c -o start.o start.S
	arm-linux-ld -Ttext 0 led.o  start.o -o led.elf
	arm-linux-objcopy -O binary -S  led.elf led.bin
	arm-linux-objdump -D led.elf  > led.dis
clean:
	rm *.bin  *.o  *.elf   *.dis
	

编译完之后下载到开发板中发现灯不亮,经查找原因是链接时文件顺序写错了,将上面makefile文件里面的

arm-linux-ld -Ttext 0 led.o  start.o -o led.elf    修改为    arm-linux-ld -Ttext 0 start.o led.o -o led.elf。

然后重新编译后程序正确。

6.循环点亮LED

首先我们把之前的汇编代码进行了修改,关掉了看门狗,另外也自动的适配nand启动和nor启动,修改后的汇编代码如下。


.text
.global _start

_start:

	/* 关闭看门狗 */
	ldr r0, =0x53000000
	ldr r1, =0
	str r1, [r0]

	/* 设置内存: sp 栈 */
	/* 分辨是nor/nand启动
	 * 写0到0地址, 再读出来
	 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
	 * 否则就是nor启动
	 */
	mov r1, #0
	ldr r0, [r1] /* 读出原来的值备份 */
	str r1, [r1] /* 0->[0] */ 
	ldr r2, [r1] /* r2=[0] */
	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
	moveq sp, #4096  /* nand启动 */
	streq r0, [r1]   /* 恢复原来的值 */
	

	bl main

halt:
	b halt
	

c语言源文件如下


#include "s3c2440_soc.h"

void delay(volatile int d)
{
	while (d--);
}

int main(void)
{
	int val = 0;  /* val: 0b000, 0b111 */
	int tmp;

	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));

	/* 循环点亮 */
	while (1)
	{
		tmp = ~val;
		tmp &= 7;
		GPFDAT &= ~(7<<4);
		GPFDAT |= (tmp<<4);
		delay(100000);
		val++;
		if (val == 8)
			val =0;
		
	}

	return 0;
}



C语言头文件如下


#ifndef  __S3C2440_SOC_H
#define  __S3C2440_SOC_H

#define     __REG(x)					(*(volatile unsigned int *)(x)) 

/*I/O port*/
#define     GPACON                   __REG(0x56000000)  //Port A control                           
#define     GPADAT                   __REG(0x56000004)  //Port A data                                      
#define     GPBCON                   __REG(0x56000010)  //Port B control                                   
#define     GPBDAT                   __REG(0x56000014)  //Port B data                                      
#define     GPBUP                    __REG(0x56000018)  //Pull-up control B                                
#define     GPCCON                   __REG(0x56000020)  //Port C control                                   
#define     GPCDAT                   __REG(0x56000024)  //Port C data                                      
#define     GPCUP                    __REG(0x56000028)  //Pull-up control C                                
#define     GPDCON                   __REG(0x56000030)  //Port D control                                   
#define     GPDDA1T                  __REG(0x56000034)  //Port D data                                      
#define     GPDUP                    __REG(0x56000038)  //Pull-up control D                                
#define     GPECON                   __REG(0x56000040)  //Port E control                                   
#define     GPEDAT                   __REG(0x56000044)  //Port E data                                      
#define     GPEUP                    __REG(0x56000048)  //Pull-up control E                                
#define     GPFCON                   __REG(0x56000050)  //Port F control                                   
#define     GPFDAT                   __REG(0x56000054)  //Port F data                                      
#define     GPFUP                    __REG(0x56000058)  //Pull-up control F                                
#define     GPGCON                   __REG(0x56000060)  //Port G control                                   
#define     GPGDAT                   __REG(0x56000064)  //Port G data                                      
#define     GPGUP                    __REG(0x56000068)  //Pull-up control G                                
#define     GPHCON                   __REG(0x56000070)  //Port H control                                   
#define     GPHDAT                   __REG(0x56000074)  //Port H data                                      
#define     GPHUP                    __REG(0x56000078)  //Pull-up control H                                
#define     GPJCON                   __REG(0x560000D0)  //Port J control                                   
#define     GPJDAT                   __REG(0x560000D4)  //Port J data                                      
#define     GPJUP                    __REG(0x560000D8)  //Pull-up control J                                
#define     MISCCR                   __REG(0x56000080)  //Miscellaneous control                            
#define     DCLKCON                  __REG(0x56000084)  //DCLK0/1 control                                  
#define     EXTINT0                  __REG(0x56000088)  //External interrupt control register 0            
#define     EXTINT1                  __REG(0x5600008C)  //External interrupt control register 1            
#define     EXTINT2                  __REG(0x56000090)  //External interrupt control register 2            
#define     EINTFLT0                 __REG(0x56000094)  //? W R/W Reserved                                 
#define     EINTFLT1                 __REG(0x56000098)  //Reserved                                         
#define     EINTFLT2                 __REG(0x5600009C)  //External interrupt filter control register 2     
#define     EINTFLT3                 __REG(0x560000A0)  //External interrupt filter control register 3     
#define     EINTMASK                 __REG(0x560000A4)  //External interrupt mask                          
#define     EINTPEND                 __REG(0x560000A8)  //External interrupt pending                       
#define     GSTATUS0                 __REG(0x560000AC)  //R External pin status                            
#define     GSTATUS1                 __REG(0x560000B0)  //R/W Chip ID                                      
#define     GSTATUS2                 __REG(0x560000B4)  //Reset status                                     
#define     GSTATUS3                 __REG(0x560000B8)  //Inform register                                  
#define     GSTATUS4                 __REG(0x560000BC)  //Inform register                                  
#define     MSLCON                   __REG(0x560000CC)  //Memory sleep control register           

#endif

7.按键控制LED

首先看一下原理图

            

可以看到三个按键分别对应GPF0,GPF2,GPG3,编写C语言代码如下


#include "s3c2440_soc.h"

void delay(volatile int d)
{
	while (d--);
}

int main(void)
{
	int val1, val2;
	
	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));

	/* 配置3个按键引脚为输入引脚:
	 * GPF0(S2),GPF2(S3),GPG3(S4)
	 */
	GPFCON &= ~((3<<0) | (3<<4));  /* gpf0,2 */
	GPGCON &= ~((3<<6));  /* gpg3 */

	/* 循环点亮 */
	while (1)
	{
		val1 = GPFDAT;
		val2 = GPGDAT;

		if (val1 & (1<<0)) /* s2 --> gpf6 */
		{
			/* 松开 */
			GPFDAT |= (1<<6);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<6);
		}

		if (val1 & (1<<2)) /* s3 --> gpf5 */
		{
			/* 松开 */
			GPFDAT |= (1<<5);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<5);
		}

		if (val2 & (1<<3)) /* s4 --> gpf4 */
		{
			/* 松开 */
			GPFDAT |= (1<<4);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<4);
		}

		
	}

	return 0;
}



猜你喜欢

转载自blog.csdn.net/u013171226/article/details/113851050