arm学习之stm32设备树学习-中断控制led灯亮灭+字符设备指令控制led灯亮灭

中断控制led灯亮灭
驱动文件源码
led-key.c

#include<linux/init.h>
#include<linux/module.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
#include<linux/of_irq.h>
#include<linux/interrupt.h>
struct device_node *led_dev;
struct device_node *key_dev;
struct gpio_desc *gpiono_led_1;
struct gpio_desc *gpiono_led_2;
struct gpio_desc *gpiono_led_3;
unsigned int irqno_1;
unsigned int irqno_2;
unsigned int irqno_3;
irqreturn_t myirq_handler(int irq, void *dev){
    printk("irq=%d\n",irq);
    switch (irq)
    {
    case 71:
        gpiod_set_value(gpiono_led_1,!gpiod_get_value(gpiono_led_1));
        break;
    case 72:
        gpiod_set_value(gpiono_led_2,!gpiod_get_value(gpiono_led_2));
        break;
    case 73:
        gpiod_set_value(gpiono_led_3,!gpiod_get_value(gpiono_led_3));
        break;
    } 
    return IRQ_HANDLED;
}
static int __init mycdev_init(void){ 
    int ret;
    led_dev = of_find_node_by_path("/leds");
    if(led_dev == NULL)
    {
        printk("解析led灯设备树节点失败\n");
        return -EFAULT;
    }
    printk("解析led灯设备树成功\n");
    key_dev = of_find_node_by_path("/myirq");
    if(key_dev == NULL)
    {
        printk("解析中断设备树节点失败\n");
        return -EFAULT;
    }
    printk("解析中断设备树成功\n");
    gpiono_led_1 = gpiod_get_from_of_node(led_dev,"led1-gpios",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono_led_1))
    {
        printk("获取GPIO号失败\n");
        return -PTR_ERR(gpiono_led_1);
    }
     gpiono_led_2 = gpiod_get_from_of_node(led_dev,"led2-gpios",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono_led_2))
    {
        printk("获取GPIO号失败\n");
        return -PTR_ERR(gpiono_led_2);
    }
     gpiono_led_3 = gpiod_get_from_of_node(led_dev,"led3-gpios",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono_led_3))
    {
        printk("获取GPIO号失败\n");
        return -PTR_ERR(gpiono_led_3);
    }
    printk("申请GPIO编号成功\n");
    irqno_1 = irq_of_parse_and_map(key_dev,0);
    if(!irqno_1){
        printk("解析中断号失败\n");
        return -ENXIO;
    }
    printk("解析软中断号成功 irqno=%d\n",irqno_1);
    irqno_2 = irq_of_parse_and_map(key_dev,1);
    if(!irqno_2){
        printk("解析中断号失败\n");
        return -ENXIO;
    }
    printk("解析软中断号成功 irqno=%d\n",irqno_2);
    irqno_3 = irq_of_parse_and_map(key_dev,2);
    if(!irqno_3){
        printk("解析中断号失败\n");
        return -ENXIO;
    }
    printk("解析软中断号成功 irqno=%d\n",irqno_3);
    //注册中断
    ret = request_irq(irqno_1,myirq_handler,IRQF_TRIGGER_FALLING,"key1",NULL);
    if(ret){
        printk("注册中断1失败\n");
        return ret;
    }
    //注册中断
    ret = request_irq(irqno_2,myirq_handler,IRQF_TRIGGER_FALLING,"key2",NULL);
    if(ret){
        printk("注册中断2失败\n");
        return ret;
    }
    //注册中断
    ret = request_irq(irqno_3,myirq_handler,IRQF_TRIGGER_FALLING,"key3",NULL);
    if(ret){
        printk("注册中断3失败\n");
        return ret;
    }
    printk("注册中断成功\n");
    return 0;
}
static void __exit mycdev_exit(void){
    free_irq(irqno_1,NULL);
    free_irq(irqno_2,NULL);
    free_irq(irqno_3,NULL);
    gpiod_set_value(gpiono_led_1,0);
    gpiod_put(gpiono_led_1);
    gpiod_set_value(gpiono_led_2,0);
    gpiod_put(gpiono_led_2);
    gpiod_set_value(gpiono_led_3,0);
    gpiod_put(gpiono_led_3);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

字符设备指令控制led灯亮灭
驱动文件
led-cmd.c

#include<linux/init.h>
#include<linux/module.h>
#include<linux/io.h>
#include<linux/fs.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
struct device_node *led_dev;
struct gpio_desc *gpiono_led_1;
struct gpio_desc *gpiono_led_2;
struct gpio_desc *gpiono_led_3;
struct class *cls;
struct device *dev;
char kbuf[128]={0};
unsigned int major;//定义一个变量保存主设备号
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
ssize_t mycdev_read(struct file *file, char  *ubuf, size_t size, loff_t *lof)
{
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
ssize_t mycdev_write(struct file *file, const char  *ubuf, size_t size, loff_t *lof)
{
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
     long ret;
     ret=copy_from_user(kbuf,ubuf,size);
     switch (kbuf[0])
    {
    case '1':
        gpiod_set_value(gpiono_led_1,!gpiod_get_value(gpiono_led_1));
        break;
    case '2':
        gpiod_set_value(gpiono_led_2,!gpiod_get_value(gpiono_led_2));
        break;
    case '3':
        gpiod_set_value(gpiono_led_3,!gpiod_get_value(gpiono_led_3));
        break;
    } 
    return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
void all_led_init(void){
    int ret;
    led_dev = of_find_node_by_path("/leds");
    if(led_dev == NULL)
    {
        printk("解析led灯设备树节点失败\n");
        //return -EFAULT;
    }
    gpiono_led_1 = gpiod_get_from_of_node(led_dev,"led1-gpios",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono_led_1))
    {
        printk("获取GPIO号失败\n");
        //return -PTR_ERR(gpiono_led_1);
    }
     gpiono_led_2 = gpiod_get_from_of_node(led_dev,"led2-gpios",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono_led_2))
    {
        printk("获取GPIO号失败\n");
        //return -PTR_ERR(gpiono_led_2);
    }
     gpiono_led_3 = gpiod_get_from_of_node(led_dev,"led3-gpios",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono_led_3))
    {
        printk("获取GPIO号失败\n");
       // return -PTR_ERR(gpiono_led_3);
    }
    printk("申请GPIO编号成功\n");
}
//定义一个操作方法结构体变量并且初始化
struct file_operations fops={
    .open=mycdev_open,
    .release=mycdev_close,
    .read=mycdev_read,
    .write=mycdev_write,
};
static int __init mycdev_init(void){ 
    //注册字符设备驱动
    major=register_chrdev(0,"mychrdev",&fops);
    if(major<0)
    {
        printk("注册字符设备驱动失败\n");
        return major;
    }
    printk("注册字符设备驱动成功major=%d\n",major);
    // 向上提交目录
    cls = class_create(THIS_MODULE, "mycdev");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录信息成功\n");
    // 向上提交设备节点信息
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycdev");
    if (IS_ERR(dev))
    {
        printk("向上提交设备节点信息失败\n");
        return -PTR_ERR(dev);
    }
    
    printk("向上提交设备节点成功\n");
    all_led_init();
    return 0;
}
static void __exit mycdev_exit(void){
    gpiod_set_value(gpiono_led_1,0);
    gpiod_put(gpiono_led_1);
    gpiod_set_value(gpiono_led_2,0);
    gpiod_put(gpiono_led_2);
    gpiod_set_value(gpiono_led_3,0);
    gpiod_put(gpiono_led_3);
     //注销字符设备驱动
        //销毁节点信息
    device_destroy(cls,MKDEV(major,0));
    //销毁目录信息
    class_destroy(cls);
    unregister_chrdev(major,"mychrdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

应用文件
led.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    char buf[128] = {0};
    int fd = open("/dev/mycdev", O_RDWR);
    if (fd < 0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while (1)
    {
        printf("请输入控制命令:1(led1关灯/开灯)2(led2关灯/开灯)3(led3关灯/开灯)>");
        fgets(buf, sizeof(buf), stdin); // 从终端输入数据到buf
        buf[strlen(buf) - 1] = '\0';    // 将buf末尾的'\n'切换为'\0'
        write(fd, buf, sizeof(buf));    
    }
    close(fd);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值