1.硬件原理图
2.设备树添加内容:
1)
/* gpio 信息
标签: 名字
使用标签的目的就是为了方便访问节点。
*/
&iomuxc_snvs {
imx6ul-evk {
pinctrl_key: keygrp {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x000110A0 /* key1 */
>;
};
}
}
2)
/* 设备树中添加设备节点 */
gpiokey {
compatible = "atkalpha-gpiokey";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_key>;
key-gpio = <&gpio5 1 GPIO_ACTIVE_LOW>;
status = "okay";
};
3.驱动的实现:
3.1.1)定义file_operations结构体变量
static const struct file_operations key_fops = {
.owner = THIS_MODULE,
.write = key_write,
.read = key_read,
.open = key_open,
.release = key_release,
};
3.1.2)驱动入口函数显示:初始化原子操作;
atomic_set(&key.keyvalue, INVAKEY);
3.1.3)用于申请设备号
ret = alloc_chrdev_region(&key.devid, 0, KEY_CNT, KEY_NAME);
3.1.4)初始化cdev
key.cdev.owner = THIS_MODULE;
3.1.5)添加cdev,向内核添加file_operations结构体
ret = cdev_add(&key.cdev, key.devid, KEY_CNT);
3.1.6)创建类
key.class = class_create(THIS_MODULE, KEY_NAME);
3.1.7)创建设备
key.device = device_create(key.class, NULL, key.devid, NULL, KEY_NAME);
3.2.1)按键引脚初始化:查找到按键引脚的设备树节点
dev->nd = of_find_node_by_path("/gpiokey");
3.2.2)从设备树获取指定 GPIO 属性信息,返回这个 GPIO 的标号。
dev->key_gpio = of_get_named_gpio(dev->nd, "key-gpio", 0);
3.2.3)申请一个 GPIO 管脚,在使用一个 GPIO 之前一定要进行申请
ret = gpio_request(dev->key_gpio, "key0");
3.2.4)设置某个 GPIO 为输入
ret = gpio_direction_input(dev->key_gpio);
3.3.1)linux驱动按键读取实现:
if(gpio_get_value(dev->key_gpio) == 0) { /* 按下 */
while(!gpio_get_value(dev->key_gpio)); //按键释放
atomic_set(&dev->keyvalue, KEY0VALUE); //读取按键值
} else {
atomic_set(&dev->keyvalue, INVAKEY);
}
value = atomic_read(&dev->keyvalue);
ret = copy_to_user(buf, &value, sizeof(value));
4.用户层代码实现:
1)打开设备:
fd = open(filename, O_RDWR);
2)循环读取按键值
while(1) {
read(fd, &value, sizeof(value));
if(value == KEY0VALUE) {
printf("KEY0 Press, value = %d\r\n", value);
}
}
5.按下按键后的效果显示: