linux 按键轮询驱动(gpio_keys_polled.c)

系统自带了gpio_keys_polled.c驱动文件,硬件资源是通过设备树获取,在不修改设备树的情况下,可以直接在驱动文件中对相关的结构体进行赋值。

1、定义当前使用的IO按钮数组

static struct gpio_keys_button buttons[]={
    {
        .gpio = 41,//IO引脚号,根据实际情况修改
        .code = KEY_1,
        .desc = "KEY1",
        .active_low = 1,
    },
    {
        .gpio = 120,
        .code = KEY_2,
        .desc = "KEY2",
        .active_low = 1,
    },
    {
        .gpio = 121,
        .code = KEY_3,
        .desc = "KEY3",
        .active_low = 1,
    },
    {
        .gpio = 5,
        .code = KEY_4,
        .desc = "KEY4",
        .active_low = 1,
    },
    {
        .gpio = 226,
        .code = KEY_5,
        .desc = "KEY5",
        .active_low = 1,
    },
};

2、修改gpio_keys_polled_probe()函数

具体硬件资源与驱动匹配的函数为 gpio_keys_polled_get_devtree_pdata(),需要注释掉“if(!pdata)这行,否则会出现pdata->poll_interval未赋值的情况。

3、修改gpio_keys_polled_get_devtree_pdata()函数

static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
{
	struct device_node *node, *pp;
	struct gpio_keys_platform_data *pdata;
	struct gpio_keys_button *button;
	int error;
	int nbuttons;
	int i;

	//不使用设备树,与之相关的代码均可注释掉
	//node = dev->of_node;
	//if (!node)
	//	return NULL;
    
    //按键数
	nbuttons = ARRAY_SIZE(buttons);//nbuttons = of_get_child_count(node);
	//if (nbuttons == 0)
	//	return NULL;

	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
			GFP_KERNEL);
	if (!pdata) {
		error = -ENOMEM;
		goto err_out;
	}

	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
	pdata->nbuttons = nbuttons;

    //扫描间隔手动赋值,注释掉从设备树获取代码
	//pdata->rep = !!of_get_property(node, "autorepeat", NULL);
	//of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
	pdata->poll_interval = 50;//50ms

	i = 0;
	#if 0 //注释掉从设备树获取相关按键代码
	for_each_child_of_node(node, pp) {
		int gpio;
		enum of_gpio_flags flags;

		if (!of_find_property(pp, "gpios", NULL)) {
			pdata->nbuttons--;
			dev_warn(dev, "Found button without gpios\n");
			continue;
		}

		gpio = of_get_gpio_flags(pp, 0, &flags);
		if (gpio < 0) {
			error = gpio;
			if (error != -EPROBE_DEFER)
				dev_err(dev,
					"Failed to get gpio flags, error: %d\n",
					error);
			goto err_free_pdata;
		}

		button = &pdata->buttons[i++];

		button->gpio = gpio;
		button->active_low = flags & OF_GPIO_ACTIVE_LOW;

		if (of_property_read_u32(pp, "linux,code", &button->code)) {
			dev_err(dev, "Button without keycode: 0x%x\n",
				button->gpio);
			error = -EINVAL;
			goto err_free_pdata;
		}

		button->desc = of_get_property(pp, "label", NULL);

		if (of_property_read_u32(pp, "linux,input-type", &button->type))
			button->type = EV_KEY;

		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);

		if (of_property_read_u32(pp, "debounce-interval",
					 &button->debounce_interval))
			button->debounce_interval = 5;
	}
	#else //使用我们定义的按键填充相关结构体
	for(i=0; i<nbuttons; i++)
	{
		button = &pdata->buttons[i];	
		button->gpio = buttons[i].gpio;
		button->active_low = buttons[i].active_low;
		button->type = EV_KEY;
		button->code = buttons[i].code;	
	}

	#endif

	if (pdata->nbuttons == 0) {
		error = -EINVAL;
		goto err_free_pdata;
	}

	return pdata;

err_free_pdata:
	kfree(pdata);
err_out:
	return ERR_PTR(error);
}

static struct of_device_id gpio_keys_polled_of_match[] = {
	{ .compatible = "gpio-keys-polled", },
	{ },
};

4、添加platform device 注册相关代码

static struct gpio_keys_platform_data button_data={
	.buttons = buttons,
	.nbuttons = ARRAY_SIZE(buttons),
};

static struct platform_device button_device={
	.name = "gpio-keys-polled",//此名字需与platform driver名字一致
	.id = -1,
	.dev = {
		.platform_data = &button_data,
	},
};
static int keys_dev_init(void)
{
	platform_device_register(&button_device);
	return 0;
}

static void keys_dev_exit(void)
{
	platform_device_unregister(&button_device);
}
module_init(keys_dev_init);
module_exit(keys_dev_exit);

到此修改完毕,编译下载运行。

5、终端输入cat /proc/bus/input/devices

6、终端输入 hexdump /dev/input/event1  查看运行情况

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是您提供的代码的注释: ``` // 引入GPIO库 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置GPIOB.8引脚为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 使能GPIOD时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // 配置GPIOD.15引脚为带下拉电阻的输入模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); } // 主函数 void main(void) { // LED_Init(); GPIO_Configuration(); int flag = 0; led_init(); while (1) { // 如果GPIOD.15引脚被触摸 if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_15) == Bit_SET) { // 触摸 if (flag == 0) { D5_off(); // 关闭LED flag = 1; } else { D5_on(); // 打开LED flag = 0; } // 等待松开 while (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_15) == Bit_SET) {} } } } ``` 这段代码主要是配置了两个GPIO引脚,一个为输出模式的GPIOB.8引脚,另一个为带下拉电阻的输入模式的GPIOD.15引脚。在主函数中,通过轮询的方式检测GPIOD.15引脚是否被触摸,如果被触摸则改变LED状态,并等待松开再继续轮询。需要注意的是,这段代码中没有使用中断,而是采用了轮询的方式检测GPIO引脚状态,因此可能会存在一定的延迟。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值