lm91000——stm32  -气体传感器(氧气 硫化氢,氨气)

最近我做了一下气体传感器,遇到了一些问题,摸索前进。最后还是有些收获。总结分享一下。

第一部分 总体部分电路

LMP91000 传感器AFE 系统:用于低功耗化学感测应用的可配置AFE 稳压器

点击打开链接 lmp91000

官方原理图

第二部分 芯片和程序

LMP91000 是一款可编程模拟前端 (AFE),适用于微功耗电化学感测应用。 它可提供传感器与微控制器之间的完整信号路径解决方案,此方案能够生成与电池电流成比例的输出电压。 LMP91000 的可编程性使它能够通过一个与多个离散解决方案相对的单一设计支持多种电化学传感器,例如,3 导线有毒气体传感器和 2 导线原电池型传感器。 LMP91000 支持 0.5nA/ppm 至 9500nA/ppm 范围内的气体灵敏度。 它还可实现 5µA 至 750µA 满量程电流范围的简单转换

这个芯片很强大,可以适配很多气体传感器。

根据不同的产期配置不同的跨阻放大器的电阻,实现放大电流

1.1 Fundamental Blocks of LMP91000
Transimpedance Amplifier — TIA provides an output voltage that is proportional to the cell current. TIA
provides seven programmable internal-gain resistors and allows the external-gain resistor to
connect to the LMP91000.
(Vref_div – Vout) / (RTIA) = Iwe (1)
Vout = (Vref_div) – (RTIA × Iwe) (2)
Input — The LMP91000 provides a 3-electrode solution — counter electrode (CE), reference electrode
(RE), working electrode (WE) (see Figure 4), as well as a 2-electrode solution — short the CE and
RE (see Figure 5).
Variable Bias — Variable bias provides the amount of bias voltage required by a biased gas sensor
between RE and WE. This bias voltage can be programmed to be 1% to 24% of the supply, or it
can be VREF. The bias can also be negative or positive depending on the type of sensing element.
Vref Divider — This is the voltage at the noninverting pin at TIA. This voltage can be programmed to be
either 20%, 50%, or 67% of the supply, or it can be VREF. The Vref divider provides the best use of
the full-scale input range of the analog-to-digital converter (ADC) and sufficient headroom for the
CE of the sensor to swing in case of sudden changes in the gas concentration.
• How to select the appropriate Vref divider:
– If the current at pin WE (Iwe) is flowing into the TIA, then the Vref divider should be set to 67%
of Vref.
– If Iwe is flowing out of the TIA, then the Vref divider should be set to 20% of Vref.
• Assume Vref_divider is set to 20% of Vref.
• Assume variable bias is set to 2% of Vref.
• Assume Vref = 4.1 V.
The Vref divider in that case would be 0.82 V. The noninverting input to A1 is 0.902 V,
which is 22% of Vref.
Control Amplifier A1 — A1 is a differential amplifier used to compare the potential between WE and RE.
The error signal is amplified and applied to the CE. Changes in the impedance between the WE
and RE cause a change in the voltage applied to CE in order to maintain the constant voltage
between WE and RE.
SNOA922–August 2013 Gas Sensor Platform Reference Design 3
Submit Documentation Feedback
Copyright © 2013, Texas Instruments Incorporated
Introduction www.ti.com
Temperature Sensor — An on-board temperature sensor provides a ±3˚C accuracy. The sensor can be
used by an external microcontroller to correct for performance over temperature.
Serial Interface — Calibration and programming is done through the I2C digital interface. The I2C
interface enables calibration and state-of-health monitoring. As mentioned before, health
monitoring is very important because chemical cells can degrade over time.

配置的过程通过IIc接口来实现,TI官网有个软件WEBENCH Design Environments ,里面可以帮我们配置lmp91000的寄存器参数,很方便。





配置好寄存器


#define I2C_RD   1       /* 读控制bit */
#define LMP_WRITE_ADDE    0x90                //LMP??+???
#define LMP_READ_ADDE     0x91                //LMP??+???#define LMP_REG1_ADDE     0x00                //   LMP???1??0x00
#define LMP_REG2_ADDE     0x01                // LMP???2??0x01
#define LMP_REG3_ADDE     0x10                //LMP???3??0x10
#define LMP_REG4_ADDE     0x11                //LMP???4??0x11
#define LMP_REG5_ADDE     0x12                //LMP???5??0x12/* 氨气 */
//#define LMP_REG2_UNLOCK   0x00                //LMP???2????0x00
//#define LMP_REG2_LOCK     0x01                //LMP???2????0x01
//#define LMP_REG3_DATA     0x1c           //LMP???3????0x0E
//#define LMP_REG4_DATA     0x90            //LMP???4????0xB0
//#define LMP_REG5_DATA     0x03                //LMP???5????0x07/03/*氧气*/
#define LMP_REG2_UNLOCK   0x00                //LMP???2????0x00
#define LMP_REG2_LOCK     0x01                //LMP???2????0x01
#define LMP_REG3_DATA     0x08        //LMP???3????0x0E
#define LMP_REG4_DATA     0xc0           //LMP???4????0xB0
#define LMP_REG5_DATA     0x07               //LMP???5????0x07/03
/*************************************IIC??????*******************************************//* 定义I2C总线连接的GPIO端口, 用户只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */
#define GPIO_PORT_I2C   GPIOB           /* GPIO端口 */
#define RCC_I2C_PORT    RCC_APB2Periph_GPIOB        /* GPIO端口时钟 */
#define I2C_SCL_PIN     GPIO_Pin_7      /* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN     GPIO_Pin_6      /* 连接到SDA数据线的GPIO */
#define I2C_EN_PIN      GPIO_Pin_8      /* 连接到EN使能线的GPIO *//* 定义读写SCL和SDA的宏,已增加代码的可移植性和可阅读性 */
#if 0   /* 条件编译: 1 选择GPIO的库函数实现IO读写 */#define I2C_SCL_1()  GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN)      /* SCL = 1 */#define I2C_SCL_0()  GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN)       /* SCL = 0 */#define I2C_SDA_1()  GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN)     /* SDA = 1 */#define I2C_SDA_0()  GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN)       /* SDA = 0 */#define I2C_EN_1()  GPIO_SetBits(GPIO_PORT_I2C, I2C_EN_PIN)       /* EN = 1 */#define I2C_EN_0()  GPIO_ResetBits(GPIO_PORT_I2C, I2C_EN_PIN)      /* EN = 0 */#define I2C_SDA_READ()  GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN)  /* 读SDA口线状态 */
#else   /* 这个分支选择直接寄存器操作实现IO读写 *//* 注意:如下写法,在IAR最高级别优化时,会被编译器错误优化 */#define I2C_SCL_1()  GPIO_PORT_I2C->BSRR = I2C_SCL_PIN             /* SCL = 1 */#define I2C_SCL_0()  GPIO_PORT_I2C->BRR = I2C_SCL_PIN             /* SCL = 0 */#define I2C_SDA_1()  GPIO_PORT_I2C->BSRR = I2C_SDA_PIN                /* SDA = 1 */#define I2C_SDA_0()  GPIO_PORT_I2C->BRR = I2C_SDA_PIN             /* SDA = 0 */#define I2C_EN_1()  GPIO_PORT_I2C->BSRR =I2C_EN_PIN       /* EN = 1 */#define I2C_EN_0()  GPIO_PORT_I2C->BRR = I2C_EN_PIN        /* EN = 0 */#define I2C_SDA_READ()  ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0)  /* 读SDA口线状态 */
#endifstatic void i2c_CfgGpio(void);
/*
*********************************************************************************************************
*   函 数 名: i2c_Delay
*   功能说明: I2C总线位延迟,最快400KHz
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay(void)
{uint8_t i;/* 下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。CPU主频72MHz时,在内部Flash运行, MDK工程不优化循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us IAR工程编译效率高,不能设置为7*/for (i = 0; i < 10; i++);
}/************************************************************************************************
** ????:LMP_Init_Func
** ????:?
** ????:?
** ????:??IIC???ADS???????
************************************************************************************************/
void LMP_IIC_Init_Func(void)
{               i2c_CfgGpio();                                                                                                                                                                        i2c_Start();//LMP_IIC_Start();  i2c_SendByte(LMP_WRITE_ADDE);/* LMP_IIC_Send_Byte(LMP_WRITE_ADDE); *//* LMP91000+写操作 */i2c_WaitAck();//LMP_IIC_Wait_Ack();i2c_SendByte(LMP_REG2_ADDE);       //锁定寄存器    地址01                                           i2c_WaitAck();                        i2c_SendByte(LMP_REG2_UNLOCK);     //解锁  命令     0x00                                       i2c_WaitAck();  i2c_Stop();i2c_Delay();i2c_Delay();//delay_us(8);i2c_Start();i2c_SendByte(LMP_WRITE_ADDE);      //LMP91000+写操作     i2c_WaitAck();i2c_SendByte(LMP_REG3_ADDE);       //TIA寄存器      地址 10                   i2c_WaitAck();                         i2c_SendByte(LMP_REG3_DATA);       //  电阻配置 命令    0x0F                                                  i2c_WaitAck(); i2c_Stop();i2c_Delay();i2c_Delay();i2c_Start();i2c_SendByte(LMP_WRITE_ADDE);     //LMP91000+写操作      i2c_WaitAck();i2c_SendByte(LMP_REG4_ADDE);       //REFCN寄存器      地址 11                                 i2c_WaitAck();                         i2c_SendByte(LMP_REG4_DATA);       // 参考源配置命令   0xb0                                                        i2c_WaitAck(); i2c_Stop();i2c_Delay();i2c_Delay();i2c_Start();i2c_SendByte(LMP_WRITE_ADDE);      //LMP91000+写操作       i2c_WaitAck();i2c_SendByte(LMP_REG5_ADDE);       //MODECN   寄存器      地址 1                 i2c_WaitAck();                         i2c_SendByte(LMP_REG5_DATA);       //模式寄存器   ox07                                                           i2c_WaitAck(); i2c_Stop();i2c_Delay();i2c_Delay();i2c_Start();i2c_SendByte(LMP_WRITE_ADDE);      //??LMP91000??        i2c_WaitAck();i2c_SendByte(LMP_REG2_ADDE);       //锁定寄存器    地址01                     i2c_WaitAck();                         i2c_SendByte(LMP_REG2_LOCK);       //   锁定                                                     i2c_WaitAck(); i2c_Stop();i2c_Delay();i2c_Delay();i2c_Delay();}/*********************************************************************************************************
*   函 数 名: i2c_Delay
*   功能说明: I2C总线位延迟,最快400KHz
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay1(void)
{uint8_t i;/* 下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。CPU主频72MHz时,在内部Flash运行, MDK工程不优化循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us IAR工程编译效率高,不能设置为7*/for (i = 0; i < 7; i++);
}
/*
*********************************************************************************************************
*   函 数 名: i2c_Start
*   功能说明: CPU发起I2C总线启动信号
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Start(void)
{I2C_EN_0();i2c_Delay();i2c_Delay();i2c_Delay();i2c_Delay();/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */I2C_SDA_1();I2C_SCL_1();i2c_Delay();I2C_SDA_0();i2c_Delay();I2C_SCL_0();i2c_Delay();
}/*
*********************************************************************************************************
*   函 数 名: i2c_Start
*   功能说明: CPU发起I2C总线停止信号
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Stop(void)
{/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */I2C_SDA_0();I2C_SCL_1();i2c_Delay();I2C_SDA_1();i2c_Delay();//I2C_EN_1();//
}/*
*********************************************************************************************************
*   函 数 名: i2c_SendByte
*   功能说明: CPU向I2C总线设备发送8bit数据
*   形    参:_ucByte : 等待发送的字节
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_SendByte(uint8_t _ucByte)
{uint8_t i;I2C_SCL_0();///* 先发送字节的高位bit7 */for (i = 0; i < 8; i++){       if (_ucByte & 0x80){I2C_SDA_1();}else{I2C_SDA_0();}i2c_Delay1();I2C_SCL_1();i2c_Delay1();I2C_SCL_0();if (i == 7){I2C_SDA_1(); // 释放总线}_ucByte <<= 1;   /* 左移一个bit */i2c_Delay1();}
}/*
*********************************************************************************************************
*   函 数 名: i2c_ReadByte
*   功能说明: CPU从I2C总线设备读取8bit数据
*   形    参:无
*   返 回 值: 读到的数据
*********************************************************************************************************
*/
uint8_t i2c_ReadByte(void)
{uint8_t i;uint8_t value;/* 读到第1个bit为数据的bit7 */value = 0;for (i = 0; i < 8; i++){value <<= 1;I2C_SCL_1();i2c_Delay();if (I2C_SDA_READ()){value++;}I2C_SCL_0();i2c_Delay();}return value;
}/*
*********************************************************************************************************
*   函 数 名: i2c_WaitAck
*   功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
*   形    参:无
*   返 回 值: 返回0表示正确应答,1表示无器件响应
*********************************************************************************************************
*/
uint8_t i2c_WaitAck(void)
{uint8_t re;I2C_SDA_1();    /* CPU释放SDA总线 */i2c_Delay1();I2C_SCL_1();   /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */i2c_Delay1();if (I2C_SDA_READ())   /* CPU读取SDA口线状态 */{re = 1;}else{re = 0;}I2C_SCL_0();//i2c_Delay();return re;
}/*
*********************************************************************************************************
*   函 数 名: i2c_Ack
*   功能说明: CPU产生一个ACK信号
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{I2C_SCL_0();I2C_SDA_0();   /* CPU驱动SDA = 0 */i2c_Delay();I2C_SCL_1(); /* CPU产生1个时钟 */i2c_Delay();I2C_SCL_0();i2c_Delay();I2C_SDA_1(); /* CPU释放SDA总线 */
}/*
*********************************************************************************************************
*   函 数 名: i2c_NAck
*   功能说明: CPU产生1个NACK信号
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{I2C_SDA_1();   /* CPU驱动SDA = 1 */i2c_Delay();I2C_SCL_1(); /* CPU产生1个时钟 */i2c_Delay();I2C_SCL_0();i2c_Delay();
}/*
*********************************************************************************************************
*   函 数 名: i2c_CfgGpio
*   功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
*   形    参:无
*   返 回 值: 无
*********************************************************************************************************
*/
static void i2c_CfgGpio(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);  /* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;      /* 开漏输出 */GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);//   PB8--REF_EN(LMP91000 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     // 推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */i2c_Stop();
}/*
*********************************************************************************************************
*   函 数 名: i2c_CheckDevice
*   功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
*   形    参:_Address:设备的I2C总线地址
*   返 回 值: 返回值 0 表示正确, 返回1表示未探测到
*********************************************************************************************************
*/
uint8_t i2c_CheckDevice(uint8_t _Address)
{uint8_t ucAck;LMP_IIC_Init_Func(); i2c_CfgGpio();      /* 配置GPIO */i2c_Start();        /* 发送启动信号 *//* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */i2c_SendByte(_Address | I2C_WR);ucAck = i2c_WaitAck();  /* 检测设备的ACK应答 */i2c_Stop();         /* 发送停止信号 */return ucAck;
}

第三部分 传感器

气体传感器分为两极很三级。图中的封装要注意。画电路封装是不能按图3的位置画。要镜像一下,(这个问题坑人啊)

我只在官方的参考设计中发现的。

点击打开链接






我遇到过坑在LMP91000的参考手册中他的图就没有镜像,我认为他可能画错了


注意


lm91000——stm32 -气体传感器(氧气 硫化氢,氨气)相关推荐

  1. 第八章 STM32+SGP气体传感器+DHT11温湿度传感器+OLED模块显示室内温湿度、二氧化碳和甲醛浓度

    在智能家居相关的物联网毕设中,少不了室内气体检测功能,比如检测烟雾,检测一氧化碳,检测甲醛等有害气体浓度,别人有的,我们也要有!所以本章给大家介绍一款气体传感器--SGP气体传感器,这款气体传感器能够 ...

  2. 基于STM32和阿里云的矿道环境监测系统(温湿度DHT117,NRF2401(2.4G模块),气体传感器(MQ-3),0.96寸OLED屏,wifi模块)

    基于STM32和阿里云的矿道环境监测系统(温湿度DHT117,NRF2401(2.4G模块),气体传感器(MQ-3)) 系统实现的功能 系统实现的是运用一块STM32F103C8T6作为发射端节点,上 ...

  3. 一文读懂常用气体传感器的分类与原理

    气体传感器主要用于针对某种特定气体进行检测,测量该气体在传感器附近是否存在,或在传感器附近空气中的含量.因此,在安全系统中,气体传感器通常都是不可或缺的.这些传感器可以为安全系统提供可燃.易燃和有毒气 ...

  4. 气体传感器的市场状况及主要厂商

    气体传感器广泛应用于工业.生活的各个领域,如石油.化工.钢铁.冶金.矿山.环保.市政.医疗.食品等诸多领域.近年来,随着互联网与物联网的高速发展,气体传感器在新兴的智能家居.可穿戴设备.智能移动终端等 ...

  5. 电化学气体传感器的工作原理

    目前,气体传感器的应用日趋广泛,在物联网等泛在应用的推动下,其技术发展方向开始向小型化.集成化.模块化.智能化方向发展.其中工业领域就是气体传感器一个应用领域,用以使人员和设备免受危险气体导致的直接和 ...

  6. 氧化锆气体传感器行业调研报告 - 市场现状分析与发展前景预测

    氧化锆气体传感器市场的企业竞争态势 该报告涉及的主要国际市场参与者有NTRODUCTION.CITY TECHNOLOGY.FIGARO ENGINEERING.DYNAMENT.BOSCH SENS ...

  7. 一分钟让你快速了解红外气体传感器作用,特性及应用

    一分钟让你快速了解红外气体传感器作用,特性及应用 红外气体传感器是一种基于不同气体分子的近红外光谱选择吸收特性,利用气体浓度与吸收强度关系(朗伯-比尔Lambert-Beer定律)鉴别)鉴别气体组分并 ...

  8. Arduino Uno 实验15——MQ-135 气体传感器模块

    MQ-135 气体传感器模块简介(空气质量检测 有害气体检测)   MQ135气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2).当传感器所处环境中存在污染气体时,传感器的电导率 ...

  9. 电化学传感器(7)---氢补偿4电极传感器气体传感器 抑制h2干扰

    MEM6 氢补偿4电极传感器气体传感器抑制h2干扰 1.  原理 这种类型的元件4电极传感器用于一氧化碳(co)或硫化氢(h2s)等目标气体,并且允许补偿干扰氢气(h2),这是用过滤器或其他技术无法消 ...

最新文章

  1. 吴恩达:诸位CEO,我有一本「AI转型秘籍」传授给你
  2. 为工厂分配用于公司间开票的销售范围
  3. 导入myql库的操作方式
  4. HDU-5935 Car 逆推 贪心 精度
  5. c语言case接收字符,switch-case-break:字符释义 | 新思维:C语言程序设计
  6. 同花顺崩了上热一!网友:早盘血亏,你还不让我跑 官方回应...
  7. Linux学习总结(70)——Bash 脚本中常用的内置变量汇总
  8. 【技术翻译】SIFT算子原理及其实现 (一)介绍
  9. MapReduce在Map端的Combiner和在Reduce端的Partitioner
  10. Java开发 基础三十条 初学必看
  11. ArcGis如何插入图片_如何在CAD图纸中以OLE形式插入图片?
  12. python调用perl_从Python调用Perl脚本不断返回值
  13. vld/rdy协议 断言
  14. 物联网:Android端控制ZigBee实现生产环境自动控制
  15. 绩效/加薪/年终奖,虐你如初恋
  16. Linux内核数据结构之 radix tree
  17. 数据库与数据库管理系统之间的关系
  18. 海鸣威《离开为了更好的回来》 MV首播感心动耳
  19. 18、DQL(分页查询:limt)
  20. 【机器学习】Learning to Rank 简介

热门文章

  1. 嵌入式开发之1553B协议
  2. GPT分区安装windows10详细教程
  3. 一款无需下载,在线就可以制作的电子相册制作工具
  4. 当魔法师挥舞起大刀!
  5. 连续时间傅里叶变换的性质
  6. 怎样在大学里学好编程。开发
  7. 亚马逊(Amazon)赢利推广模式分析
  8. [20][04][10] Fortify Static Code Analyzer 详解
  9. webapp下资源文件无法访问 mvc resources
  10. 从输入URL到页面加载完的过程中都发生了什么事情