完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
本来想做的是Android APP方向的工作,结果稀里糊涂的就干起了驱动。长话短说,作为人生中的第一个驱动,当灯终于亮起来的时候,还是蛮感动的,菜鸟真的很感动的说。
AW9523B分为2种工作模式,分别为GPIO模式和LED模式,由于刚开始的时候并不熟悉驱动编写,也根本没有仔细看数据手册的习惯(计算机专业的通病吗?),所以开始的道路真是曲折的不行。后来在带头大哥的英明指导下,终于发现了这茬,通过配置12H和13H寄存器 可以将P0_1-7和P1_1-7的工作模式切换,默认都是GPIO模式,若想将某个IO口配为LED模式,则将改为写0; 开始的时候由于不知道有LED模式这种东西的存在,傻乎乎的就开搞了,虽然结果不咋地,但是好歹是亮起来了。 首先,从probe函数开始: static int led_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct led_data *led; int err; led = kzalloc(sizeof(struct led_data), GFP_KERNEL); if (!led) { printk("[led]:alloc data failed.n"); err = -ENOMEM; goto exit_alloc_data_failed; } printk(" ++++value=%x ++++n ",client->addr); INIT_WORK(&led->work, led_work_func); INIT_DELAYED_WORK(&led->delaywork, led_delaywork_func); schedule_work(&led->work); led->client = client; i2c_set_clientdata(client, led); this_client = client; err = led_init_client(client); if (err < 0) { printk(KERN_ERR "led_probe: led_init_client failedn"); goto exit_request_gpio_irq_failed; } iomux_set(GPIO1_A6); mdelay(100); gpio_request(RK30_PIN1_PA6, "i2c_led-start"); mdelay(50); gpio_direction_output(RK30_PIN1_PA6, 1); printk("============in func:%s, LINE:%d ==============n", __func__, __LINE__); light_red_on(); // led_start(client, LED_RATE_32); led_device.parent = &client->dev; err = misc_register(&led_device); if (err < 0) { printk(KERN_ERR "led_probe: led_device register failedn"); return 0; } err = i2c0_led_sysfs_init(); if (err < 0) { printk(KERN_ERR "led_probe: i2c0_led sysfs init failedn"); goto exit_i2c0_led_sysfs_init_failed; } printk(KERN_INFO "led probe okn"); return 0; exit_i2c0_led_sysfs_init_failed: misc_deregister(&led_device); exit_request_gpio_irq_failed: kfree(led); exit_alloc_data_failed: ; return err; } 其实回过头再看,探测函数是非常的简单啊,无非就是申请内存,定义工作队列以及定义sys文件系统。 然后就是很重要的I2C读写函数了: static int led_rx_data(struct i2c_client *client, char *rxData, int length) { int ret = 0; char reg = rxData[0]; ret = i2c_master_reg8_recv(client, reg, rxData, length, LED_SPEED); printk("led_rx_data++++++++++++++++++++++n"); return (ret > 0)? 0 : ret; } static int led_tx8_data(struct i2c_client *client, char *txData, int length) { int ret = 0; char reg = txData[0]; printk("led_tx8_data++++++++++++++++++++++n"); ret = i2c_master_reg8_send(client, reg, &txData[1], length-1, LED_SPEED); printk("led_tx8_data++++++++++++++++++++++n"); return (ret > 0)? 0 : ret; } 创建sys节点: static int i2c0_led_sysfs_init(void) { int ret ; android_i2c0_led_kobj = kobject_create_and_add("android_i2c0_led", NULL); if (android_i2c0_led_kobj == NULL) { printk(KERN_ERR "i2c0_led_sysfs_init:" "subsystem_register failedn"); ret = -ENOMEM; goto err; } ret = sysfs_create_file(android_i2c0_led_kobj, &dev_attr_i2c0_led.attr); if (ret) { printk(KERN_ERR "i2c0_led_sysfs_init:" "sysfs_create_group failedn"); goto err4; } printk("i2c_led_sysfs_init ++++++++++++++++n"); return 0 ; err4: kobject_del(android_i2c0_led_kobj); err: return ret ; } 由于硬件工程师将18个灯分别挂到四条I2C总线上,所以本菜鸟很聪明的写了四个I2C设备驱动,简单粗暴。开始的时候怎么都亮不了,硬件工程师检测I2C也是有供电的,后来自己瞎琢磨半天,才发现原来 是由于复位脚没有拉高,所以I2C设备根本都没有工作起来,不管咋说,瞎整瞎整总算是也把灯给点亮了,算是涨姿势了,哈哈。 明天尝试下LED模式下的LED驱动编写,加油。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
458 浏览 0 评论
716 浏览 1 评论
620 浏览 1 评论
1850 浏览 1 评论
3099 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 02:44 , Processed in 0.836324 second(s), Total 70, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号