1.将IIC核心层和总线驱动层配置进内核
*********************配置核心层*************************1.找到核心层代码目录:内核顶层目录/drivers/i2c2. 内核顶层目录执行make menuconfig3. > Device Drivers > I2C support ->-*-I2C support4.保存退出********************配置总线驱动层************1.找到iic总线驱动层代码目录:内核顶层目录/drivers/i2c/busses2.内核顶层目录执行make menuconfig3. > Device Drivers > I2C support > I2C Hardware Bus support-》<*> STMicroelectronics STM32F7 I2C support 4.保存退出*************编译**********1.内核顶层目录下执行make uImage LOADADDR=0XC20000002.cp 内核层目录/arch/arm/boot/uImage ~/tftpboot3.重启开发板
2.I2C设备树节点的修改和SI7006设备树节点的添加
在stm32mp157a-fsmp1a.dts文件的根节点外部,添加如下内容:&i2c1 {pinctrl-names = "default", "sleep";//关于pinctrl的一个列表,"default"表示默认工作模式//"sleep"表示低功耗模式pinctrl-0 = <&i2c1_pins_b>;//-0表示pinctrl-name列表中第一个值defaultpinctrl-1 = <&i2c1_sleep_pins_b>;//在stm32mp15-pinctrl.dtsi文件中存在内核添加的各种用于管脚复用的节点,i2c1_pins_a就是其中之一i2c-scl-rising-time-ns = <100>;i2c-scl-falling-time-ns = <7>;status = "okay";/delete-property/dmas; //删除不必要的属性/delete-property/dma-names;si7006@40{ //添加SI7006的从机节点compatible="hqyj,si7006";reg=<0X40>;};};
3.si7006读取温湿度的功能码
4.温湿度的读取时序
5.温度湿度的计算公式
6.读取温湿度实例
头文件
#ifndef __HEAD_H__
#define __HEAD_H__#define GET_HUM _IOR('m',1,int)//获取湿度的功能码
#define GET_TEM _IOR('m',0,int)//获取温度的功能码#endif
应用程序
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include<string.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include"head.h"
int main(int argc, char const *argv[])
{int tem,hum;float tem1,hum1;int fd=open("/dev/si7006",O_RDWR);if(fd<0){printf("设备文件打开失败\n");exit(-1);}while(1){//获取数据ioctl(fd,GET_HUM,&hum);ioctl(fd,GET_TEM,&tem);//大小端转换hum=ntohs(hum);tem=ntohs(tem);//计算数据hum1=125.0*hum/65536-6;tem1=175.72*tem/65536-46.85;printf("tem=%f,hum=%f\n",tem1,hum1);sleep(1);}return 0;
}
驱动程序
#include <linux/init.h>
#include <linux/module.h>
#include<linux/i2c.h>
#include<linux/fs.h>
#include<linux/device.h>
#include"head.h"
unsigned int major;
struct class *cls;
struct device *dev;
struct i2c_client *client1;
//读取温湿度的函数
int i2c_read_hum_tem(char reg)
{short value;char r_buf[]={reg};int ret;
//封装消息struct i2c_msg r_msg[]={[0]={.addr=client1->addr,.flags=0,.len=sizeof(r_buf),.buf=r_buf, },[1]={.addr=client1->addr,.flags=1,.len=2,.buf=(char *)&value, },
};
//将消息传送
ret=i2c_transfer(client1->adapter,r_msg,2);
if(ret!=2)
{printk("消息传输失败\n");return -EIO;
}return value;//将读取到的温度和湿度返回
}
int si7006_open(struct inode * inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
long si7006_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int tem,hum,ret;switch(cmd){case GET_HUM://读取湿度//读取湿度的逻辑hum=i2c_read_hum_tem(0XE5);ret=copy_to_user((void *)arg,&hum,4);if(ret){printk("向用户拷贝数据失败\n");return ret;}break;case GET_TEM://读取温度//读取温度的逻辑tem=i2c_read_hum_tem(0XE3);ret=copy_to_user((void *)arg,&tem,4);if(ret){printk("向用户拷贝数据失败\n");return ret;}break;}return 0;
}
int si7006_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
struct file_operations fops={.open=si7006_open,.unlocked_ioctl=si7006_ioctl,.release=si7006_close,
};
//给对象分配空间并且初始化
int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{client1=client;//字符设备驱动的注册major=register_chrdev(0,"si7006",&fops);if(major<0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功\n");//设备节点的创建//向上提交目录cls=class_create(THIS_MODULE,"si7006");if(IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录成功\n");//向上提交设备节点dev=device_create(cls,NULL,MKDEV(major,0),NULL,"si7006");if(IS_ERR(dev)){printk("向上提交节点信息失败\n");return -PTR_ERR(dev);}printk("向上提交节点信息成功\n");//设备信息的获取。。。return 0;
}
int i2c_remove(struct i2c_client *client)
{//销毁节点device_destroy(cls,MKDEV(major,0));//销毁目录class_destroy(cls);//注销字符设备驱动unregister_chrdev(major,"si7006");return 0;
}
//定义设备树匹配的表
struct of_device_id oftable[]={{.compatible="hqyj,si7006",},{},
};
//分配IIC驱动信息对象
struct i2c_driver i2c_drv={.probe=i2c_probe,.remove=i2c_remove,.driver={.name="si7006",.of_match_table=oftable, },
};
//一键注册宏
module_i2c_driver(i2c_drv);
MODULE_LICENSE("GPL");