1. bread鸿运国际论坛
  2. 小组 > 技术 > 盈鹏飞嵌入式
  3. / 【EVB-T335开发板试用体验】- 基于I2C的温度传感器项目 ...

[作品] 【EVB-T335开发板试用体验】- 基于I2C的温度传感器项目(结项)

[复制链接]
实习生
发表于 2017-5-8 08:34:37   1787 查看 3 回复 只看该作者 倒序浏览
分享


本项目最终使用的是数字式温度传感器对温度数值进行探测,使用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)用来存储可编程的过热关断和滞后限制,器件通过两线的串行I2C总线接口与控制器通信。LM75A还包含一个开漏输出(OS)管脚,当温度超过编程限制的值时该输出有效。LM75A有3个可选的逻辑地址管脚,使得同一总线上可同时连接8个器件而不发生地址冲突。
  LM75A可配置成不同的工作模式。它可设置成在正常工作模式下周期性地对环境温度进行监控,或进入关断模式来将器件功耗降至最低。OS输出有2种可选的工作模式:OS比较器模式和OS中断模式。OS输出可选择高电平或低电平有效。错误队列和设定点限制可编程,可以激活OS输出。
  温度寄存器通常存放着一个11位的二进制数的补码,用来实现0.125℃的精度,在需要精确地测量温度偏移或超出限制范围的应用中非常有用。当LM75A在转换过程中不产生中断(I2C总线部分与∑-Δ转换部分完全独立)或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 <linux/module.h>
  • #include <linux/init.h>
  • #include <linux/fs.h>
  • #include <linux/device.h>
  • //#include <linux/leds.h>
  • #include <linux/gpio.h>
  • #include <linux/errno.h>
  • #include <linux/types.h>
  • #include <asm/uaccess.h>
  • #include <linux/miscdevice.h>
  • #include <linux/gpio.h>
  • #include <linux/poll.h>
  • #include <linux/cdev.h>
  • #include <linux/wait.h>
  • #include <linux/sched.h>
  • #include <linux/semaphore.h>
  • #include <linux/timer.h>
  • #include <linux/jiffies.h>
  • #include <linux/i2c.h>
  • #include <linux/slab.h>
  • #include <linux/miscdevice.h>


  • #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] = %x\n", 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 fail\n");
  •       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)
  • {<div class="blockcode"><blockquote>
  • 复制代码

      i2c_del_driver(&lm75x_driver);
    }


    module_init(lm75x_init);
    module_exit(lm75x_exit);

    MODULE_LICENSE("GPL");
    应用程序,负责对驱动进行操作,比如何时读,何时配置等,这些我们一般都放在应用层来执行

  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <unistd.h>
  • #include <syspes.h>
  • #include <sys/stat.h>
  • #include <fcntl.h>
  • #include <termios.h>
  • #include <errno.h>

  • #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 failed\r\n", 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 对设备进行操作。

    到这里我们就完成了对温度传感器的数据采集的效果。
    发表于 2017-5-10 10:37:44  
    lz有效果演示嘛?
    回复 点赞 举报
    实习生
    发表于 2017-5-11 14:19:11    楼主|

    PCB在线计价下单

    板子大小:

    cm
    X
    cm

    层数:

    2

    板子数量:

    10

    厚度:

    1.6

    有的,就是执行./app 我效果
    回复 点赞 举报
    技术员
    发表于 2017-6-14 14:03:20  
    驱动框架写的不错,就是功能太简单了。。就读个数就完事了啊?
    回复 点赞 举报
    只有小组成员才能发言,加入小组>>
    6个成员聚集在这个小组 加入小组

    创建小组步骤

    关闭

    站长推荐 上一条 /9 下一条

    快速回复 返回顶部 返回列表
    1. time最新主题
    2. recommend推荐主题
    3. hot热门主题
    4. post 我的帖子
    -

    推荐专区

    技术干货集中营

    专家问答

    用户帮助┃咨询与建议┃版主议事

    我的提问

    工程师杂谈

    工程师创意

    工程师职场

    论坛电子赛事

    社区活动专版

    发烧友活动

    -

    嵌入式论坛

    ARM技术论坛

    Android论坛

    Linux论坛

    单片机/MCU论坛

    FPGA|CPLD|ASIC论坛

    DSP论坛

    嵌入式系统论坛

    -

    电源技术论坛

    电源技术论坛

    无线充电技术

    -

    硬件设计论坛

    PCB设计论坛

    电路设计论坛

    电子元器件论坛

    控制|传感

    总线技术|接口技术

    -

    测试测量论坛

    LabVIEW论坛

    Matlab论坛

    测试测量技术专区

    仪器仪表技术专区

    -

    EDA设计论坛

    multisim论坛

    PADS技术论坛

    Protel|AD|DXP论坛

    Allegro论坛

    proteus论坛|仿真论坛

    EasyEDA-中国人自已的EDA工具

    Orcad论坛

    -

    综合技术与应用

    电机控制

    智能电网

    光电及显示

    参考设计中心

    汽车电子技术论坛

    医疗电子论坛

    -

    开源硬件

    -

    无线通信论坛

    无线通信技术专区

    天线|RF射频|微波|雷达技术

    -

    IC设计论坛

    芯片测试与失效分析

    Mixed Signal/SOC[数模混合芯片设计]

    Analog/RF IC设计

    设计与制造封装测试

    -

    厂商专区

    TI论坛

    TI Deyisupport社区

    -

    检测技术与质量

    电磁兼容(EMC)设计与整改

    安规知识论坛

    检测与认证

    -

    消费电子论坛

    手机技术论坛

    平板电脑/mid论坛

    音视/视频/机顶盒论坛

    -

    电子论坛综合区

    聚丰众筹官方社区

    新人报道区

    聚丰供应链

    -

    论坛服务区

    -

    供求信息发布

    供需广告

    招聘┃求职发布区

    电子展览展会专区

    鸿运国际手机欢迎你