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;
}