完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
原理图
发光二极管与普通二极管一样是由一个PN结组成,也具有单向导电性。当给发光二极管加上正向电压后,从P区注入到N区的空穴和由N区注入到P区的电子,在PN结附近数微米内分别与N区的电子和P区的空穴复合,产生自发辐射的荧光。 问题1:如何判断正负极? 尺寸大的LED 在极片引脚附近做有一些标记,如切角、涂色、或引脚大小不一样,一般有标志的、引脚小的、短的 一边是阴极(即负极),尺寸小的0805、0603封装的在底部有“T”字形 或 倒三角形符号“T”字一横的一边是正极; 三角形符号的“边”靠近的极性正,“角”靠近的是负极。 添加设备树 在设备树 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 invalid ",gpio_led1); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led1 = %d ",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 invalid ",gpio_led2); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led2 = %d ",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 error "); 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 error "); goto err_get_gpio2; } //第三步:设置LED引脚的初始化电平 ret = gpio_direction_output(gpio_led1,0); //初始化LED1为关闭状态 if(ret < 0){ printk("gpio direction input gpio = LED1 error "); goto err_gpio_direction; } ret = gpio_direction_output(gpio_led2,0); //初始化LED2为关闭状态 if(ret < 0){ printk("gpio direction input gpio = LED2 error "); goto err_gpio_direction; } //第四步:通过杂项设备注册LED灯 ret = misc_register(&gec3399_led_misc); //注册字符设备 if(ret < 0){ printk("misc register error "); goto err_misc_register; } printk( KERN_ALERT "led dirve install succee "); 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 succee "); gpio_led1 = of_get_named_gpio(led_node,"gpio-led1", 0); //从设备树获取GPIO号 if (!gpio_is_valid(gpio_led1)) { printk("gpio-led1: %d is invalid ",gpio_led1); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led1 = %d ",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 invalid ",gpio_led2); ret = -ENODEV; goto err_get_gpio1; } printk("gpio-led2 = %d ",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 error "); 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 error "); goto err_get_gpio2; } ret = gpio_direction_output(gpio_led1,0); //初始化LED1为关闭状态 if(ret < 0){ printk("gpio direction input gpio = ak8963c_DYDR error "); goto err_gpio_direction; } ret = gpio_direction_output(gpio_led2,0); //初始化LED2为关闭状态 if(ret < 0){ printk("gpio direction input gpio = ak8963c_DYDR error "); goto err_gpio_direction; } ret = misc_register(&gec3399_led_misc); //注册字符设备 if(ret < 0){ printk("misc register error "); goto err_misc_register; } printk( KERN_ALERT "led dirve install succee "); 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 succee "); 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的闪烁 原作者:冷静的领头狼 |
|
相关推荐
1个回答
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
rk1126实现BT601输入,输入不带IIC接口的驱动程序
1196 浏览 0 评论
1203 浏览 1 评论
2296 浏览 3 评论
RK3568 Android11让系统ntp校准时间生效,需要设置些什么
3058 浏览 1 评论
5061 浏览 2 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-17 09:16 , Processed in 0.793803 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号