0%

Linux驱动学习日记(5) GPIO输入

原理分析

图 1 原理图

  根据原理图分析,按键KEY0连接到UART1_CTS这个IO口,并且接了一个10K的上拉电阻,由此可知当按键按下时,UART1_CTS是低电平,没有按下时是高电平。

  在第一次学习中已经知道,当GPIO_PIN被配置为输入时,GPIO->DR寄存器保存了当前引脚读到的电平,基于此原理可以通过按键控制LED亮灭。

代码编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// bsp_gpio.h

#ifndef _BSP_GPIO_H
#define _BSP_GPIO_H
#include"imx6ul.h"

typedef enum _gpio_pin_direction
{
kGPIO_INPUT = 0U,
kGPIO_OUTPUT = 1U,
}gpio_pin_direction_t;

typedef struct _gpio_pin_config
{
gpio_pin_direction_t direction;
uint8_t outPutLogic;
}gpio_pin_config_t;

void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *Config);
uint8_t gpio_ReadPin(GPIO_Type *base, int pin);
void gpio_WritePin(GPIO_Type *base, int pin, uint8_t value);

#endif

// bsp_gpio.c

#include "bsp_gpio.h"

void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *Config)
{
if(Config->direction == kGPIO_INPUT)
{
base->GDIR &= ~(1 << pin);
}
else
{
base->GDIR |= 1 << pin;
}
}

uint8_t gpio_ReadPin(GPIO_Type *base, int pin)
{
return (((base->DR) >> pin) & 0x01);
}

void gpio_WritePin(GPIO_Type *base, int pin, uint8_t value)
{
if(value == 1)
{
base->DR |= 1<<pin;
}
else
base->DR &= ~(1 << pin);
}

main.c如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_key.h"
#include "bsp_gpio.h"

int main(void)
{
clk_enable(); /* 使能所有的时钟 */
led_init(); /* 初始化led */
Key_Init();
led_switch(LED0,0);
while(1)
{
if(!gpio_ReadPin(GPIO1,18))
{
delay(40);
if(!gpio_ReadPin(GPIO1,18))
{
while(!gpio_ReadPin(GPIO1,18));
if(GPIO1->DR >> 3 & 0X1)
led_switch(LED0,1);
else
led_switch(LED0,0);
}
}
}

return 0;
}

按键需要消抖、防长按,因此做延时和while处理。

运行结果

使用上一章的makefile和链接脚本文件烧录即可。