【S3C2440③】GPIO实验

实验1 —— 点亮一个LED

1.看原理图确定硬件如何连接

原理图中表示了芯片控制LED的硬件电路以及芯片的引脚与LED如何连接。

【S3C2440③】GPIO实验
【S3C2440③】GPIO实验

2. 看主芯片手册确定如何控制引脚

具体:如何让GPF4输出高低电平?
【S3C2440③】GPIO实验

2.1.配置GPF4为输出模式(GPFCON)

【S3C2440③】GPIO实验
设置GPFCON寄存器的第[9:8]位=0b01

2.2.配置GPF4输出高/低电平(GPFDAT)

【S3C2440③】GPIO实验
GPFDAT的第4位为0-低电平,1-高电平。(注:corresponding,相应的)

3.汇编程序访问寄存器控制LED

3.1.编辑程序

@ brief:	点亮连接在GPF4的LED
@ author:	mculover666
@ date:		2019/3/1

.text
.global _start

_start:
	@ 设置GPFCON寄存器,GPF4为输出模式
	LDR R0,=0x56000050
	LDR R1,=0x0100
	STR R1,[R0]

	@ 设置GPFDAT寄存器,GPF4输出低电平
	LDR R0,=0X56000054
	LDR R1,=0
	STR R1,[R0]

	@程序暂停
halt:
	B halt

3.2.编译程序

  1. 汇编为二进制目标文件
arm-linux-gcc -c led_on.s -Wall -o led_on.o
  1. 链接为可执行文件elf
arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
  1. 转换为bin文件
arm-linux-objcopy -O binary -S led_on.elf led_on.bin

整个编译步骤可编写为一个makefile:

TARGET = led_on

#输出所有warning
CFLAGS = -Wall

$(TARGET).bin:$(TARGET).elf
	arm-linux-objcopy -O binary -S $(TARGET).elf $(TARGET).bin
$(TARGET).elf:$(TARGET).o
	arm-linux-ld -Ttext 0 $(TARGET).o -o $(TARGET).elf
$(TARGET).o:$(TARGET).s
	arm-linux-gcc -c $(TARGET).s $(CFLAGS) -o $(TARGET).o
	
clean:
	rm -rf *.o *.elf *.bin

download_to_nand:
	#下载到nand flash
	oflash 0 1 0 0 0 $(TARGET).bin 

3.3.烧写程序

使用oflash烧写bin文件到Nand Flash的0地址:

oflash 0 1 0 0 0 .\led_on.bin

3.4.运行程序

  1. 设置启动开关选择为Nand启动;
  2. 重新上电;
  3. 实验结果
    【S3C2440③】GPIO实验

4.C程序访问寄存器控制LED

4.1.运行C程序的前提——启动文件

  • C语言入口函数是main()函数,main函数由启动文件(刚上电时执行的汇编程序)来调用;
  • 在调用时会进行压栈操作,调用完毕进行出栈操作,所以需要设置好栈顶指针SP;
  • main函数调用完毕返回启动文件调用处。
启动文件start.s:初始化C语言运行环境,引入C程序

@ brief:	S3C2440启动文件
@ author:	mculover666

.text
.global	_start

_start:
	@ 关闭看门狗
	LDR	R0,=0x53000000
	MOV	R1,#0
	STR	R1,[R0]
	
	@ 设置栈顶指针SP(从Nand启动)
	LDR SP,=4096
	
	@ 调用main函数,保存返回地址,转入C程序
	BL	main
	
	@ main函数返回,程序暂停
halt:
	B	halt
	

4.2.编写C程序——指针+位操作

int main(void)
{

	/* 设置GPFCON寄存器,配置GPF4引脚为输出模式 */
	*(unsigned int *)0x56000050 &= ~(3<<(2*4));
	*(unsigned int *)0x56000050 |= 1<<(2*4);
	
	/* 设置GPFDAT寄存器,GPF4输出低电平,点亮LED */
	*(unsigned int *)0x56000054 &= ~(1<<4);

	/* 程序暂停 */
	while(1);
	
}

4.3.编译

TARGET = led_on

#输出所有warning
CFLAGS = -Wall

$(TARGET).bin:$(TARGET).elf
	arm-linux-objcopy -O binary -S $(TARGET).elf $(TARGET).bin
$(TARGET).elf:$(TARGET).o start.o
	arm-linux-ld -Ttext 0 $(TARGET).o start.o -o $(TARGET).elf
$(TARGET).o:$(TARGET).c
	arm-linux-gcc -c $(TARGET).c $(CFLAGS) -o $(TARGET).o
start.o:start.s
	arm-linux-gcc -c start.s $(CFLAGS) -o start.o
	
clean:
	rm -rf *.o *.elf *.bin
	
download_to_nand:
	#下载到nand flash
	oflash 0 1 0 0 0 $(TARGET).bin 

4.4.烧写运行

oflash 0 1 0 0 0 .\led_on.bin

【S3C2440③】GPIO实验

实验2 —— 按键检测

1.看原理图确定硬件如何连接

【S3C2440③】GPIO实验
【S3C2440③】GPIO实验

2. 看主芯片手册确定如何控制引脚

2.1.配置GPF0为输入模式(GPFCON)

【S3C2440③】GPIO实验

2.2.读取GPF0的状态(高/低电平)(GPFDAT)

【S3C2440③】GPIO实验

3.C程序访问寄存器检测按键

3.1.编写程序

int main(void)
{
	int GPF0_state;

	/* 设置GPFCON寄存器 */
	//设置GPF4为输出
	*(unsigned int *)0x56000050 &= ~(3<<(2*4));
	*(unsigned int *)0x56000050 |= (1<<(2*4));
	//设置GPF0为输入
	*(unsigned int *)0x56000050 &= ~(3<<(2*0));
	
	while(1)
	{
		/* 读取GPFDAT寄存器 */
		GPF0_state = *(unsigned int *)0x56000054;
		
		/* 检测GPF4引脚的状态 */
		if(GPF0_state & 0x01)
		{
			//按键未按下,上拉电阻拉为高电平,熄灭LED
			*(unsigned int *)0x56000054 |= (1<<4);
		}
		else
		{
			//按键按下,低电平,点亮LED
			*(unsigned int *)0x56000054 &= ~(1<<4);
		}
	}
}

3.2.编译程序

TARGET = key_scan

$(TARGET).bin:$(TARGET).elf
	arm-linux-objcopy -O binary -S $(TARGET).elf $(TARGET).bin
$(TARGET).elf:$(TARGET).o start.o
	arm-linux-ld -Ttext 0 $(TARGET).o start.o -o $(TARGET).elf
$(TARGET).o:$(TARGET).c
	arm-linux-gcc -c $(TARGET).c -o $(TARGET).o
start.o:start.s
	arm-linux-gcc -c start.s -o start.o
	
clean:
	rm -rf *.o *.elf *.bin

download_to_nand:
	#下载到nand flash
	oflash 0 1 0 0 0 $(TARGET).bin 

3.3.烧写程序运行

oflash 0 1 0 0 0 .\led_on.bin

【S3C2440③】GPIO实验
【S3C2440③】GPIO实验

实验1、2总结