这个比较简单,和之前说的控制LED没有本质的差别。
我们看一下原理图开关和LED的位置。
这里开关并不是灯连一起的,我们只能检测开关状态然后控制灯。
裸机下不知道怎么控制中断寄存器,就先用GPIO的输入功能先了。
我们把按键的gpio设置为输入功能,led的gpio设置为输出功能。
一个循环来检测按键的状态,如果按下就给灯的gpio输出低电平,就点亮。反之就输出高电平,灯灭了。
原理很简单,我们这里主要实现是 位控制。
我们的控制的原则是:不能破坏原来寄存器的状态,设置寄存器。
这里涉及到C语言的位操作,这里主要看C语言的位操作。
这里见我总结的C语言位运算,详细见:http://blog.csdn.net/zmnqazqaz/article/details/51266616
下面是代码时间:
├── startc.S
└── switch_led
├── led_switch.c
└── Makefile
led_switch.c
#include "../../pub/include/bit.h"
#define P_GPFCON ((volatile unsigned long *)0x56000050)
#define P_GPFDAT ((volatile unsigned long *)0x56000054)
#define P_GPGCON ((volatile unsigned long *)0x56000060)
#define P_GPGDAT ((volatile unsigned long *)0x56000064)
int main()
{
//关闭LED
setNbit(P_GPFDAT,2,4,0x7);//111
//按键默认抬起
SetBit(*P_GPFDAT,0);
SetBit(*P_GPFDAT,2);
SetBit(*P_GPGDAT,3);
//1.config
setNbit(P_GPFCON,2,4*2,0x1);
setNbit(P_GPFCON,2,5*2,0x1);
setNbit(P_GPFCON,2,6*2,0x1);
setNbit(P_GPFCON,2,0*2,0x0);
setNbit(P_GPFCON,2,2*2,0x0);
setNbit(P_GPGCON,2,3*2,0x0);
while(1)
{
if(GetBit(*P_GPFDAT,0)==0){
ClearBit(*P_GPFDAT,4);//LED1
}else{
SetBit(*P_GPFDAT,4);
}
if(GetBit(*P_GPFDAT,2)==0){
ClearBit(*P_GPFDAT,5);//LED1
}else{
SetBit(*P_GPFDAT,5);
}
if(GetBit(*P_GPGDAT,3)==0){
ClearBit(*P_GPFDAT,6);//LED1
}else{
SetBit(*P_GPFDAT,6);
}
}
}
这里首先将led的date寄存器默认值默认是低电平,一设置成输出灯立刻点亮。
出现的现象就是灯一闪而过,然后可以正常控制了。
所以一开始吧data寄存器设置成高电平就好了。
下面是控制位的实现:
void setNbit(unsigned long *bits, int N, int start_bit, int value)
{
int mask = 0, i = N;
while (--i >= 0)
{
mask |= (0x1 << i);
}
*bits = *bits & (~(mask << start_bit)) | (value << start_bit);
}
void getNbit(unsigned long * bits, int N, int start_bit, int *value)
{
int mask = 0, i = N;
while (--i >= 0)
{
mask |= (0x1 << i);
}
*value = ( *bits >> start_bit) & mask;
}
#define GetBit(dat,i) ( (dat)&( 0x1<<(i) )?1:0 )
#define SetBit(dat,i) ( (dat)|=( 0x1<<(i) ) )
#define ClearBit(dat,i) ( (dat)&= ~(0x01<<(i)) )