在气体分析类产品中,我们经常会用到远红外气体传感器。我们就在碳氢类气体成分分析中使用了S-Modlue远红外气体传感器。接下来,我们将讨论S-Modlue远红外气体传感器驱动的设计与实现。

1、功能概述

  S-MODULE EVO 使用非分散红外检测技术NDIR,集成稳定红外光源,配置可靠性能的光电探测器,确保了传感器检测的稳定性能。

  S-MODULE采用的是RS232串行通讯接口,但其通讯接口对外只有一个通讯引脚,所以实现的是半双工模式。串口参数为:2400波特率,7位数据位,1位停止位,偶校验。

  在应用层采用的则是Modbus ASCII协议。S-MODULE非分光红外气体模块支持03和06功能码。S-MODULE非分光红外气体模块支持的Modbus参数如下:

2、驱动设计与实现

  我们知道S-Module远红外气体传感器采用基于半双工RS232接口的Modbus ASCII通讯协议。接下来我们将基于它的协议规则设计并实现驱动程序。

2.1、对象定义

  在使用一个对象之前我们需要获得一个对象。同样的我们想要S-Modlue远红外气体传感器就需要先定义S-Modlue远红外气体传感器的对象。

2.1.1、对象的抽象

  我们要得到S-Modlue远红外气体传感器对象,需要先分析其基本特性。一般来说,一个对象至少包含两方面的特性:属性与操作。接下来我们就来从这两个方面思考一下S-Modlue远红外气体传感器的对象。

  先来考虑属性,作为属性肯定是用于标识或记录对象特征的东西。我们来考虑S-Modlue远红外气体传感器对象的属性。首先Modbus协议对象都有站地址用以标识不同的设备,所以我们将设备地址作为对象的一个属性。此外,状态信息、温度、浓度等实时信息表示了对象当前的工作状态,所以我们将这些参数也作为对象的属性。

  接着我们还需要考虑S-Modlue远红外气体传感器对象的操作问题。我们需要从S-Modlue远红外气体传感器获取数据和下发命令,就需要通过串口发送消息,但串口的处理与具体的平台相关,所以我们将其作为对象的操作。此外,在操作对象的过程中需要控制时序,所以延时操作函数必不可少,而延时操作函数往往依赖于具体的软硬件平台,所以将延时函数作为对象的操作。

  根据上述我们对S-Modlue远红外气体传感器的分析,我们可以定义S-Modlue远红外气体传感器的对象类型如下:

/*定义NDIR对象类型*/
typedef struct NdirObject {uint8_t moduleAddress;uint16_t status;uint32_t softVersion;float concentration;float temperature;void (*SendByte)(uint8_t data);void (*Delayms)(volatile uint32_t nTime);
}NdirObjectType;

2.1.2、对象初始化

  我们知道,一个对象仅作声明是不能使用的,我们需要先对其进行初始化,所以这里我们来考虑S-Modlue远红外气体传感器对象的初始化函数。一般来说,初始化函数需要处理几个方面的问题。一是检查输入参数是否合理;二是为对象的属性赋初值;三是对对象作必要的初始化配置。据此我们设计S-Modlue远红外气体传感器对象的初始化函数如下:

/*NDIR初始化配置函数*/
void NdirInitialization(NdirObjectType *ndir,  //NDIR对象uint8_t moduleAddress, //模块地址NdirSendByteType send, //发送数据操作函数NdirDelaymsType delayms //毫秒延时操作函数)
{if((ndir==NULL)||(send==NULL)||(delayms==NULL)){return;}ndir->SendByte=send;ndir->Delayms=delayms;ndir->moduleAddress=moduleAddress;ndir->concentration=0.0;ndir->temperature=0.0;ndir->status=0;ndir->softVersion=0;
}

2.2、对象操作

  我们已经完成了S-Modlue远红外气体传感器对象类型的定义和对象初始化函数的设计。但我们的主要目标是获取对象的信息,接下来我们还要实现面向S-Modlue远红外气体传感器的各类操作。

  对于S-Modlue远红外气体传感器对象来说,最基本的操作就是向其发送操作命令或数据消息。这是基于串口的Modbus ASCII协议的数据通讯,基于此我们可编写响应的数据发送操作函数如下:

/*发送数据给舒茨非分光红外气体检测模块(读写数据)*/
static void NDIRSendData(NdirObjectType *ndir,uint8_t *txData,uint16_t length)
{uint16_t sendDataAmount=0;uint8_t sendDataArray[17]; //不小于(length+1)*2+3uint8_t rawData[7];//含校验码for(int i=0;i<length;i++){rawData[i]=txData[i];}rawData[6]=CheckSumCalc(txData,length);uint8_t objData[14];uint16_t cLength=ConvertHexArrayToASCIICharArray(rawData,length+1,objData);sendDataArray[sendDataAmount++]=':';for(int i=0;i<cLength;i++){sendDataArray[sendDataAmount++]=objData[i];}sendDataArray[sendDataAmount++]=0x0D;sendDataArray[sendDataAmount++]=0x0A;for(uint16_t sendDataIndex=0;sendDataIndex<sendDataAmount;sendDataIndex++){/*发送一个字节*/ndir->SendByte(sendDataArray[sendDataIndex]);}
}

3、驱动的使用

  我们已经实现了S-Module远红外气体传感器的驱动程序,但我们还需要验证一下它的正确性,所以在本节中我们就来设计一个简单的验证应用。

3.1、声明并初始化对象

  使用基于对象的操作我们需要先得到这个对象,所以我们先要使用前面定义的S-Modlue远红外气体传感器对象类型声明一个S-Modlue远红外气体传感器对象变量,具体操作格式如下:

  NdirObjectType ndir;

  声明了这个对象变量并不能立即使用,我们还需要使用驱动中定义的初始化函数对这个变量进行初始化。这个初始化函数所需要的输入参数如下:

NdirObjectType *ndir,  //NDIR对象
uint8_t moduleAddress, //模块地址
NdirSendByteType send, //发送数据操作函数
NdirDelaymsType delayms //毫秒延时操作函数

  对于这些参数,对象变量我们已经定义了。模块地址根据我们实际的使用情况输入就好了。主要的是我们需要定义几个函数,并将函数指针作为参数。这几个函数的类型如下:

/*发送一个字节操作函数指针类型*/
typedef void (*NdirSendByteType)(uint8_t data);
/*毫秒延时函数指针类型*/
typedef void (*NdirDelaymsType)(volatile uint32_t nTime);

  对于这几个函数我们根据样式定义就可以了,具体的操作可能与使用的硬件平台有关系。具体函数定义如下:

static void SendByteForNdir(uint8_t data)
{HAL_UART_Transmit(&ndirhuart,&data,1,1000);
}

  对于延时函数我们可以采用各种方法实现。我们采用的STM32平台和HAL库则可以直接使用HAL_Delay()函数。于是我们可以调用初始化函数如下:

/*上位通讯设备端口初始化配置*/
void Ndir_Init_Configuration(void)
{NDIR_USART_Init_Configuration();  //配置串口中断/*NDIR初始化配置函数*/NdirInitialization(&ndir,  //NDIR对象0x02, //模块地址SendByteForNdir, //发送数据操作函数HAL_Delay //毫秒延时操作函数);/*读软件版本*/ReadNDIRSoftVersion(&ndir,rxBuffer);
}

3.2、基于对象进行操作

  我们定义了对象变量并使用初始化函数给其作了初始化。接着我们就来考虑操作这一对象获取我们想要的数据。我们在驱动中已经封装了温度、浓度以及状态信息的操作函数,接下来我们使用这一驱动开发我们的应用实例。

/*NDIR数据操作*/
void Ndir_Comm_Process(void)
{/*从舒茨非分光红外气体检测模块读取浓度值*/ReadConcentrationData(&ndir,rxBuffer);/*从舒茨非分光红外气体检测模块读取内部温度值*/ReadTemperatureData(&ndir,rxBuffer);/*从舒茨非分光红外气体检测模块读取状态标志*/ReadNDIRStatusflags(&ndir,rxBuffer);
}

4、应用总结

  在我们的气体分析仪产品上,我们就是用来S-Module远红外气体传感器,也是基于我们的这一驱动实现的,通讯稳定,效果良好。

  在使用驱动程序时需要注意,驱动程序将解析程序封装到了数据发送函数中,可以直接调用数据读取函数就可以了,也可以单独调用解析函数来实现,具体工作方式可应需求实现。

欢迎关注:

外设驱动库开发笔记31:S-Modlue远红外气体传感器驱动相关推荐

  1. 外设驱动库开发笔记20:BME280压力湿度温度传感器驱动

    嵌入式产品开发中,我们常常会有检测环境温度.压力.湿度的需求.如果有一个集成有这3个传感器的元件,无疑将是很方便的.博世的BME280就能实现这一要求.在这一篇中我们将讨论BME280的驱动设计与实现 ...

  2. 外设驱动库开发笔记0:EPD总体设计

    在产品开发过程中,不可避免需要使用很多外部的元件及传感器,这些元器件也许是板载的,也许是板外的,但不管怎样,为其开发驱动程序都是必须的.每次都需要为这些元器件编写驱动程序.但每次重复编写调试很麻烦,于 ...

  3. 外设驱动库开发笔记13:MLX90614红外温度传感器驱动

    红外温度传感器一般用于非接触式的温度检测.在我们的系统中经常会有这样的需求.所以我们将其设计为通用的驱动库以备复用.这一篇我们将讲述MLX90614红外温度传感器驱动的设计与实现. 1.功能概述 ML ...

  4. 外设驱动库开发笔记12:TSEV01CL55红外温度传感器驱动

    有时候我们需要检测一些无法直接接触的器件的温度.为了实现这一需求,我们通常会选择红外温度传感器来实现这一功能.考虑到复用的问题,我们一般会将操作元器件的代码抽象为驱动函数以备调用.这里我们就来设计并实 ...

  5. 外设驱动库开发笔记54:外设库驱动设计改进的思考

      不知不觉中我们已经发布了五十多篇外设驱动的文章.前段时间有一位网友提出了一些非常中肯的建议,这也让我们开始考虑怎么优化驱动程序设计的问题.在这一篇中我们将来讨论这一问题. 1.问题分析   首先我 ...

  6. 外设驱动库开发笔记15:DHT11温湿度传感器驱动

    与DS18B20一样DHT11也是采用单总线,但所不同的是DHT11可同时实现温度和湿度的检测.在我们的产品中经常使用它来检测环境的温湿度信息.这一篇我们将设计并封装DHT11的驱动程序,以方便重复使 ...

  7. 外设驱动库开发笔记34:OLED显示屏驱动

      现在OLED显示屏在嵌入式系统中应用的越来越多.对于一些显示信息不太复杂,以显示信息为主的需求,我们一般会选择OLED显示屏.在这一篇中,我们将讨论OLED显示屏驱动的设计与实现. 1.功能概述 ...

  8. 外设驱动库开发笔记29:DS17887实时时钟驱动

    一些时候,在我们的嵌入式产品中需要记录时间,所以我们就需要获取时钟,当然实现的方式多种多样,有的MCU本身就有这一功能,不过精度较低.当我们的应用要求较高时就需要使用专门的实时时钟芯片,如DS1788 ...

  9. 外设驱动库开发笔记27:ESP8266无线通讯驱动

    我们的物联网产品所使用的平台都支持无线通讯,而且无线通讯本身更的成本较低,受到大家的欢迎.在本篇文章中,我们将详细讨论并实现ESP8266无线通讯模块的驱动. 1.功能概述 ESP8266是由乐鑫公司 ...

最新文章

  1. 互联网协议 — HTTP/2 超文本传输协议第 2 版
  2. 成功解决解决VM软件安装Linux的Ubuntu过程,开启Linux出现Oprating System not found错误
  3. gc就是fullgc吗 major_线上出现fullgc问题如何排查?
  4. 声明定义存储过程或者函数时,其中的 delimiter 关键字是干嘛的呢?
  5. 微信地图 leaflet 腾讯地图
  6. oracle有人用过fra吗,FRA(闪回恢复区)
  7. 源码编译安装PostgresSQL(11.5)
  8. 前端开发必看 | Vue在前端市场这么火,它到底是什么?
  9. Android TableLayout
  10. 「leetcode」40.组合总和II【回溯算法】详解!
  11. pycharm的python解释器选择_pycharm中配置python解释器
  12. 网易云音乐encseckey算法php,网易云音乐热评api
  13. python中浮点型占几个字节_python的浮点数占多少个字节
  14. jira迁移问题解决(实践篇)
  15. 初等行变换不改变列向量组的线性关系
  16. Rainbow Fart安装及设置其他语音包
  17. 【C语言】C语言的简介
  18. 手动查杀病毒的第一课
  19. 一套自动化无纸办公系统(OA+审批流)源码:带数据字典
  20. et199PHP,[原创]ET199带狗脱壳过程

热门文章

  1. Channel使用技巧
  2. HDU 5510 Bazinga 暴力匹配加剪枝
  3. 【转载】贝叶斯决策论
  4. 学习C++的五十条忠告
  5. 3D 鼠标跟随脚本详解
  6. 2.42死锁的处理策略一预防死锁
  7. 【剑指offer】面试题34:二叉树中和为某一值的路径(Java)
  8. 【剑指offer】面试题05:替换空格(java)
  9. pycharm python 模板配置_pycharm设置python脚本模板
  10. springboot导入项目依赖报错_最详细的 Spring Boot 多模块开发与排坑指南