Linux:MLX90614驱动

设备树

1、设备树IO修改

在这里插入图片描述
pinctrl_i2c1 就是 I2C1 的 IO 节点,这里将 UART4_TXD 和 UART4_RXD 这两个 IO 分别
复用为 I2C1_SCL 和 I2C1_SDA,电气属性都设置为 0x4001b8b0。

2、在 i2c1 节点追加子节点

在这里插入图片描述

设置完成后,拷贝设备树到linux内核
sudo cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /home/sjh/linux/tftpboot/ -f

3、查看设备树是否修改成功

重启开发板
/sys/bus/i2c/devices 目录下存放着所有 I2C 设备,如果设备树修改正确的话,会在
/sys/bus/i2c/devices 目录下看到一个名为“0-005a”的子目录
在这里插入图片描述
0-005a 就是MLX90614设备目录
在这里插入图片描述

ls /sys/bus/platform/devices/  查看设备名
ls /sys/bus/platform/drivers/  查看驱动名

驱动程序编写

驱动代码

#include <linux/types.h>

#include <linux/kernel.h>

#include <linux/delay.h>

#include <linux/ide.h>

#include <linux/init.h>

#include <linux/module.h>

#include <linux/errno.h>

#include <linux/gpio.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <linux/of_gpio.h>

#include <linux/semaphore.h>

#include <linux/timer.h>

#include <linux/i2c.h>

#include <asm/mach/map.h>

#include <asm/uaccess.h>

#include <asm/io.h>

#include "MLX90614reg.h"



#define MLX90614_CNT 	1

#define MLX90614_NAME	"MLX90614"



struct	MLX90614_dev{

	dev_t devid; 						/* 设备号 	 */

	struct cdev cdev;				/* cdev 	*/

	struct class *class;		/* 类 		*/

	struct device *device;	/* 设备 	 */

	struct device_node *nd;	/* 设备节点 */

	int major;							/* 主设备号 */

	void *private_data;			/* 私有数据 */

	float temp;							/* 温度 */

	unsigned int  t1;

};



static struct MLX90614_dev MLX90614dev;

//============================================================================//

static const unsigned char crc_table[] = {

    0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,

    0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,

    0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,

    0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,

    0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,

    0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,

    0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,

    0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,

    0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,

    0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,

    0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,

    0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,

    0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,

    0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,

    0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,

    0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,

    0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,

    0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,

    0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,

    0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,

    0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,

    0xfa, 0xfd, 0xf4, 0xf3

};



unsigned char CRC8_Calc (unsigned char *p, unsigned char len) 

{

    unsigned int i;

    unsigned int crc = 0x0;



    while (len--) {

            i = (crc ^ *p++) & 0xFF;

            crc = (crc_table[i] ^ (crc << 8)) & 0xFF;

    }



    return (crc & 0xFF);

}

static int MLX90614_read_regs(struct MLX90614_dev *dev,u8 reg,void *val,int len)

{

		struct i2c_client *client = (struct i2c_client *)dev->private_data;

	int ret;

		struct i2c_msg msg[2];



		msg[0].addr = (client->addr)<<1;

		msg[0].flags = 0;

		msg[0].buf = &reg;

		msg[0].len = 1;  



		msg[1].addr = (client->addr)<<1;

		msg[1].flags = I2C_M_RD;

		msg[1].buf = val;

		msg[1].len = len;



	ret = i2c_transfer(client->adapter, msg, 2);

	if(ret == 2) {

		ret = 0;

	} else {

		printk("i2c rd failed=%d reg=%06x len=%d\n",ret, reg, len);

		ret = -EREMOTEIO;

	}

	return ret;

}

static unsigned char * MLX90614_read_reg(struct MLX90614_dev *dev, u8 reg)

{

	u8 data[3];

	u8 *p=NULL;



	// MLX90614_read_regs(dev, reg, data, 3);

	// p = data;

	// return p;



#if 0

	struct i2c_client *client = (struct i2c_client *)dev->private_data;

	return i2c_smbus_read_byte_data(client, reg);

#endif

	/*连续读函数*/

	struct i2c_client *client = (struct i2c_client *)dev->private_data;

 	i2c_smbus_read_i2c_block_data(client,reg,3,data);

	p = data;

	return p;



}

void MLX90614_readdata(struct MLX90614_dev *dev)

{

    unsigned char ValBuf[6] = {0};

    unsigned char prcRegVal = 0;

	unsigned char *save;

    ValBuf[0] = MLX90614_ADDR << 1;

    ValBuf[1] = MLX90614_TOBJ1;

    ValBuf[2] = (MLX90614_ADDR << 1) | 0x01;

	save = MLX90614_read_reg(dev, MLX90614_TOBJ1);	

	// save[0] = MLX90614_read_reg(dev, MLX90614_TOBJ1);	

	// save[1] = MLX90614_read_reg(dev, MLX90614_TOBJ1);	

	// save[2] = MLX90614_read_reg(dev, MLX90614_TOBJ1);	

	ValBuf[3] = save[0];

	ValBuf[4] = save[1];

	ValBuf[5] = save[2];

	//printk("save : %x %x %x \r\n",save[0],save[1],save[2]);

    prcRegVal = CRC8_Calc(ValBuf,5);

    if(prcRegVal == ValBuf[5])

        dev->t1 = (ValBuf[4] << 8) + ValBuf[3];

	//printk("dev->t1 = %d\r\n",dev->t1);

}

static int MLX90614_open(struct inode *inode,struct file *filp)

{

	filp->private_data = &MLX90614dev;

	printk("MLX90614_open\r\n");

	return 0;

}

static ssize_t MLX90614_read(struct file *filp,char __user *buf,size_t cnt,loff_t *off)

{

	unsigned int test;

	long err = 0;

	struct MLX90614_dev *dev = (struct MLX90614_dev *)filp->private_data;



	MLX90614_readdata(dev);

	test  = dev->t1;

	err = copy_to_user(buf,&test,sizeof(test));

	return 0;

}

static int MLX90614_release(struct inode *inode,struct file *filp)

{

	printk("MLX90614_release\r\n");

	return 0;

}



static const struct file_operations MLX90614_ops = {

	.owner = THIS_MODULE,

	.open  = MLX90614_open,

	.read  = MLX90614_read,

	.release = MLX90614_release,

};



static int MLX90614_probe(struct i2c_client *client,const struct i2c_device_id *id)

{

	printk("MLX90614_probe\r\n");

	/*构建设备号*/

	if(MLX90614dev.major){

		MLX90614dev.devid = MKDEV(MLX90614dev.major,0);

		register_chrdev_region(MLX90614dev.devid,MLX90614_CNT,MLX90614_NAME);

	}else

	{

		alloc_chrdev_region(&MLX90614dev.devid,0,MLX90614_CNT,MLX90614_NAME);

		MLX90614dev.major = MAJOR(MLX90614dev.devid);

	}

	/*注册设备*/

	cdev_init(&MLX90614dev.cdev,&MLX90614_ops);

	cdev_add(&MLX90614dev.cdev,MLX90614dev.devid,MLX90614_CNT);



	/*创建类*/

	MLX90614dev.class = class_create(THIS_MODULE,MLX90614_NAME);

	if(IS_ERR(MLX90614dev.class)){

		return PTR_ERR(MLX90614dev.class);

	}

	/*创建设备*/

	MLX90614dev.device = device_create(MLX90614dev.class,NULL,MLX90614dev.devid,NULL,MLX90614_NAME);

	if(IS_ERR(MLX90614dev.device)){

		return PTR_ERR(MLX90614dev.device);

	}

	MLX90614dev.private_data =client;

	return 0;

}

static int MLX90614_remove(struct i2c_client *client)

{

	printk("MLX90614_remove\r\n");

	/* 删除设备 */

	cdev_del(&MLX90614dev.cdev);

	unregister_chrdev_region(MLX90614dev.devid, MLX90614_CNT);



	/* 注销掉类和设备 */

	device_destroy(MLX90614dev.class, MLX90614dev.devid);

	class_destroy(MLX90614dev.class);

	return 0;

}

/* 传统匹配方式ID列表 */

static const struct i2c_device_id MLX90614_id[] = {

	{"alientek,MLX90614", 0},  

	{}

};

static const struct of_device_id MLX90614_of_math[]={

	{ .compatible = "alientek,MLX90614"},

	{}

};

/*iac驱动结构体*/

static struct i2c_driver MLX90614_driver = {

	.probe =	MLX90614_probe,

	.remove = MLX90614_remove,

	.driver = {

				.owner = THIS_MODULE,

				.name = "MLX90614",

				.of_match_table = MLX90614_of_math,

				},

	.id_table = MLX90614_id,

};

/*驱动入口函数*/

static int __init MLX90614_init(void)

{

	int ret = 0;

	ret = i2c_add_driver(&MLX90614_driver);

	return ret;

}

/*驱动出口函数*/

static void __exit MLX90614_exit(void)

{	

	i2c_del_driver(&MLX90614_driver);

}

module_init(MLX90614_init);

module_exit(MLX90614_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("sjh");


应用代码

#include "stdio.h"

#include "unistd.h"

#include "sys/types.h"

#include "sys/stat.h"

#include "sys/ioctl.h"

#include "fcntl.h"

#include "stdlib.h"

#include "string.h"

#include <poll.h>

#include <sys/select.h>

#include <sys/time.h>

#include <signal.h>

#include <fcntl.h>



/*

 * @description		: main主程序

 * @param - argc 	: argv数组元素个数

 * @param - argv 	: 具体参数

 * @return 			: 0 成功;其他 失败

 */

int main(int argc, char *argv[])

{

	int fd;

	char *filename;

	int ret = 0;

	unsigned int test;

	float read_dat;

	if (argc != 2) {

		printf("Error Usage!\r\n");

		return -1;

	}



	filename = argv[1];

	fd = open(filename, O_RDWR);

	if(fd < 0) {

		printf("can't open file %s\r\n", filename);

		return -1;

	}

		printf("Run!\r\n");

	while (1) {

		ret = read(fd, &test, sizeof(test));

		if(ret == 0) { 			/* 数据读取成功 */

			read_dat = (test * 0.02) - 273.15;;

			printf("Temp = %.2f摄氏度\r\n",read_dat);

		}

		usleep(200000); /*100ms */

	}

	close(fd);	/* 关闭文件 */	

	return 0;

}




结果截图
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值