外设驱动库开发笔记32:HLPM025K3 PM2.5传感器驱动

  现在人们对大气环境及室内环境都比较关注。PM2.5在生活中也是常见的词汇。在有些产品中就要求检测PM2.5的数值。检测PM2.5的手段多种多样,在要求不高时我们通常可以采用激光模块。在这一篇中,我们将讨论HLPM025K3 PM2.5传感器驱动的设计与实现。

1、功能概述

  HLPM025K3传感器采用激光散射原理。即令激光照射在空气中的悬浮颗粒物上产生散射,同时在某一特定角度收集散射光,得到散射光强随时间变化的曲线。通过稳定的气 体对流系统,使外界空气均匀的通过自主研发设计的风路,同时在风路中设有多个精密的光学传感器,可以精确的获得粒子的尺寸、速度和质量等信息,加以统计学原理,继而计算出总的粒子质量,从而实时的得到空气中所被关注的粒子的浓度,达到检测PM2.5以及PM10的目的。其基本原理如下图所示:

  HLPM025K3传感器采用串行通讯,采用6脚通讯接口,其引脚定义如下图所示:

  HLPM025K3传感器采用TTL串行通讯,采用9600的波特率,8为数据位,1为停止位,无校验的方式。HLPM025K3传感器通讯采取主动发送模式,0.8到1.2秒发送一次数据。其数据包含7个字节,具体格式如下:

  其中,校验位=PM2.5(H)+PM2.5(L)+PM10(H)+PM10(L)
  接收到的数据按公式计算后得到 PM2.5 和 PM10 的值。
  PM2.5 = (PM2.5(H)×256 + PM2.5(L))×0.1;
  PM10 = (PM2.5(H)×256 + PM2.5(L))×0.1;

2、驱动设计与实现

  我们已经了解了HLPM025K3型PM2.5传感器的基本情况。在这一节中我们将设计并实现HLPM025K3型PM2.5传感器的驱动。

2.1、对象定义

  在使用一个对象之前我们需要获得一个对象。同样的我们想要HLPM025K3 PM2.5传感器就需要先定义HLPM025K3 PM2.5传感器的对象。

2.1.1、对象的抽象

  我们要得到HLPM025K3 PM2.5传感器对象,需要先分析其基本特性。一般来说,一个对象至少包含两方面的特性:属性与操作。接下来我们就来从这两个方面思考一下HLPM025K3 PM2.5传感器的对象。
  先来考虑属性,作为属性肯定是用于标识或记录对象特征的东西。我们来考虑HLPM025K3 PM2.5传感器对象属性。我们将测量数据作为对象的属性,因为他们表示了对象当前的状态。
  接着我们还需要考虑HLPM025K3 PM2.5传感器对象的操作问题。对象本身除了接受数据并没有什么需要操作的。我们使用队列来存储接收到的数据,所以入队出队过程可看作是其操作。
  根据上述我们对HLPM025K3 PM2.5传感器的分析,我们可以定义HLPM025K3 PM2.5传感器的对象类型如下:

/*定义HLPM025K3对象类型*/
typedef struct HlpmObject {float pm25;		//PM2.5测量值float pm100;	//PM10测量值struct DwinRxBuffer{uint8_t queue[HLPMRxBufferLength];	//键值存储队列uint8_t pRead;									//读队列指针uint8_t pWrite;									//写队列指针uint16_t (*DeQueue)(struct HlpmObject *hlpm,uint8_t *rxBuf);	//出队操作void (*EnQueue)(struct HlpmObject *hlpm,uint8_t rData);				//入队操作}rxBuffer;					//定义接收缓存队列
}HlpmObjectType;

2.1.2、对象初始化

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

/*HLPM对象初始化函数*/
void HlpmInitialization(HlpmObjectType *hlpm)
{if(hlpm==NULL){return;}hlpm->pm25=0.0;hlpm->pm100=0.0;hlpm->rxBuffer.pRead=0;hlpm->rxBuffer.pWrite=0;hlpm->rxBuffer.EnQueue=BufferDataEnQueue;hlpm->rxBuffer.DeQueue=BufferDataDeQueue;
}

2.2、对象操作

  我们已经完成了HLPM025K3 PM2.5传感器对象类型的定义和对象初始化函数的设计。但我们的主要目标是获取对象的信息,接下来我们还要实现面向HLPM025K3 PM2.5传感器的各类操作。
  由于HLPM025K3 PM2.5传感器对象是自主发送,所以我们需要做的就是接收消息并解析。

/*解析PM2.5和PM10的数据*/
bool ParsingPMData(HlpmObjectType *hlpm)
{uint16_t length=0;uint8_t receivedData[7]={0};bool isValid=false;length=hlpm->rxBuffer.DeQueue(hlpm,receivedData);if(length>0){isValid=CheckDataIsValid(receivedData);if(isValid){hlpm->pm25=SynthesisPMValue(receivedData+1);hlpm->pm100=SynthesisPMValue(receivedData+3);}}return isValid;
}

3、驱动的使用

  我们已经设计并实现了HLPM025K3 PM2.5传感器对象的驱动程序。接下来我们设计一个简单的应用来验证这一驱动程序是否可行。

3.1、声明并初始化对象

  使用基于对象的操作我们需要先得到这个对象,所以我们先要使用前面定义的HLPM025K3 PM2.5传感器对象类型声明一个HLPM025K3 PM2.5传感器对象变量,具体操作格式如下:
  HlpmObjectType hlpm;
  声明了这个对象变量并不能立即使用,我们还需要使用驱动中定义的初始化函数对这个变量进行初始化。这个初始化函数所需要的输入参数如下:
  HlpmObjectType *hlpm,HLPM025K3 PM2.5传感器对象
  这个对象变量我们已经定义了,所以只需输入这个对象就好了。于是我们可以调用初始化函数如下:
  HlpmInitialization(&hlpm);
  对于串口通讯,我们可以使用多种方式,我们在此使用中断来接收数据,具体实现如下:

//数据接收中断处理函数
void HLPM_USART_ReceiveDataHandle(void)
{uint8_t res;// 接收寄存器为空,等待字节被对应的串口完全接收 if(__HAL_UART_GET_FLAG(&hlpmhuart,UART_FLAG_RXNE)!=RESET){   // 获取接收到的字节数HAL_UART_Receive(&hlpmhuart,&res,1,1000);hlpm.rxBuffer.EnQueue(&hlpm,res);__HAL_UART_CLEAR_FLAG(&hlpmhuart,UART_FLAG_RXNE);}
}

3.2、基于对象进行操作

  我们定义了对象变量并使用初始化函数给其作了初始化。接着我们就来考虑操作这一对象获取我们想要的数据。我们在驱动中已经将获取数据并转换为转换值的比例值,接下来我们使用这一驱动开发我们的应用实例。

/*数据获取*/
void GetDataFromHLPM025K3(void)
{float pm25Value;float pm10Value;ParsingPMData(&hlpm);pm25Value=hlpm.pm25;pm10Value=hlpm.pm100;
}

4、应用总结

  我们已经设计并实现了HLPM025K3 PM2.5传感器对象的驱动程序,并且设计了简单的验证程序。HLPM025K3 PM2.5传感器的操作本身比较简单,只需要通过串口获取数据就可以了。
  驱动中采用了FIFO队列存储接收到的HLPM025K3 PM2.5传感器数据,主要是考虑到被动接收的情况下,能够保证正确的解析数据。如果不使用也是没有问题的,本身不是HLPM025K3 PM2.5传感器对象所必需的。

欢迎关注:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外设驱动库开发笔记33:LCD1602液晶显示屏驱动

LCD1602是一种工业字符型液晶,能够同时显示16x02即32个字符。LCD1602液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,即可以显示出图形。在这一章我们就来讨论LCD1602液晶显示屏驱动的设计与实现。 1、功能概述 LCD1602液…

滤波器开发之四:基于算术平均的中值滤波器

在信号采集系统中,除了我们感兴趣的数据外,难免会有一些来自于环境的干扰信号。但我们总希望我们得到的数据是纯净而真实的,为了达到这个目标,我们不得不想办法去除这些干扰信号,于是滤波器就成为我们必不可少的帮手。…

LwIP应用开发笔记之十一:LwIP带操作系统UDP服务器

我们已经实现了在FreeRTOS系统上的LwIP的移植工作,但只是简单的在系统平台上跑了起来。我们还希望能做更多的事情,这一节我们就在FreeRTOS系统上实现基于LwIP的UDP服务器。 1、UDP协议简述 UDP协议全称是用户数据报协议,在网络中它与TCP协议…

滤波器开发之五:基于算术平均的限幅滤波器

通过AD采集数据时,我们总是希望采集到的数据是纯净而真实的,而实际上环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响。所以软件实现的数字滤波器应运而生,这一篇我…

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

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

外设驱动库开发笔记35:迪文触摸屏驱动

有些时候嵌入式系统也需要显示更为复杂的图形,需要更丰富的数据展示。为此,我们需要更大,色彩更丰富,带触屏的显示屏,当然性价比更高就最好了。在我们的项目中遇到此类需求,我们有时会选择DWIN触摸屏。在本…

快速实现一个室内空气质量检测仪

冬天我们大多会关闭门窗,而依靠暖通空调设备来维持室内温度。而在保证居室温度的同时,我们也希望保持居室内大气环境的健康度。鉴于此,我们设计了一个简单的室内空气质量检测器。 1、系统概述 我们依靠暖通空调设备来维持室内温度、湿度和通…

外设驱动库开发笔记36:NTC负温度系数热电阻测温驱动

在嵌入式产品中,温度检测非常常见。在成本比较敏感而精度要求较低时,NTC电阻是个不错的选择。在这一篇中,我们将讨论如何和设计并实现一个通用的NTC驱动,以便在后续的项目中更方便的复用。 1、功能概述 NTC是指随温度上升电阻呈指…

外设驱动库开发笔记37:S1336-5BQ光敏二极管作为光度计驱动

光敏二极管能够实现很多应用,用于光度检测即是其一。我们在一些产品中就曾使用S1336-5BQ光敏二极管进行光度值检测。所以在本篇中,我们将讨论如何设计并实现S1336-5BQ光敏二极管用于光度检测的驱动。 1、功能概述 根据相关的资料,光电二极管…

PID控制器改进笔记之六:改进PID控制器之参数设定

前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。这篇中我们来讨论改进PID控制…

软件设计开发笔记1:基于状态机的程序设计

在编码实现的过程中,我们会经常使用到条件判断结构,而且使用起来很方便。但是在需要转移的状态比较多,或是条件比较复杂时,我们就可能需要很长的条件判断结构来处理。不过,过于复杂的条件判断结构会给代码的编写和维护…

外设驱动库开发笔记38:RTD热电阻测温驱动

我们已经讨论过多种温度检测方式,但我们尚未关注热电阻温度检测,但热电阻测温在工业环境中是非常常见的。尽管有很多集成的数字式的热电阻接口元器件,但这些器件不但成本较高,灵活性也大打折扣。所以我们有时会使用更简单灵活的电…

外设驱动库开发笔记39:按键操作驱动

按键在我们的项目中是经常使用到的组件。一般来说,我们都是在用到按键时直接针对编码,但这样每次都做很多重复性的工作。所以在这里我们考虑做一般性抽象得到一个可应用于按键操作的通用性驱动程序。 1、功能概述 按键操作在我们的产品种经常用到&#…

外设驱动库开发笔记40:AT25xxx外部存储器驱动

我们在前面开发过AT24CXX系列EEPROM存储器,它使用的是I2C接口。不过有时候我们也会使用SPI接口的EEPROM存储器。在这一篇我们将来讨论AT25XXX系列EEPROM存储器的驱动设计、实现及使用。 1、功能概述 AT25XXX系列EEPROM存储器采用SPI接口,因其操作简单且…

闪存中的键值对:无文件系统 minINI

许多嵌入式系统应用需要以持久的方式存储某种数据:校准值、设置或日志信息。对于较少的数据量,使用外部存储器或文件系统是一种过度大材小用。在许多系统中,我使用minINI以“ini-file”的方式存储键值解析,但它需要使用某种文件系…

外设驱动库开发笔记41:ADS1256 ADC驱动

我们经常会碰到多通道AD采集的需求,有时候甚至需要高精度的ADC器件。本篇我们将来设计并实现ADS1256模数转换器的驱动。并简单讨论该驱动使用方式。 1、功能概述 ADS1256是TI公司推出的一款低噪声高分辨率的24位Sigma-Delta(E-v)模数转换器(ADC)。E-vADC与传统的逐…

PID参数自整定库之一:继电反馈整定算法

在前述的篇章中,我们实现了PID控制器并在后续对其进行了改进。但作为经典PID控制器还存在PID参数整定的问题。通常我们可以采取人工整定的办法,但人工整定涉及到比较专业的知识,而且找到合适的参数本身也不是一件容易的事,所以人们…

外设驱动库开发笔记42:DAC8552 DAC驱动

模拟信号输出是经常会遇到的应用需求,解决的办法应多种,但我们使用最多的还是数模转换。对于不同的数模转换器我们需要为其编写适用的驱动程序,在这一篇中我们就来考虑如何实现DAC8552高精度模数转换器的驱动程序。 1、功能概述 该DAC8552是…

软件设计开发笔记2:基于QT设计串口调试工具

串口通信是我们经常会遇到的问题。很多时候当我们设计一个串口应用时,我们希望有一个简便的、可视的方式来验证它。这一篇中我们就来基于QT设计一个串口调试工具。 1、概述 在开始软件设计之前,我们来简略地分析一下这样一个小软件其要包含的主要内容有…

外设驱动库开发笔记43:GPIO模拟SPI驱动

SPI总线是我们常用的串行设备接口,一般情况下我们都会适应硬件SPI接口,但有些时候当硬件端口不足时,我们也希望可以使用软件来模拟SPI硬件接口,特别是要求不是很高的时候。在这一篇中我们将来讨论如何使用GPIO和软件来模拟SPI通讯…