orangepi zero2w H618按键驱动(三)

跟着韦老师学的,不过使用的是orangepi
写的比较简单,请配合韦老师的视频食用

button_drv.h

//button_drv.h
#ifndef _BUTTON__DRV_H
#define _BUTTON__DRV_H

struct button_operations
{
    int count;
    void (*init) (int which);
	int (*read) (int which);
};


void register_button_operation(struct button_operations *opr);

void unregister_button_operation(void);



#endif

button_drv.c

//button_drv.c
#include <linux/fs.h>      //file_operations声明
#include <linux/module.h>  //module_init  module_exit声明
#include <linux/init.h>    //__init  __exit 宏定义声明
#include <linux/device.h>  //class  devise声明
#include <linux/uaccess.h> //copy_from_user 的头文件
#include <linux/types.h>   //设备号  dev_t 类型声明
#include <asm/io.h>        //ioremap iounmap的头文件


#include "button_drv.h"
static int major = 0; // find dirver funtion
// static int minor =0;  //次设备号 what ever

static struct class *button_class;

static struct button_operations *p_button_opr;

int button_open(struct inode *node, struct file *file)
{
    int minor = iminor(node); // give minor from node
    p_button_opr->init(minor);
    return 0;
}
	
ssize_t button_read(struct file *file, char __user *buf, size_t size, loff_t *off)
{
    int minor = iminor(file_inode(file)); // give minor from file
    char level;
    level = p_button_opr->read(minor);
    copy_to_user(buf, &level, sizeof(level));
    return 0;
}

void register_button_operation(struct button_operations *opr)
{
    int i;
    p_button_opr = opr;
    for (i = 0; i < opr->count; i++)
    {
        device_create(button_class, NULL, MKDEV(major, i), NULL, "clx_button%d", i);
    }
}

void unregister_button_operation(void)
{
    int i;
    for (i = 0; i < p_button_opr->count; i++)
    {
        device_destroy(button_class, MKDEV(major, i));
    }
}

EXPORT_SYMBOL(register_button_operation);
EXPORT_SYMBOL(unregister_button_operation);

static struct file_operations button_fops = {
    .open = button_open,
    .read = button_read,
};

int clx_button_init(void)
{

    major = register_chrdev(0, "clx_button", &button_fops);
    button_class = class_create(THIS_MODULE, "clx_button");
    if (IS_ERR(button_class))
        return -1;
    return 0;
}

void clx_button_exit(void)
{
    class_unregister(button_class);
    unregister_chrdev(major, "clx_button");
}

// 注册模块加载函数
module_init(clx_button_init);
// 卸载模块加载函数
module_exit(clx_button_exit);
// 开源信息
MODULE_LICENSE("GPL");

button_dev.c

//button_dev.c
#include <linux/fs.h>      //file_operations声明
#include <linux/module.h>  //module_init  module_exit声明
#include <linux/init.h>    //__init  __exit 宏定义声明
#include <linux/device.h>  //class  devise声明
#include <linux/uaccess.h> //copy_from_user 的头文件
#include <linux/types.h>   //设备号  dev_t 类型声明
#include <asm/io.h>

#include "button_drv.h"


#define GPIO_BASE 0x0300B000
#define GPIOC_BASE GPIO_BASE + 2 * 0x24
#define GPIOF_BASE GPIO_BASE + 5 * 0x24
#define GPIOG_BASE GPIO_BASE + 6 * 0x24
#define GPIOH_BASE GPIO_BASE + 7 * 0x24

#define PIO_POW_MOD_SEL 0x0300B340
#define PIO_POW_MS_CTL 0x0300B344
#define PIO_POW_VAL 0x0300B348





static struct Pn_CFG {
    unsigned int Pn_CFG0;
    unsigned int Pn_CFG1;
    unsigned int Pn_CFG2;
    unsigned int Pn_CFG3;
    unsigned int Pn_DAT;
    unsigned int Pn_DRV0;
    unsigned int Pn_DRV1;
    unsigned int Pn_PUL0;
    unsigned int Pn_PUL1;
};

static struct Pn_INT_CFG {
    unsigned int Pn_INT_CFG0;
    unsigned int Pn_INT_CFG1;
    unsigned int Pn_INT_CFG2;
    unsigned int Pn_INT_CFG3;
    unsigned int Pn_INT_STL;
    unsigned int Pn_INT_STA;
    unsigned int Pn_INT_DEB;
};

struct Pn_CFG* PC_CFG;

static void clx_button_init(int which)
{
    printk("start init\n");
    PC_CFG = ioremap(GPIOC_BASE,sizeof(struct Pn_CFG));
    //in mode
    PC_CFG->Pn_CFG1 &=  ~((unsigned int)7 << (12%8)*4);//使用GPIOC_12引脚
    //pull up
    PC_CFG->Pn_PUL0 |=  ((unsigned int)1 << 12);
    printk("Pn_CFG1 = %#x p = %p , Pn_PUL0 = %#x p = %p ",PC_CFG->Pn_CFG1,PC_CFG->Pn_CFG1,(PC_CFG->Pn_PUL0),PC_CFG->Pn_PUL0);//output 0x
}
static int clx_button_read(int which)
{
    printk("start read\n");
    if(~(PC_CFG->Pn_CFG1 >> (12%8)*4) & 7 == 7)//判断引脚是否为输入模式
    {
        if((PC_CFG->Pn_DAT >> 12)&0x01 == 1)//判断读取引脚的值是否为1
            printk("read data is high\n");
        else printk("read data is low\n");
        return 0;
    }
        
    else
        return -1;
}

static struct button_operations clx_button_opr = {
    .count = 2,
    .init = clx_button_init,
    .read = clx_button_read,
};

int __init clx_button_drv_init(void)
{
    register_button_operation(&clx_button_opr);
    return 0;
}

void __exit clx_button_drv_exit(void)
{
    unregister_button_operation();
}

module_init(clx_button_drv_init);
module_exit(clx_button_drv_exit);

// 开源信息
MODULE_LICENSE("GPL");

Makefile

# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR
# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量:
# 2.1 ARCH,          比如: export ARCH=arm64
# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu-
# 2.3 PATH,          比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin 
# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同,
#       请参考各开发板的高级用户使用手册

KERN_DIR = /home/coolx/orangepi-build/kernel/orange-pi-6.1-sun50iw9

all:
	make -C $(KERN_DIR) M=`pwd` modules 
#$(CROSS_COMPILE)gcc -o led_dev led_dev.c 
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order
#rm -f led_dev


#obj-m	+= pindriver.o
obj-m	+= led_dev.o led_tree_drv.o
obj-m   += button_drv.o button_dev.o

在这里插入图片描述
编译模块后上传到开发板

orangepi@orangepizero2w:~$ sudo insmod button_drv.ko
orangepi@orangepizero2w:~$ sudo insmod button_dev.ko
orangepi@orangepizero2w:~$ sudo chmod 666 /dev/clx_button0
orangepi@orangepizero2w:~$ sudo dmesg -c
//短接PC12和GND(上图圈出)
orangepi@orangepizero2w:~$ cat /dev/clx_button0
orangepi@orangepizero2w:~$ dmesg
[170038.569863] start init
[170038.569920] Pn_CFG1 = 0x17107760 p = 000000006cd91c13 , Pn_PUL0 = 0x5541 p = 000000006633a63a
[170038.570021] start read
[170038.570035] read data is low
//断开PC12和GND(上图圈出)
orangepi@orangepizero2w:~$ cat /dev/clx_button0
orangepi@orangepizero2w:~$ dmesg
[170038.569863] start init
[170038.569920] Pn_CFG1 = 0x17107760 p = 000000006cd91c13 , Pn_PUL0 = 0x5541 p = 000000006633a63a
[170038.570021] start read
[170038.570035] read data is low
[170293.852490] start init
[170293.852546] Pn_CFG1 = 0x17107760 p = 000000006cd91c13 , Pn_PUL0 = 0x5541 p = 000000006633a63a
[170293.852649] start read
[170293.852663] read data is high

参考链接:
https://www.100ask.net/
https://www.bilibili.com/video/BV1w4411B7a4?p=116

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值