exynos4412之按键控制led

1. 按键控制灯的亮灭

1.1 配置寄存器

据电路图可知,k2按键接在 GPX1_1 

K2 ----  GPX1_1   

key  input功能    按键按下 LED 亮   按键弹起LED 灭 

1.  熟悉操作目标硬件   

KEY 轻触开关   按下 接通  弹起 断开 

2.  硬件设备 与 芯片的 逻辑连接(看电路图)

k2 按下  低电平   弹起  高电平  

3. 芯片管脚控制 功能   芯片手册    gpio功能 

4. 芯片手册  查询GPX1_1 寄存器 

GPX1CON   configuration register   配置寄存器 

[7:4]  = 0  INPUT 模式

GPX1DAT    data register    数据寄存器 

if	( [1] == 0 )  按键按下 
else   按键 弹起 

GPX1PUD    pull-up/ pull-down register  上下拉配置寄存器

[3:2]  = 0  不使能上下拉

GPX1DRV    drive strength control register  驱动强度配置 

不配置 

1.2 代码

key2_led3-----main

1.2 代码

key2_led3-----main

#include "exynos_4412.h"
//按键控制灯的亮灭

//初始化led3
void led3_init()
{
    //配置引脚模式
    GPX1.CON = (GPX1.CON & ~(0xf<<0)) | (0x1 << 0);
    //配置数据寄存器
    GPX1.DAT |= 1;
    //配置上下拉寄存器
    GPX1.PUD &= ~(0x3<<0);
}
void key2_init()
{
    //配置为输入模式
    // GPX1.CON = (GPX1.CON & ~(0xf<<4))|(0x0<<4);
    GPX1.CON &= ~(0xf<<4);
    //配置上下拉寄存器
    // GPX1.PUD = (GPX1.PUD & ~(0x3<<2)) | (0x0<<2);
    GPX1.PUD &= ~(0x3<<2);
}
int main()
{
    led3_init();
    key2_init();

    while(1){

        //读出数据位GPX1.DAT & (0x1<<1) 看看是0还是1  是0表示按键按下  1表示按键松开
        if(!(GPX1.DAT & (0x1<<1))){//按键按下
        // if(((GPX1.DAT>>1) & 1) == 0){
            //点亮led3
            GPX1.DAT |= 1;
        }else{
            //熄灭
            GPX1.DAT &= ~1;
        }
    }

    return 0;
}

2. 实现 按下对应按键控制 LED亮灭 

2.1 普通版

k2 ---- LED2 

K3 ---- LED3 

K4 ---- LED4/5

key_led_pro---mian.c

#include "exynos_4412.h"

/*
实现 按下对应按键控制 LED亮灭 
			k2 ---- LED2 
			K3 ---- LED3 
			K4 ---- LED4/5

*/

void led2_init()
{
    //配置引脚模式
    GPX2.CON = (GPX2.CON & ~(0xf<<28)) | (0x1 << 28);
    //配置数据寄存器
    // GPX2.DAT |= 0x80;  //1000 0000
    GPX2.DAT &= ~(0x80);
    //配置上下拉寄存器
    GPX2.PUD &= ~(0x3<<14);
}

void led3_init()
{
    //配置引脚模式
    GPX1.CON = (GPX1.CON & ~(0xf<<0)) | (0x1 << 0);
    //配置数据寄存器
    // GPX1.DAT |= 1;
    GPX1.DAT &= ~1;
    //配置上下拉寄存器
    GPX1.PUD &= ~(0x3<<0);
}

void led4_init()
{
   GPF3.CON = (GPF3.CON & ~(0xf << 16)) | (0x1 << 16); //配置引脚模式 配置为输出模式
    // GPF3.DAT |= 0x10;//配置数据寄存器,输出高电平  0001 0000
    GPF3.DAT &= ~(0x10);
    GPF3.PUD &= ~(0x3<<8);//配置上下拉配置寄存器,不使能上下拉
}
void led5_init()
{
    GPF3.CON = (GPF3.CON & ~(0xf << 20)) | (0x1 << 20); //配置引脚模式 配置为输出模式
    // GPF3.DAT |= 0x20;//配置数据寄存器,输出高电平  0010 0000
    GPF3.DAT &= ~(0x20);
    GPF3.PUD &= ~(0x3<<10);//配置上下拉配置寄存器,不使能上下拉
}

//key2初始化 GPX1_1
void key2_init()
{
    //配置为输入模式
    // GPX1.CON = (GPX1.CON & ~(0xf<<4))|(0x0<<4);
    GPX1.CON &= ~(0xf<<4);
    //配置上下拉寄存器
    // GPX1.PUD = (GPX1.PUD & ~(0x3<<2)) | (0x0<<2);
    GPX1.PUD &= ~(0x3<<2);
}

//key3 初始化   GPX1_2
void key3_init()
{
    //配置为输入模式
    GPX1.CON &= ~(0xf<<8);

    //配置上下拉寄存器
    GPX1.PUD &= ~(0x3<<4);
}

//key4 初始化 GPX3_2
void key4_init()
{
    GPX3.CON &= ~(0xf<<8);
    GPX3.PUD &= ~(0x3<<4);
}

int main()
{
    led2_init();
    led3_init();
    led4_init();
    led5_init();

    key2_init();
    key3_init();
    key4_init();

    
    while(1){
        //读取 key2 键值
       if(((GPX1.DAT>>1) & 1) == 0){
            GPX2.DAT |= 0x80;
       }else{
            GPX2.DAT &= ~(0x80);
       }

       //读取 key3 键值
       if(((GPX1.DAT>>2) & 1) == 0){
            GPX1.DAT |= 1;
       }else{
            GPX1.DAT &= ~1;
       }

       //读取 key4 键值
       if(((GPX3.DAT>>2) & 1) == 0){
            GPF3.DAT |= 0x10;
            GPF3.DAT |= 0x20;
       }else{
            GPF3.DAT &= ~(0x10);
            GPF3.DAT &= ~(0x20);
       }
    }
    
    return 0;
}

2.2 升级版

key_test2----led.h

#ifndef __LED_H
#define __LED_H


//初始化ADDR对应的gpio控制 对于bit管脚为 output 模式
void gpio_output(volatile void * addr, int bit);
		
//对 addr 的 bit 管脚 设置输出 out 状态
void gpio_set(volatile void * addr, int bit, int out);

//初始化ADDR对应的gpio控制 对于bit管脚为 input 模式
void gpio_input(volatile void * addr, int bit);

void led_init();

#endif

key_test2----led.c

"exynos_4412.h" 中gpx...和gpf...的结构体结构一样

#include "exynos_4412.h"

//初始化ADDR对应的gpio控制 对于bit管脚为 output 模式
void gpio_output(volatile void * addr, int bit)
{
	//CON ADDR->CON [bit*4+3 : bit*4] = 0x1;
	//((volatile gpx1 *)addr)转换位结构体指针
	//结构体gpx1 这里解释一下为什么都用gpx1结构体,因为gpx1,gpx2,gpx3,包括gpf1...等等在 "exynos_4412.h"头文件中定义的结构都是一样的
	//只是一个名字而已,不必在意
	((volatile gpx1 *)addr)->CON = (((volatile gpx1 *)addr)->CON & ~(0XF << (4 * bit )) | (0x1 << (4 * bit )));
	
	//PUD ADDR->PUD [2 *bit+1 : 2*bit] = 0x0
	((volatile gpx1 *)addr)->PUD &=  ~(0X3 << (2 * bit ));
}

//初始化ADDR对应的gpio控制 对于bit管脚为 input 模式   也就是初始化按键key
void gpio_input(volatile void * addr, int bit)
{
	//CON ADDR->CON [bit*4+3 : bit*4] = 0x0;
	((volatile gpx1 *)addr)->CON  &=  ~(0XF << (4 * bit ));
	
	//PUD ADDR->PUD [2 *bit+1 : 2*bit] = 0x0
	((volatile gpx1 *)addr)->PUD &=  ~(0X3 << (2 * bit ));
}

//对 addr 的 bit 管脚 设置输出 out 状态
void gpio_set(volatile void * addr, int bit, int out)
{
	if(out){ //输出高电平 	
	 	((volatile gpx1 *)addr)->DAT |= 1<< bit; 
	}
	else{    //输出低电平
	 	((volatile gpx1 *)addr)->DAT &= ~(1 << bit); 
	}	
}

void led_init()
{
	gpio_output(&GPX1, 0);  //gpx1_0
	gpio_output(&GPX2, 7);  //gpx2_7
	gpio_output(&GPF3, 4);  
	gpio_output(&GPF3, 5);
}



key_test2----main


#include "exynos_4412.h"
#include "led.h"

//宏函数
//这个宏就是用来读取按键的状态的 是按下还松开
#define  TESTGPIO(GPIO,BIT)   (!(GPIO.DAT&(1<<BIT)))  //按键按下

//延时函数
void delay(int m)
{
	int i;
	while(m--)
	  for(i=0; i < 10000 ; i++);
}

int main()
{
	//初始化led
	led_init();
	//初始化按键
	gpio_input(&GPX1, 1);
	gpio_input(&GPX1, 2);
	gpio_input(&GPX3, 2);


	while(1)
	{
		if( TESTGPIO(GPX1,1) )
		{//亮 led2
			gpio_set(&GPX2, 7, 1);
		}
		else 
		{//灭 led2
			gpio_set(&GPX2, 7, 0);
		}

		if( TESTGPIO(GPX1,2) )
		{//亮 LED3
			gpio_set(&GPX1, 0, 1);
		}
		else 
		{//灭 led3
			gpio_set(&GPX1, 0, 0);
		}
		
		if( TESTGPIO(GPX3,2) )
		{//亮 LED4-5
			gpio_set(&GPF3, 4, 1);
			gpio_set(&GPF3, 5, 1);
		}
		else 
		{//灭 led4-5
			gpio_set(&GPF3, 4, 0);
			gpio_set(&GPF3, 5, 0);
		}
	}

    return 0;
}

3. 重点细节

一定注意我们这块板子,按键key全都默认打开输入模式的

led2是板子以上点就默认打开的

4 . led按一下亮,按一下灭

这里我们控制key2 和led3

4.1 普通版

key2_led3----main

//按键控制灯的亮灭 按一下亮按一下灭
//这里我们控制key2 和led3
#include "exynos_4412.h"
void delay(int m){
    int i;
    while(m--){
        for(i=0;i<10000;i++);
    }
}
//初始化led3
void led3_init()
{
    //配置引脚模式
    GPX1.CON = (GPX1.CON & ~(0xf<<0)) | (0x1 << 0);
    //配置数据寄存器
    // GPX1.DAT |= 1;
    GPX1.DAT &= ~1;
    //配置上下拉寄存器
    GPX1.PUD &= ~(0x3<<0);
}
void key2_init()
{
    //配置为输入模式
    // GPX1.CON = (GPX1.CON & ~(0xf<<4))|(0x0<<4);
    GPX1.CON &= ~(0xf<<4);
    //配置上下拉寄存器
    // GPX1.PUD = (GPX1.PUD & ~(0x3<<2)) | (0x0<<2);
    GPX1.PUD &= ~(0x3<<2);
}
int main()
{
    led3_init();
    key2_init();

    int flag = 0;
    while(1){

        //读出数据位GPX1.DAT & (0x1<<1) 看看是0还是1  是0表示按键按下  1表示按键松开

        if(((GPX1.DAT>>1) & 1) == 0){

            delay(10);
            while(((GPX1.DAT>>1) & 1) == 0);
            delay(10);
            if(flag==0){
                //点亮led3
                GPX1.DAT |= 1;
                flag = 1;
            }else{
                GPX1.DAT &= ~1;
                flag = 0;
            }

            
        }
    }

    return 0;
}

4.2 升级版

key_test3----led.h

#ifndef __LED_H
#define __LED_H


//初始化ADDR对应的gpio控制 对于bit管脚为 output 模式
void gpio_output(volatile void * addr, int bit);
		
//对 addr 的 bit 管脚 设置输出 out 状态
void gpio_set(volatile void * addr, int bit, int out);

//初始化ADDR对应的gpio控制 对于bit管脚为 input 模式
void gpio_input(volatile void * addr, int bit);

void led_init();

#endif

key_test3----led.c

#include "exynos_4412.h"

//初始化ADDR对应的gpio控制 对于bit管脚为 output 模式
void gpio_output(volatile void * addr, int bit)
{
	//CON ADDR->CON [bit*4+3 : bit*4] = 0x1;
	//((volatile gpx1 *)addr)转换位结构体指针
	//结构体gpx1 这里解释一下为什么都用gpx1结构体,因为gpx1,gpx2,gpx3,包括gpf1...等等在 "exynos_4412.h"头文件中定义的结构都是一样的
	//只是一个名字而已,不必在意
	((volatile gpx1 *)addr)->CON = (((volatile gpx1 *)addr)->CON & ~(0XF << (4 * bit )) | (0x1 << (4 * bit )));
	
	//PUD ADDR->PUD [2 *bit+1 : 2*bit] = 0x0
	((volatile gpx1 *)addr)->PUD &=  ~(0X3 << (2 * bit ));
}

//初始化ADDR对应的gpio控制 对于bit管脚为 input 模式   也就是初始化按键key
void gpio_input(volatile void * addr, int bit)
{
	//CON ADDR->CON [bit*4+3 : bit*4] = 0x0;
	((volatile gpx1 *)addr)->CON  &=  ~(0XF << (4 * bit ));
	
	//PUD ADDR->PUD [2 *bit+1 : 2*bit] = 0x0
	((volatile gpx1 *)addr)->PUD &=  ~(0X3 << (2 * bit ));
}

//对 addr 的 bit 管脚 设置输出 out 状态
void gpio_set(volatile void * addr, int bit, int out)
{
	if(out){ //输出高电平 	
	 	((volatile gpx1 *)addr)->DAT |= 1<< bit; 
	}
	else{    //输出低电平
	 	((volatile gpx1 *)addr)->DAT &= ~(1 << bit); 
	}	
}

void led_init()
{
	gpio_output(&GPX1, 0);  //gpx1_0
}



key_test3----main.c

//按键控制灯的亮灭 按一下亮按一下灭 升级版
//这里我们控制key2 和led3

#include "exynos_4412.h"
#include "led.h"

//宏函数
//这个宏就是用来读取按键的状态的 是按下还松开
#define  TESTGPIO(GPIO,BIT)   (!(GPIO.DAT&(1<<BIT)))  //按键按下

//延时函数
void delay(int m)
{
	int i;
	while(m--)
	  for(i=0; i < 10000 ; i++);
}

int main()
{
	//初始化led
	led_init();

	//初始化按键key2
	gpio_input(&GPX1, 1);

	//定义保存状态的变量 this_stat这次状态  last_stat上一次状态
	int this_stat, last_stat;

	//因为我们第一次按下,没有上一次的状态,所以第一次按下的状态 既是这一次的 也是上一次的
	last_stat = TESTGPIO(GPX1,1);  

	while(1)
	{
		//读这一次的状态	
		this_stat = TESTGPIO(GPX1,1);  

		//比较这一次和上一次的区别  这一次和上一次状态不同,说明按键按下或者松开
		if(this_stat != last_stat)//有边沿触发了
		{
			if(this_stat) //我们需要按键松开
			{//上升沿
				//控制led3的亮灭
				//LED2 取反  
				//这里解释取反,因为使用的是 异或操作,相同为0  不同为1  这就达到了取反的操作
				GPX1.DAT ^= (1<<0);  
			}

			//这一次状态过后就变成了上一次状态,所以将这一次状态赋值给上一次
			//这里解释为什么在if里面区改变上一次的状态,因为,进入if的前提是两次状态不同,不同的话肯定要更新上一次的状态值
			//要是没进入if 那么两次状态还是一样的,就没必要执行这句代码了
			last_stat = this_stat;
		}

		delay(10);//延时,软件消抖

	}

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值