本项目最终使用的是数字式温度传感器对温度数值进行探测,使用app对数据进行读取和反馈
数字式温度传感器通过I2C连接:
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。I2C 总线支持任何IC 生产工艺(CMOS、双极型)。通过串行数据(SDA)线和串行时钟 (SCL)线在连接到总线的器件间传递信息。每个器件都有一个唯一的地址识别(无论是微控制器——MCU、LCD 驱动器、存储器或键盘接口),而且都可以作为一个发送器或接收器(由器件的功能决定)。LCD 驱动器只能作为接收器,而存储器则既可以接收又可以发送数据。除了发送器和接收器外,器件在执行数据传输时也可以被看作是主机或从机(见表1)。主机是初始化总线的数据传输并产生允许传输的时钟信号的器件。此时,任何被寻址的器件都被认为是从机。
温度传感器芯片介绍:
LM75A是一款内置带隙温度传感器和∑-Δ模数转换功能的温度数字转换器,它也是温度检测器,可提供过热输出功能。LM75A包含多个数据寄存器:配置寄存器(Conf)用来存储器件的某些设置,如器件的工作模式、OS工作模式、OS极性和OS错误队列等;温度寄存器(Temp)用来存储读取的数字温度;设定点寄存器(Tos & Thyst)用来存储可编程的过热关断和滞后限制,器件通过两线的串行I2 C总线接口与控制器通信。LM75A还包含一个开漏输出(OS)管脚,当温度超过编程限制的值时该输出有效。LM75A有3个可选的逻辑地址管脚,使得同一总线上可同时连接8个器件而不发生地址冲突。
LM75A可配置成不同的工作模式。它可设置成在正常工作模式下周期性地对环境温度进行监控,或进入关断模式来将器件功耗降至最低。OS输出有2种可选的工作模式:OS比较器模式和OS中断模式。OS输出可选择高电平或低电平有效。错误队列和设定点限制可编程,可以激活OS输出。
温度寄存器通常存放着一个11位的二进制数的补码,用来实现0.125℃的精度,在需要精确地测量温度偏移或超出限制范围的应用中非常有用。当LM75A在转换过程中不产生中断(I2 C总线部分与∑-Δ转换部分完全独立)或LM75A不断被访问时,器件将一直更新温度寄存器中的数据。
正常工作模式下,当器件上电时,OS工作在比较器模式,温度阈值为80℃,滞后75℃,这时,LM75A就可用作独立的温度控制器,预定义温度设定点。
管脚号 | 符号 | 功能 | 1 | SDA | 串行数据线 | 2 | SCL | 串行时钟线 | 3 | OS | 过热关断输出,开漏 | 4 | GND | 地 | 5 | A2 | 用户定义的地址位2 | 6 | A1 | 用户定义的地址位1 | 7 | A0 | 用户定义的地址位0 | 8 | VCC | |
其中温度寄存器0x00,配置寄存器0x01,滞后寄存器0x02,过温保护寄存器0x03,只要对对应寄存器读取特定的数值即可。
因为选择了linux 系统,所以我们将驱动与应用分开,下面就来看下我们的实际代码:
驱动代码,主要负责读取数据,与底层硬件通讯,在这里是负责与温度传感器的I2C进行交互,即直接对I2C的寄存器进行读取信息
- #include
- #include
- #include
- #include
- //#include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include timer.h>
- #include
- #include
- #include
- #include
- #define LM75A_ADDR 0x48
- #define CMD_SET_ROM_ADRR 0x01
- #define DEBUG 1
- #ifdef DEBUG
- #define DEV_DEBUG(...) printk(__VA_ARGS__);
- #endif
- #define LM75X_CONF_REG 0x01
- static const u8 LM75X_REG_TEMP[3] = {
- 00,
- 02,
- 03,
- };
- struct lm75x_data{
- struct i2c_client *i2c_client;
- struct device *dev;
- u8 old_config;
- u16 temp[3]; // 0 input / 1 max / 2 hyst
- };
- struct lm75x_data *data;
- static int lm75_read_value(struct i2c_client *client, u8 reg)
- {
- if (reg == LM75X_CONF_REG)
- return i2c_smbus_read_byte_data(client, reg);
- else
- return i2c_smbus_read_word_swapped(client, reg);
- }
- static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
- {
- if (reg == LM75X_CONF_REG)
- return i2c_smbus_write_byte_data(client, reg, value);
- else
- return i2c_smbus_write_word_swapped(client, reg, value);
- }
- static u16 read_reg_value(struct i2c_client *client, u8 reg)
- {
- u16 temp_state = 0;
- temp_state = lm75_read_value(client, reg);
- if (reg == 0x00){
- temp_state = temp_state >> 5;
- // temp_state && 0x1ff;
- return temp_state;
- }
- }
- static const struct i2c_device_id lm75x_id[] = {
- {"lm75a", 0},
- {"lm75b", 1},
- {}
- };
- MODULE_DEVICE_TABLE(i2c, lm75x_id);
- long lm75x_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
- {
- int ret = 0;
- return ret;
- }
- ssize_t lm75x_write(struct file *filp, const char __user *buf, size_t count, loff_t *loff)
- {
- int ret = 0;
- return ret;
- }
- ssize_t lm75x_read(struct file *filp, char __user *buf, size_t count, loff_t *loff)
- {
- int ret = 0;
- u16 temp_state = 0;
- char temp[2];
- temp_state = read_reg_value(data->i2c_client, 0x00);
- //temp = (char)temp_state;
- temp[0] = (char)(temp_state & 0x00FF);
- temp[1] = (char)(temp_state >> 8);
- DEV_DEBUG("temp[0] = %xn", temp[0]);
- // DEV_DEBUG("temp_state = %x n", temp_state);
- if (copy_to_user(buf, &temp, count)){
- ret = -EFAULT;
- }
- DEV_DEBUG("temp_state = %x n", temp_state);
- DEV_DEBUG("buf = %x n", temp);
- // /lm75_read_value();
- return ret;
- }
- int lm75x_oepn(struct inode *node , struct file *filp)
- {
- return 0;
- }
- static const struct file_operations lm75x_fops ={
- .owner = THIS_MODULE,
- // .open = lm75x_oepn,
- // .release = lmx75x_remove,
- .read = lm75x_read,
- .write = lm75x_write,
- .unlocked_ioctl = lm75x_ioctl,
- };
- static struct miscdevice lm75x_misc = {
- .name = "lm75x_misc",
- .minor = 99,
- .fops = &lm75x_fops,
- };
- int lm75x_probe(struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id)
- {
- int err = 0;
- int conf_state, old_conf;
- data = kzalloc(sizeof(struct lm75x_data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- data->i2c_client = i2c_client;
- dev_set_drvdata(&i2c_client->dev, data);
- if (!i2c_check_functionality(i2c_client->adapter,I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
- return -EIO;
- conf_state = lm75_read_value(i2c_client, LM75X_CONF_REG);
- DEV_DEBUG("conf_state = %02x n", conf_state);
- if (!conf_state)
- data->old_config = conf_state;
- err = misc_register(&lm75x_misc);
- DEV_DEBUG("sizeof data = %d n", sizeof(*data));
- if (err) {
- printk("miscdevice is failn");
- return err;
- }
- printk("i2c is detected n");
- #if 0
- data->temp[0] = lm75_read_value(i2c_client, 0x00);
- DEV_DEBUG("state-pre = %x n", state);
- state = state >> 5;
- printk("state = %x n", state);
- tys = lm75_read_value(i2c_client, 0x02);
- DEV_DEBUG("tys-pre = %x n", tys);
- tys = tys >> 7;
- printk("tys = %x n", tys);
- tos = lm75_read_value(i2c_client, 0x03);
- DEV_DEBUG("tos-pre = %x n", tos);
- tos = tos >> 7;
- printk("tos = %x n", tos);
- lm75_write_value(i2c_client, 0x03, 0xa1 << 7);
- tos = lm75_read_value(i2c_client, 0x03);
- DEV_DEBUG("tos-pre = %x n", tos);
- tos = tos >> 7;
- printk("tos = %x n", tos);
- #endif
- return 0;
- }
- int lm75x_remove(struct i2c_client *i2c_client)
- {
- struct lm75x_data *data = dev_get_drvdata(&i2c_client->dev);
- misc_deregister(&lm75x_misc);
- kfree(data);
- printk("remove the i2c n");
- return 0;
- }
- static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
- 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
- static struct i2c_driver lm75x_driver = {
- .driver = {
- .name = "lm75a",
- },
- .probe = lm75x_probe,
- .remove = lm75x_remove,
- .id_table = lm75x_id,
- .address_list = normal_i2c,
- };
- static int __init lm75x_init(void)
- {
- i2c_add_driver(&lm75x_driver);
- return 0;
- }
- static void __exit lm75x_exit(void)
- {复制代码
i2c_del_driver(&lm75x_driver);
}
module_init(lm75x_init);
module_exit(lm75x_exit);
MODULE_LICENSE("GPL");
应用程序,负责对驱动进行操作,比如何时读,何时配置等,这些我们一般都放在应用层来执行
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define I2C_DEV_NAME "/dev/lm75x_misc"
- #define DATA_LEN 20
- char buf[DATA_LEN];
- int main(int arg,char*args[])
- {
- int fd;
- float temp;
- fd = open(I2C_DEV_NAME, O_RDWR);
- if(fd < 0) {
- printf("open %s failedrn", I2C_DEV_NAME);
- return -1;
- }
- printf("success n");
- read(fd, buf, DATA_LEN);
- //printf("temp = %s n", buf);
- temp = (float)buf[0] * 0.125;
- printf("temp = %.03f n", temp);
- return 0;
- }
复制代码
应用程序主要负责读取驱动的数值,在linux中使用sysfs 对设备进行操作。
到这里我们就完成了对温度传感器的数据采集的效果。
0
|
|
|
|