本帖最后由 Stark扬 于 2018-10-31 15:11 编辑
hx711编写的linux字符设备驱动,读不了数据,使用的是手册上的例程修改的。不连数据线的时候,时钟脉冲输出正常25个脉冲。一旦连接上数据线,cpu输出的时钟脉冲数量就不对了。
补充内容 (2018-10-31 15:30):
/*头文件部分*/
#include "ym_weight.h"
/*设备号*/
sta
tic 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!
");
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 %u
",Count);
}
gpio_set_value(SPICL, 1);
udelay(2);
//printk(KERN_ALERT"weight is %u
",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!
");
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!
");
ret = gpio_request(SPIIN,"SPIIN");
if (ret !=0)
printk(KERN_ALERT"SPIIN request fail!
");
ret = gpio_direction_output(SPICL,0);
if (ret !=0)
printk(KERN_ALERT"SPICL set fail!
");
ret = gpio_direction_input(SPIIN);
if (ret !=0)
printk(KERN_ALERT"SPIIN set fail!
");
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.
");
}
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.
");
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!
");
goto fail;
}
/*2. 为设备文件分配一块内存空间并将该空间清零*/
weight_dev = kzalloc(sizeof(struct ym_weight_dev), GFP_KERNEL);
if (weight_dev == NULL) {
ret = -ENOMEM;
printk(KERN_ALERT"kmalloc failed!
");
goto unregister;
}
/*3. 注册设备*/
ret = dev_register();
if (ret < 0) {
printk(KERN_ALERT"cdev_add failed!
");
goto clean_up;
}
/*4. 硬件相关的初始化*/
ret = weight_hardware_init();
if (ret < 0) {
printk(KERN_ALERT"led_hardware_init failed!
");
goto clean_up;
}
/*5. 自动创建设备文件节点*/
ret = ym_weight_device_create();
if (ret < 0) {
printk(KERN_ALERT"device_create failed!
");
goto clean_up;
}
/*6. 驱动成功加载返回0*/
printk(KERN_ALERT"Succeed to initialize led device.
");
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");
一周热门 更多>