完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 Stark扬 于 2018-10-31 15:11 编辑
hx711编写的linux字符设备驱动,读不了数据,使用的是手册上的例程修改的。不连数据线的时候,时钟脉冲输出正常25个脉冲。一旦连接上数据线,cpu输出的时钟脉冲数量就不对了。 补充内容 (2018-10-31 15:30): /*头文件部分*/ #include "ym_weight.h" /*设备号*/ static dev_t dev_no; /*设备文件指针*/ static struct ym_weight_dev * weight_dev = NULL; /*设备类结对象,用于自动生成设备节点*/ static struct class *led_class = NULL; static int weight_open(struct inode * node, struct file * file) { printk("This is open!n"); return 0; } /** 函数名:ReadCount 功能描述:读取硬件数据 返回值:读取成功返回读取数据 **/ unsigned int ReadCount(void) { unsigned int Count = 0; unsigned char i; preempt_disable(); //gpio_set_value(SPICL, 0); while(gpio_get_value(SPIIN)); udelay(2); //local_irq_disable(); for (i=0;i<24;i++) { gpio_set_value(SPICL, 1); Count=Count<<1; udelay(2); gpio_set_value(SPICL, 0); if(gpio_get_value(SPIIN)) Count++; udelay(2); //printk(KERN_ALERT"weight is %un",Count); } gpio_set_value(SPICL, 1); udelay(2); //printk(KERN_ALERT"weight is %un",Count); Count=Count^0x800000; gpio_set_value(SPICL, 0); DELAY; //local_irq_enable(); preempt_enable(); return(Count); } /** 函数名:weight_read 功能描述:读取数据实现 返回值:读取成功返回读取数据 **/ static ssize_t weight_read(struct file *file,char __user *buf,size_t count,loff_t *pos) { unsigned int weight = 0; weight = ReadCount(); if (copy_to_user(buf,(void *)(&weight), sizeof(int))) return -EFAULT; //拷贝失败 return 0; } /*设备文件操作集--函数指针集*/ struct file_operations weight_fops = { .owner = THIS_MODULE, //该文件操作集应用于当前驱动模块 .open = weight_open, .read = weight_read, .llseek = weight_llseek, }; static int dev_register(void) { /*1. 将文件操作集和设备文件绑定*/ cdev_init(&(weight_dev->dev), &weight_fops); /*2. 单独初始化owner成员*/ weight_dev->dev.owner = THIS_MODULE; /*3. 根据设备号和设备名注册设备到内核*/ if (cdev_add(&(weight_dev->dev), dev_no, DEV_NUM) < 0) { printk(KERN_ALERT "dev_register failed!n"); return -1;; //注册失败返回-1 } /*4. 设备注册成功返回0*/ return 0; } static int weight_hardware_init(void) { int ret = -1; ret = gpio_request(SPICL,"SPICL"); if (ret !=0) printk(KERN_ALERT"SPICL request fail!n"); ret = gpio_request(SPIIN,"SPIIN"); if (ret !=0) printk(KERN_ALERT"SPIIN request fail!n"); ret = gpio_direction_output(SPICL,0); if (ret !=0) printk(KERN_ALERT"SPICL set fail!n"); ret = gpio_direction_input(SPIIN); if (ret !=0) printk(KERN_ALERT"SPIIN set fail!n"); return ret; } static int ym_weight_device_create(void) { int ret = -1; /*用于和class结构体指针联合自动创建设备文件*/ struct device *tmp = NULL; /*1. 创建设备类对象*/ led_class = class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(led_class)) { //检测是否创建成功 ret = PTR_ERR(led_class); printk(KERN_ALERT"Failed to create led class.n"); } tmp = device_create(led_class, NULL, dev_no, NULL, "%s", FILE_NAME); if (IS_ERR(tmp)) { ret = PTR_ERR(tmp); printk(KERN_ALERT"Failed to create led device.n"); goto destroy_class; } dev_set_drvdata(tmp, (void *) weight_dev); return 0; destroy_class: class_destroy(led_class); cdev_del(&(weight_dev->dev)); return ret; } /** 函数名:ym_weight_init 功能描述:驱动加载函数,申请资源 返回值:加载成功返回0 **/ static int __init ym_weight_init(void) { /*用于检测加载过程中各函数的执行结果*/ int ret = -1; /*1. 动态申请设备号*/ ret = alloc_chrdev_region(&dev_no, 0, DEV_NUM, DEV_NAME); if (ret < 0) { printk(KERN_ALERT"Alloc_chrdev_region failed!n"); goto fail; } /*2. 为设备文件分配一块内存空间并将该空间清零*/ weight_dev = kzalloc(sizeof(struct ym_weight_dev), GFP_KERNEL); if (weight_dev == NULL) { ret = -ENOMEM; printk(KERN_ALERT"kmalloc failed!n"); goto unregister; } /*3. 注册设备*/ ret = dev_register(); if (ret < 0) { printk(KERN_ALERT"cdev_add failed!n"); goto clean_up; } /*4. 硬件相关的初始化*/ ret = weight_hardware_init(); if (ret < 0) { printk(KERN_ALERT"led_hardware_init failed!n"); goto clean_up; } /*5. 自动创建设备文件节点*/ ret = ym_weight_device_create(); if (ret < 0) { printk(KERN_ALERT"device_create failed!n"); goto clean_up; } /*6. 驱动成功加载返回0*/ printk(KERN_ALERT"Succeed to initialize led device.n"); return 0; /*设备注册失败,释放之前申请的资源--从释放为设备文件申请的内存空间开始(此时设备文件已成功申请到内存空间)*/ clean_up: kfree(weight_dev); /*为设备文件申请内存失败,释放之前申请的资源--从释放设备号开始(此时设备号已经成功申请)*/ unregister: unregister_chrdev_region(dev_no, DEV_NUM); /*设备号动态申请失败,终止驱动初始化*/ fail: return ret; } static void __exit ym_weight_exit(void) { /*1. 释放自动创建设备文件节点申请的资源*/ if (led_class) { device_destroy(led_class, dev_no); //释放设备文件 class_destroy(led_class); //释放设备类对象 } /*2. 释放GPIO寄存器映射的地址*/ //iounmap(led_dat); //iounmap(led_con); gpio_free(SPICL); gpio_free(SPIIN); /*3. 释放注册设备文件申请的资源*/ if (weight_dev) { cdev_del(&(weight_dev->dev)); //注销内核中的设备文件 kfree(weight_dev); //释放为设备文件分配的内存空间 } /*4. 注销设备号*/ unregister_chrdev_region(dev_no, DEV_NUM); } module_init(ym_weight_init); module_exit(ym_weight_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tom Wang"); MODULE_DESCRIPTION("driver of weight"); |
|
相关推荐
4个回答
|
|
解决了
|
|
|
|
挺好的
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1146 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程介绍之烧写所需镜像
1225 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程之烧写方法
675 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-内核编译之初次编译
1019 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-内核源代码的目录结构和文件说明
937 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 08:26 , Processed in 0.900482 second(s), Total 104, Slave 79 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号