天天看點

外設驅動庫開發筆記31:S-Modlue遠紅外氣體傳感器驅動

  在氣體分析類産品中,我們經常會用到遠紅外氣體傳感器。我們就在碳氫類氣體成分分析中使用了S-Modlue遠紅外氣體傳感器。接下來,我們将讨論S-Modlue遠紅外氣體傳感器驅動的設計與實作。

1、功能概述

  S-MODULE EVO 使用非分散紅外檢測技術NDIR,內建穩定紅外光源,配置可靠性能的光電探測器,確定了傳感器檢測的穩定性能。

  S-MODULE采用的是RS232串行通訊接口,但其通訊接口對外隻有一個通訊引腳,是以實作的是半雙工模式。序列槽參數為:2400波特率,7位資料位,1位停止位,偶校驗。

  在應用層采用的則是Modbus ASCII協定。S-MODULE非分光紅外氣體子產品支援03和06功能碼。S-MODULE非分光紅外氣體子產品支援的Modbus參數如下:

外設驅動庫開發筆記31:S-Modlue遠紅外氣體傳感器驅動

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+3
 uint8_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遠紅外氣體傳感器驅動

如果閱讀這篇文章讓您略有所得,還請點選下方的【好文要頂】按鈕。

當然,如果您想及時了解我的部落格更新,不妨點選下方的【關注我】按鈕。

如果您希望更友善且及時的閱讀相關文章,也可以掃描上方二維碼關注我的微信公衆号【木南創智】

繼續閱讀