A40i使用笔记:第一个实物驱动HX711(传统方式,非设备树)

一、前言

又是一个熬夜的夜晚,已经不知道连续多少天没有正常休息了,每天早期都要下定决心晚上早点睡觉,可是一到了晚上就是来思路学习或者干点什么的冲动,赶紧写完睡觉。

这是我第一个基于全志a40i平台写的Linux驱动,可能不是特别标准,也未使用到设备树,不是特别完美,万事开头难,开了头后续我会继续更新A40i使用笔记系列的。

二、环境

全志A40i

linux3.10

三、正文

本文主要就是记录一下代码把,函数的详细描述我也就不述说了,网上大把教学视频,都比较专业。

为什么一定要写底层驱动呢,主要原因是,再涉及到界面开发的项目,已经使用到qt界面开发,就相当于转战linux平台,不再去使用stm32做界面开发,也不是说32就不用了,在无界面开发或者小屏oled或者点阵屏,一些控制类还是使用的到的。既然使用了Linux做上位机,那么对应就有一些底层的ic需要驱动读取信息,这里我就用到了hx711读取重量,但是还不想附加一个32再采用串口去通讯,主要就是不想多余占用板子空间,因为linux本身就可以驱动ic,为什么就只因为我不会驱动开发就放弃而去使用32呢,所以就学习,到目前位置差不多一个礼拜,看视频+实际敲代码验证,也算是搞出来了基础框架了。

下面正文,hx711驱动使用一个c文件,还有一个应用层文件

驱动文件核心代码如下:

//入口:insmod
static int hx711_init(void)
{
	int err;
    int i;
	printk(KERN_INFO "hx711_drv_init\n");
	//注册字符设备
	major = register_chrdev(0, "hx711_drv", &hx711_drv);  //参数1:0动态分配设备号,参数2:设备名称,参数3:文件操作结构体//返回申请的设备号

	//创建class并将class注册到内核中
	hx711_class = class_create(THIS_MODULE, "hx711_class");//参数1:owner,参数2:class名称//返回class结构体指针
	err = PTR_ERR(hx711_class);
	if (IS_ERR(hx711_class)) { 
		printk(KERN_ERR "hx711_class err\n");
		//卸载注册的设备
 		unregister_chrdev(major, "hx711_drv");//参数1:分配的设备号,参数2:设备名称
		return -1;
	}
	//创建设备文件,通知用户在“/dev/”目录下创件名字为hx711_class-x的设备文件
	device_create(hx711_class, NULL, MKDEV(major, 0), NULL, "hx711_class-0", 0); //参数1:class结构体指针,参数3:设备号,参数5:节点名称,参数6:次设备号
	

	//初始化io函数
    for(i = 0; i < ARRAY_SIZE(led_info); i++) {//遍历led_info结构体
        int result = gpio_request(led_info[i].gpio,led_info[i].name);//先向内核申请GPIO硬件资源;
		if(result!=0){//判断申请的GPIO资源是否成功,失败返回提示信息
			printk(KERN_ERR "GPIO%d has used...led init err!\n",led_info[i].gpio);//打印错误信息
			return -1;
		}		
    }
	gpio_direction_output(led_info[0].gpio, 0);//设置 GPIO 为输出功能,输出0  //sclk
	gpio_direction_input(led_info[1].gpio);//设置 GPIO 为输人功能       //sda	

	printk(KERN_INFO "hx711_drv_init ok...\n");
    return 0;
}

//出口:rmmod
static void hx711_exit(void)
{
    int i;	
	//释放gpio
    for(i = 0; i < ARRAY_SIZE(led_info); i++) {//遍历led_info结构体
        gpio_free(led_info[i].gpio);//释放GPIO硬件资源
    } 

	//删除设备类
	device_destroy(hx711_class, MKDEV(major, 0));//参数1:class结构体指针,参数2:设备号
	//注销class
	class_destroy(hx711_class);//参数:class结构体指针
	
	//卸载注册的设备
	unregister_chrdev(major, "hx711_drv");//参数1:分配的设备号,参数2:设备名称
	
	printk(KERN_INFO "hx711_drv_exit\n");
}

unsigned long HX711_Read(void)  //读取711读到的数据
{
    unsigned long val; 
    unsigned char i; 	
    HX711_SCL1_L(); 
    val = 0;
    while(HX711_SDA1_IN());
    udelay(1); 
    for(i=0;i<24;i++){ 
		HX711_SCL1_H(); 
		val=val<<1; 
		udelay(1);
		HX711_SCL1_L(); 
		if(HX711_SDA1_IN()) 
		    val++; 
		udelay(1);
    } 
    HX711_SCL1_H(); 
    val = val^0x800000; 
    udelay(1);
    HX711_SCL1_L(); 
    udelay(1);
	
    return val; 	
}


int hx711_buffer=0;//定义hx711_buffer来接受hx711read读取的信息
int weight_maopi=0;//毛皮重量
int weight_shiwu=0;//实物重量
//获取毛皮重量,并记录
int Get_Maopi(void)
{
    hx711_buffer=HX711_Read();
    weight_maopi=hx711_buffer;
    return weight_maopi;
}
//获取净重量,并记录
int Get_Weight(void)
{
    hx711_buffer=HX711_Read();
	if(hx711_buffer>weight_maopi)
		weight_shiwu=hx711_buffer-weight_maopi;
//    weight_shiwu=weight_shiwu/100;
//    weight_shiwu=(unsigned int)((float)weight_shiwu/4.30+0.05);//每一个传感器需要矫正4.30这个除数。当发现测试出来的重量偏大时,增加该数值。如果测试出来的重量偏小时,减小改数值.该数值一般在4.0-5.0之间。因传感器线性斜率不同而定。			
    return weight_shiwu;
}

应用文件代码如下:

char *hx711_PATH = "/dev/hx711_class-0";
int main(int argc, char **argv)
{
	int fd;
	int weight_int;
	double weight_double;
	

	/* 打开文件 */
	fd = open(hx711_PATH, O_RDWR);
	if (fd == -1){
		printf("can not open file %s\n", hx711_PATH);
		return -1;
	}

	/* 读文件 */
	weight_int = 1;
	read(fd, &weight_int, sizeof(int));//读取毛皮
	printf("maopi = %d\r\n",weight_int);
	while(1){
		usleep(100000);//延时100ms
		weight_int = 2;
		read(fd, &weight_int, sizeof(int));//读取净重
		weight_double = weight_int;
		weight_double = weight_double/100;
		weight_double=(unsigned int)((float)weight_double/4.30+0.05);//每一个传感器需要矫正4.30这个除数。当发现测试出来的重量偏大时,增加该数值。如果测试出来的重量偏小时,减小改数值.该数值一般在4.0-5.0之间。因传感器线性斜率不同而定。			
		printf("weight = %.4fg\r\n",weight_double);
	}
	close(fd);
	return 0;
}

再前文介绍了如何编译驱动文件以及交叉编译应用文件,最后编译完毕生成ko文件和可执行程序文件,如下所示,资源里下载就是

 使用到了如下几个命令:

  • lsmod查看已经加载的内核模块
  • insmod加载内核模块
  • rmmod卸载内核模块
  • dmesg查看日志信息
  • dmesg -c清除日志信息
  • ls  /dev查看设备节点
  • cat /proc/devices查看设备的设备号

最后测试效果如下所示:

 

四、结语

速战速决,下一个驱动,准备驱动AD7606,搞起~

猜你喜欢

转载自blog.csdn.net/qq_37603131/article/details/120898243