完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
原理图
发光二极管与普通二极管一样是由一个PN结组成,也具有单向导电性。当给发光二极管加上正向电压后,从P区注入到N区的空穴和由N区注入到P区的电子,在PN结附近数微米内分别与N区的电子和P区的空穴复合,产生自发辐射的荧光。
添加设备树 在设备树 arch/arm64/boot/dts/rockchip/rk3399pro-toybrick-prop-linux.dts 中添加 gpio-led{ status = "okay"; compatible = "gpio-led"; gpio-led1 = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; gpio-led2 = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; }; 编写驱动程序 设备节点 static const struct of_device_id of_gec_leder_match[] = { { .compatible = "gpio-led", }, //compatible 兼容属性名,需与设备树节点的属性一致 {}, }; static struct platform_driver gec3399_led_driver = { .driver = { .name ="gpio-led", .owner = THIS_MODULE, .of_match_table = of_gec_leder_match, //设备树设备匹配 }, .probe = gec3399_led_probe, //驱动探测 .remove = gec3399_led_remove, //驱动移除 }; 文件入口函数 static int gec3399_led_probe(struct platform_device *pdev) { int ret; struct device_node *led_node = pdev->dev.of_node; //第一步:获取GPIO引脚号 gpio_led1 = of_get_named_gpio(led_node,"gpio-led1", 0); //从设备树获取GPIO号 if (!gpio_is_valid(gpio_led1)) { printk("gpio-led1: %d is invalidn",gpio_led1); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led1 = %dn",gpio_led1); gpio_led2 = of_get_named_gpio(led_node,"gpio-led2", 0); //从设备树获取GPIO号 if (!gpio_is_valid(gpio_led2)) { printk("gpio-led2: %d is invalidn",gpio_led2); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led2 = %dn",gpio_led2); //第二步:申请GPIO引脚 gpio_free(gpio_led1); ret = gpio_request(gpio_led1,"GPIO_LED1"); //申请gpio_led引脚为GPIO模式 if(ret < 0){ printk("gpio_request gpio = GPIO_LED1 errorn"); goto err_get_gpio1; } gpio_free(gpio_led2); ret = gpio_request(gpio_led2,"GPIO_LED2"); //申请gpio_led引脚为GPIO模式 if(ret < 0){ printk("gpio_request gpio = GPIO_LED1 errorn"); goto err_get_gpio2; } //第三步:设置LED引脚的初始化电平 ret = gpio_direction_output(gpio_led1,0); //初始化LED1为关闭状态 if(ret < 0){ printk("gpio direction input gpio = LED1 errorn"); goto err_gpio_direction; } ret = gpio_direction_output(gpio_led2,0); //初始化LED2为关闭状态 if(ret < 0){ printk("gpio direction input gpio = LED2 errorn"); goto err_gpio_direction; } //第四步:通过杂项设备注册LED灯 ret = misc_register(&gec3399_led_misc); //注册字符设备 if(ret < 0){ printk("misc register errorn"); goto err_misc_register; } printk( KERN_ALERT "led dirve install succeen"); return 0; err_misc_register: err_gpio_direction: gpio_free(gpio_led2); err_get_gpio2: gpio_free(gpio_led1); err_get_gpio1: return ret; } 杂项设备 static struct miscdevice gec3399_led_misc = { .minor = MISC_DYNAMIC_MINOR, .fops = &gec3399_led_fops, .name = "led_drv", }; //混杂设备结构体定义和初始化 文件操作集 static struct miscdevice gec3399_led_misc = { .minor = MISC_DYNAMIC_MINOR, .fops = &gec3399_led_fops, .name = "led_drv", }; //混杂设备结构体定义和初始化 控制函数 static long gec3399_led_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case LED_ON: gpio_set_value(gpio_led1,1); gpio_set_value(gpio_led2,1); break; case LED_OFF: gpio_set_value(gpio_led1,0); gpio_set_value(gpio_led2,0); break; } return 0; } 完整驱动代码 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LED_ON _IO('B',0) #define LED_OFF _IO('B',1) int gpio_led1,gpio_led2; static long gec3399_led_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case LED_ON: gpio_set_value(gpio_led1,1); gpio_set_value(gpio_led2,1); break; case LED_OFF: gpio_set_value(gpio_led1,0); gpio_set_value(gpio_led2,0); break; } return 0; } static int gec3399_led_release(struct inode *inode, struct file *file) { gpio_set_value(gpio_led1,0); //应用程序退出时,关闭蜂鸣器 gpio_set_value(gpio_led2,0); //应用程序退出时,关闭蜂鸣器 return 0; } static const struct file_operations gec3399_led_fops = { .owner = THIS_MODULE, .unlocked_ioctl = gec3399_led_ioctl, .release = gec3399_led_release, }; //文件操作集结构体 static struct miscdevice gec3399_led_misc = { .minor = MISC_DYNAMIC_MINOR, .fops = &gec3399_led_fops, .name = "led_drv", }; //混杂设备结构体定义和初始化 static int gec3399_led_probe(struct platform_device *pdev) { int ret; struct device_node *led_node = pdev->dev.of_node; //enum of_gpio_flags flag; printk(KERN_ALERT"gpio-led math succeen"); gpio_led1 = of_get_named_gpio(led_node,"gpio-led1", 0); //从设备树获取GPIO号 if (!gpio_is_valid(gpio_led1)) { printk("gpio-led1: %d is invalidn",gpio_led1); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led1 = %dn",gpio_led1); gpio_led2 = of_get_named_gpio(led_node,"gpio-led2", 0); //从设备树获取GPIO号 if (!gpio_is_valid(gpio_led2)) { printk("gpio-led2: %d is invalidn",gpio_led2); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led2 = %dn",gpio_led2); gpio_free(gpio_led1); ret = gpio_request(gpio_led1,"GPIO_LED1"); //申请gpio_led引脚为GPIO模式 if(ret < 0){ printk("gpio_request gpio = GPIO_LED1 errorn"); goto err_get_gpio1; } gpio_free(gpio_led2); ret = gpio_request(gpio_led2,"GPIO_LED2"); //申请gpio_led引脚为GPIO模式 if(ret < 0){ printk("gpio_request gpio = GPIO_LED1 errorn"); goto err_get_gpio2; } ret = gpio_direction_output(gpio_led1,0); //初始化LED1为关闭状态 if(ret < 0){ printk("gpio direction input gpio = ak8963c_DYDR errorn"); goto err_gpio_direction; } ret = gpio_direction_output(gpio_led2,0); //初始化LED2为关闭状态 if(ret < 0){ printk("gpio direction input gpio = ak8963c_DYDR errorn"); goto err_gpio_direction; } ret = misc_register(&gec3399_led_misc); //注册字符设备 if(ret < 0){ printk("misc register errorn"); goto err_misc_register; } printk( KERN_ALERT "led dirve install succeen"); return 0; err_misc_register: err_gpio_direction: gpio_free(gpio_led2); err_get_gpio2: gpio_free(gpio_led1); err_get_gpio1: return ret; } static int gec3399_led_remove(struct platform_device *pdev) { gpio_free(gpio_led1); gpio_free(gpio_led2); misc_deregister(&gec3399_led_misc); printk(KERN_ALERT "led dirve rmove succeen"); return 0; } static const struct of_device_id of_gec_leder_match[] = { { .compatible = "gpio-led", }, //compatible 兼容属性名,需与设备树节点的属性一致 {}, }; static struct platform_driver gec3399_led_driver = { .driver = { .name ="gpio-led", .owner = THIS_MODULE, .of_match_table = of_gec_leder_match, //设备树设备匹配 }, .probe = gec3399_led_probe, //驱动探测 .remove = gec3399_led_remove, //驱动移除 }; module_platform_driver(gec3399_led_driver); //module的描述,不是必需的。#modinfo led_drv.ko MODULE_DESCRIPTION("led driver for RK3399"); MODULE_LICENSE("GPL"); //符合GPL协议 MODULE_VERSION("V1.0"); 测试代码 测试代码主要实现LED的闪烁功能 #include #include #include #include #include #include #include //宏定义 #define LED_ON _IO('B',0) #define LED_OFF _IO('B',1) int main(void) { int fd_led; int ret; //第一步:打开设备节点 fd_led = open("/dev/led_drv", O_WRONLY); if(fd_led < 0) { perror("open led driver"); return -1; } while(1) { //第二步:点亮LED灯 ret = ioctl(fd_led,LED_ON); if(ret < 0) perror("write led driver "); sleep(1); //第三步:关闭LED灯 ret = ioctl(fd_led,LED_OFF); if(ret < 0 ) perror("write led driver "); sleep(1); } //第四步:关闭设备节点 close(fd_led); return 0; } Makefile文件 obj-m += led_drv.o KERNELDIR:=/file/RK3399Pro/rk3399pro_git_repo/kernel PWD:=$(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules test: aarch64-linux-gnu-gcc led_test.c -o led_test clean: rm -rf *.o *.order .*.cmd *.ko *.mod.c *.symvers *.tmp_versions led_test 测试步骤 编译源码 在ubuntu中输入: make 得到驱动目标文件led_drv.ko 输入: make test 得到测试目标文件:led_test 加载驱动 在开发板命令终端输入: insmod led_drv.ko 执行测试程序 在开发板命令终端输入: chmod 777 led_test./led_test 实验现象 实现LED的闪烁 |
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
谁有3566+电池+POE充电的方案,有个项目需要用该功能的主板
1265 浏览 0 评论
RK3588的GMAC0与PHY的参考时钟电平匹配问题??????
6401 浏览 1 评论
请问各位大佬,如何解决,瑞芯微 RV1126B 使用 mpp 自带工具 调试时,内核直接报错崩溃!
2076 浏览 0 评论
使用rk3568开发板,核0\\1\\3运行linux,核2运行hal,在核0中怎么关闭核2
2616 浏览 0 评论
2615 浏览 0 评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-12 06:05 , Processed in 0.893909 second(s), Total 72, Slave 55 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
2308