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

[复制链接]

实习生

发表于 2017-5-8 08:34:37   1915 查看 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,只要对对应寄存器读取特定的数值即可。
AAAAAAAAAAAAAAA.png

因为选择了linux 系统,所以我们将驱动与应用分开,下面就来看下我们的实际代码:

驱动代码,主要负责读取数据,与底层硬件通讯,在这里是负责与温度传感器的I2C进行交互,即直接对I2C的寄存器进行读取信息

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/fs.h>
  4. #include <linux/device.h>
  5. //#include <linux/leds.h>
  6. #include <linux/gpio.h>
  7. #include <linux/errno.h>
  8. #include <linux/types.h>
  9. #include <asm/uaccess.h>
  10. #include <linux/miscdevice.h>
  11. #include <linux/gpio.h>
  12. #include <linux/poll.h>
  13. #include <linux/cdev.h>
  14. #include <linux/wait.h>
  15. #include <linux/sched.h>
  16. #include <linux/semaphore.h>
  17. #include <linux/timer.h>
  18. #include <linux/jiffies.h>
  19. #include <linux/i2c.h>
  20. #include <linux/slab.h>
  21. #include <linux/miscdevice.h>


  22. #define LM75A_ADDR 0x48
  23. #define CMD_SET_ROM_ADRR 0x01

  24. #define DEBUG 1
  25. #ifdef DEBUG
  26. #define DEV_DEBUG(...) printk(__VA_ARGS__);
  27. #endif

  28. #define LM75X_CONF_REG 0x01

  29. static const u8 LM75X_REG_TEMP[3] = {
  30.     00,
  31.     02,
  32.     03,
  33. };


  34. struct lm75x_data{
  35.   struct i2c_client *i2c_client;
  36.   struct device *dev;
  37.   u8 old_config;
  38.   u16 temp[3];  // 0 input / 1 max  / 2 hyst
  39. };

  40. struct lm75x_data *data;


  41. static int lm75_read_value(struct i2c_client *client, u8 reg)
  42. {
  43.         if (reg == LM75X_CONF_REG)
  44.                 return i2c_smbus_read_byte_data(client, reg);
  45.         else
  46.                 return i2c_smbus_read_word_swapped(client, reg);
  47. }


  48. static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
  49. {
  50.         if (reg == LM75X_CONF_REG)
  51.                 return i2c_smbus_write_byte_data(client, reg, value);
  52.         else
  53.                 return i2c_smbus_write_word_swapped(client, reg, value);
  54. }

  55. static u16 read_reg_value(struct i2c_client *client, u8 reg)
  56. {
  57.   u16 temp_state = 0;
  58.   temp_state = lm75_read_value(client, reg);

  59.   if (reg == 0x00){
  60.       temp_state = temp_state >> 5;
  61.      // temp_state && 0x1ff;
  62.       return temp_state;
  63.   }
  64. }

  65. static const struct i2c_device_id lm75x_id[] = {
  66.   {"lm75a", 0},
  67.   {"lm75b", 1},
  68.   {}
  69. };

  70. MODULE_DEVICE_TABLE(i2c, lm75x_id);

  71. long lm75x_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
  72. {
  73.   int ret = 0;




  74.    return ret;
  75. }


  76. ssize_t lm75x_write(struct file *filp, const char __user *buf, size_t count, loff_t *loff)
  77. {
  78.   int ret = 0;




  79.    return ret;
  80. }

  81. ssize_t lm75x_read(struct file *filp, char __user *buf, size_t count, loff_t *loff)
  82. {
  83.   int ret = 0;
  84.   u16 temp_state = 0;
  85.   char temp[2];

  86.   temp_state = read_reg_value(data->i2c_client, 0x00);
  87.   //temp = (char)temp_state;
  88.   temp[0] = (char)(temp_state & 0x00FF);
  89.   temp[1] = (char)(temp_state >> 8);
  90.   DEV_DEBUG("temp[0] = %x\n", temp[0]);
  91. // DEV_DEBUG("temp_state = %x \n", temp_state);
  92.   if (copy_to_user(buf, &temp, count)){
  93.       ret = -EFAULT;
  94.   }
  95.   DEV_DEBUG("temp_state = %x \n", temp_state);
  96.   DEV_DEBUG("buf = %x \n", temp);
  97. //  /lm75_read_value();


  98.   return ret;
  99. }

  100. int lm75x_oepn(struct inode *node , struct file *filp)
  101. {

  102.   return 0;
  103. }

  104. static const struct file_operations lm75x_fops ={
  105.    .owner = THIS_MODULE,
  106.   // .open = lm75x_oepn,
  107.   // .release = lmx75x_remove,
  108.    .read = lm75x_read,
  109.    .write = lm75x_write,
  110.    .unlocked_ioctl = lm75x_ioctl,
  111. };


  112. static struct miscdevice lm75x_misc = {
  113.     .name = "lm75x_misc",
  114.     .minor = 99,
  115.     .fops = &lm75x_fops,
  116. };


  117. int lm75x_probe(struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id)
  118. {
  119.   int err = 0;
  120.   int conf_state, old_conf;
  121.   data = kzalloc(sizeof(struct lm75x_data), GFP_KERNEL);
  122.   if (!data)
  123.     return -ENOMEM;
  124.   data->i2c_client = i2c_client;
  125.   dev_set_drvdata(&i2c_client->dev, data);

  126.   if (!i2c_check_functionality(i2c_client->adapter,I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
  127.                   return -EIO;

  128.   conf_state = lm75_read_value(i2c_client, LM75X_CONF_REG);
  129.   DEV_DEBUG("conf_state = %02x \n", conf_state);
  130.   if (!conf_state)
  131.     data->old_config = conf_state;

  132.   err = misc_register(&lm75x_misc);

  133.   DEV_DEBUG("sizeof data = %d \n", sizeof(*data));
  134.   if (err) {
  135.       printk("miscdevice is fail\n");
  136.       return err;
  137.     }

  138.   printk("i2c is detected \n");
  139. #if 0
  140.   data->temp[0] = lm75_read_value(i2c_client, 0x00);
  141.   DEV_DEBUG("state-pre = %x \n", state);
  142.   state = state >> 5;
  143.   printk("state = %x \n", state);

  144.   tys = lm75_read_value(i2c_client, 0x02);
  145.   DEV_DEBUG("tys-pre = %x \n", tys);
  146.   tys = tys >> 7;
  147.   printk("tys = %x \n", tys);

  148.   tos = lm75_read_value(i2c_client, 0x03);
  149.   DEV_DEBUG("tos-pre = %x \n", tos);
  150.   tos = tos >> 7;
  151.   printk("tos = %x \n", tos);

  152.   lm75_write_value(i2c_client, 0x03, 0xa1 << 7);

  153.   tos = lm75_read_value(i2c_client, 0x03);
  154.   DEV_DEBUG("tos-pre = %x \n", tos);
  155.   tos = tos >> 7;
  156.   printk("tos = %x \n", tos);


  157. #endif
  158.   return 0;
  159. }


  160. int lm75x_remove(struct i2c_client *i2c_client)
  161. {
  162.   struct lm75x_data *data = dev_get_drvdata(&i2c_client->dev);
  163.   misc_deregister(&lm75x_misc);
  164.   kfree(data);
  165.   printk("remove the i2c \n");
  166.   return 0;
  167. }

  168. static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
  169.          0x4d, 0x4e, 0x4f, I2C_CLIENT_END };


  170. static struct i2c_driver lm75x_driver = {
  171.   .driver = {
  172.       .name = "lm75a",
  173.   },
  174.   .probe = lm75x_probe,
  175.   .remove = lm75x_remove,
  176.   .id_table = lm75x_id,
  177.   .address_list = normal_i2c,
  178. };

  179. static int __init lm75x_init(void)
  180. {
  181.   i2c_add_driver(&lm75x_driver);
  182.   return 0;
  183. }

  184. static void __exit lm75x_exit(void)
  185. {<div class="blockcode"><blockquote>
复制代码

  i2c_del_driver(&lm75x_driver);
}


module_init(lm75x_init);
module_exit(lm75x_exit);

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

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <syspes.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <termios.h>
  8. #include <errno.h>

  9. #define I2C_DEV_NAME "/dev/lm75x_misc"

  10. #define DATA_LEN 20

  11. char buf[DATA_LEN];

  12. int main(int arg,char*args[])
  13. {
  14. int fd;
  15. float temp;

  16. fd = open(I2C_DEV_NAME, O_RDWR);
  17. if(fd < 0) {
  18. printf("open %s failed\r\n", I2C_DEV_NAME);
  19. return -1;
  20. }
  21. printf("success \n");

  22. read(fd, buf, DATA_LEN);

  23. //printf("temp = %s \n", buf);

  24. temp = (float)buf[0] * 0.125;
  25. printf("temp = %.03f \n", temp);



  26. return 0;

  27. }
复制代码
应用程序主要负责读取驱动的数值,在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  
驱动框架写的不错,就是功能太简单了。。就读个数就完事了啊?
回复

点赞 举报

只有小组成员才能发言,加入小组>>

10个成员聚集在这个小组

加入小组

创建小组步骤

关闭

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

快速回复 返回顶部 返回列表
-

推荐专区

技术干货集中营

专家问答

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

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

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论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区