学会了操作led,那按键就轻而一举,同样是对GPIO操作,只不过按键的GPIO是输入模式,led的GPIO是输出模式,这节我们添加了main.c和main.h 开始模块化编程,为后面编写BootLoader做好准备。
不废话,盘它,先看下按键的原理图,知道具体操作什么端口。下图可以知道按键S2~S7依次接到了6410的GPN0~GPN5。
开始写代码前需要将GPN端口添加到s3c6410.h文件中,后面的不再赘述了。
#ifndef S3C6410_H
#define S3C6410_H
#define GPMCON (*(volatile unsigned int *)(0x7F008820))
#define GPMDAT (*(volatile unsigned int *)(0x7F008824))
#define GPNCON (*(volatile unsigned int *)(0x7F008830))
#define GPNDAT (*(volatile unsigned int *)(0x7F008834))
#endif
开始写代码,我们用写51单片机的思维来为按键写一个驱动程序,具体代码如下:
key.c的代码如下,主要实现了对按键GPIO的初始化和按键扫描操作,通过按键来控制led灯操作。
#include "key.h"
//按键初始化
//S2~S7:GPN0~GPN5
void KeyInit()
{
//输入模式
GPNCON &= ~((3<<0)|(3<<2)|(3<<4)|(3<<6)|(3<<8)|(3<<10));
//按键都没有按下
GPNDAT |= ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5));
}
//按键扫描函数
// keyval值: 按下按键
// 0 无
// 1 S2
// 2 S3
// 3 S4
// 4 S5
// 5 S6
// 6 S7
void KeyScan()
{
// 按键S2
if(!(GPNDAT& (1<<0)))
{
LED1_ON;
}
//按键S3
if(!(GPNDAT& (1<<1)))
{
LED2_ON;
}
//按键S4
if(!(GPNDAT& (1<<2)))
{
LED3_ON;
}
//按键S5
if(!(GPNDAT& (1<<3)))
{
LED4_ON;
}
//按键S6
if(!(GPNDAT& (1<<4)))
{
LED1_ON;LED2_ON;LED3_ON;LED4_ON;
}
//按键S7
if(!(GPNDAT& (1<<5)))
{
LED1_OFF;LED2_OFF;LED3_OFF;LED4_OFF;
}
}
key.h的代码如下,主要是为了其它函数调用
#ifndef _KEY_H
#define _KEY_H
#include "s3c6410.h"
#include "led.h"
void KeyInit(void);
void KeyScan(void);
#endif
main.c中调用KeyScan 函数即可,需要注意的是不要忘记对makefile的修改,具体的make代码如下:
main.bin: start.o led.o key.o main.o
arm-linux-ld -Ttext 0 -o main.elf start.o led.o key.o main.o
arm-linux-objcopy -O binary main.elf main.bin
arm-linux-objdump -D main.elf > main.dis
start.o : start.S
arm-linux-gcc -o start.o start.S -c -O2
led.o : led.c
arm-linux-gcc -o led.o led.c -c -O2
key.o : key.c
arm-linux-gcc -o key.o key.c -c -O2
main.o : main.c
arm-linux-gcc -o main.o main.c -c -O2
clean:
rm *.o *.elf *.bin *.dis