在氣體分析類產(chǎn)品中,我們經(jīng)常會用到遠(yuǎn)紅外氣體傳感器。我們就在碳?xì)漕悮怏w成分分析中使用了S-Modlue遠(yuǎn)紅外氣體傳感器。接下來,我們將討論S-Modlue遠(yuǎn)紅外氣體傳感器驅(qū)動的設(shè)計與實(shí)現(xiàn)。
1、功能概述
??S-MODULE EVO 使用非分散紅外檢測技術(shù)NDIR,集成穩(wěn)定紅外光源,配置可靠性能的光電探測器,確保了傳感器檢測的穩(wěn)定性能。
??S-MODULE采用的是RS232串行通訊接口,但其通訊接口對外只有一個通訊引腳,所以實(shí)現(xiàn)的是半雙工模式。串口參數(shù)為:2400波特率,7位數(shù)據(jù)位,1位停止位,偶校驗(yàn)。
??在應(yīng)用層采用的則是Modbus ASCII協(xié)議。S-MODULE非分光紅外氣體模塊支持03和06功能碼。S-MODULE非分光紅外氣體模塊支持的Modbus參數(shù)如下:
2、驅(qū)動設(shè)計與實(shí)現(xiàn)
??我們知道S-Module遠(yuǎn)紅外氣體傳感器采用基于半雙工RS232接口的Modbus ASCII通訊協(xié)議。接下來我們將基于它的協(xié)議規(guī)則設(shè)計并實(shí)現(xiàn)驅(qū)動程序。
2.1、對象定義
??在使用一個對象之前我們需要獲得一個對象。同樣的我們想要S-Modlue遠(yuǎn)紅外氣體傳感器就需要先定義S-Modlue遠(yuǎn)紅外氣體傳感器的對象。
2.1.1、對象的抽象
??我們要得到S-Modlue遠(yuǎn)紅外氣體傳感器對象,需要先分析其基本特性。一般來說,一個對象至少包含兩方面的特性:屬性與操作。接下來我們就來從這兩個方面思考一下S-Modlue遠(yuǎn)紅外氣體傳感器的對象。
??先來考慮屬性,作為屬性肯定是用于標(biāo)識或記錄對象特征的東西。我們來考慮S-Modlue遠(yuǎn)紅外氣體傳感器對象的屬性。首先Modbus協(xié)議對象都有站地址用以標(biāo)識不同的設(shè)備,所以我們將設(shè)備地址作為對象的一個屬性。此外,狀態(tài)信息、溫度、濃度等實(shí)時信息表示了對象當(dāng)前的工作狀態(tài),所以我們將這些參數(shù)也作為對象的屬性。
??接著我們還需要考慮S-Modlue遠(yuǎn)紅外氣體傳感器對象的操作問題。我們需要從S-Modlue遠(yuǎn)紅外氣體傳感器獲取數(shù)據(jù)和下發(fā)命令,就需要通過串口發(fā)送消息,但串口的處理與具體的平臺相關(guān),所以我們將其作為對象的操作。此外,在操作對象的過程中需要控制時序,所以延時操作函數(shù)必不可少,而延時操作函數(shù)往往依賴于具體的軟硬件平臺,所以將延時函數(shù)作為對象的操作。
??根據(jù)上述我們對S-Modlue遠(yuǎn)紅外氣體傳感器的分析,我們可以定義S-Modlue遠(yuǎn)紅外氣體傳感器的對象類型如下:
/*定義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、對象初始化
??我們知道,一個對象僅作聲明是不能使用的,我們需要先對其進(jìn)行初始化,所以這里我們來考慮S-Modlue遠(yuǎn)紅外氣體傳感器對象的初始化函數(shù)。一般來說,初始化函數(shù)需要處理幾個方面的問題。一是檢查輸入?yún)?shù)是否合理;二是為對象的屬性賦初值;三是對對象作必要的初始化配置。據(jù)此我們設(shè)計S-Modlue遠(yuǎn)紅外氣體傳感器對象的初始化函數(shù)如下:
/*NDIR初始化配置函數(shù)*/
void NdirInitialization(NdirObjectType *ndir, //NDIR對象
uint8_t moduleAddress, //模塊地址
NdirSendByteType send, //發(fā)送數(shù)據(jù)操作函數(shù)
NdirDelaymsType delayms //毫秒延時操作函數(shù)
)
{
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、對象操作
??我們已經(jīng)完成了S-Modlue遠(yuǎn)紅外氣體傳感器對象類型的定義和對象初始化函數(shù)的設(shè)計。但我們的主要目標(biāo)是獲取對象的信息,接下來我們還要實(shí)現(xiàn)面向S-Modlue遠(yuǎn)紅外氣體傳感器的各類操作。
??對于S-Modlue遠(yuǎn)紅外氣體傳感器對象來說,最基本的操作就是向其發(fā)送操作命令或數(shù)據(jù)消息。這是基于串口的Modbus ASCII協(xié)議的數(shù)據(jù)通訊,基于此我們可編寫響應(yīng)的數(shù)據(jù)發(fā)送操作函數(shù)如下:
/*發(fā)送數(shù)據(jù)給舒茨非分光紅外氣體檢測模塊(讀寫數(shù)據(jù))*/
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];//含校驗(yàn)碼
for(int i=0;i6]=CheckSumCalc(txData,length);
uint8_t objData[14];
uint16_t cLength=ConvertHexArrayToASCIICharArray(rawData,length+1,objData);
sendDataArray[sendDataAmount++]=':';
for(int i=0;i0x0D;
sendDataArray[sendDataAmount++]=0x0A;
for(uint16_t sendDataIndex=0;sendDataIndex/*發(fā)送一個字節(jié)*/
ndir->SendByte(sendDataArray[sendDataIndex]);
}
}
3、驅(qū)動的使用
??我們已經(jīng)實(shí)現(xiàn)了S-Module遠(yuǎn)紅外氣體傳感器的驅(qū)動程序,但我們還需要驗(yàn)證一下它的正確性,所以在本節(jié)中我們就來設(shè)計一個簡單的驗(yàn)證應(yīng)用。
3.1、聲明并初始化對象
??使用基于對象的操作我們需要先得到這個對象,所以我們先要使用前面定義的S-Modlue遠(yuǎn)紅外氣體傳感器對象類型聲明一個S-Modlue遠(yuǎn)紅外氣體傳感器對象變量,具體操作格式如下:
??NdirObjectType ndir;
??聲明了這個對象變量并不能立即使用,我們還需要使用驅(qū)動中定義的初始化函數(shù)對這個變量進(jìn)行初始化。這個初始化函數(shù)所需要的輸入?yún)?shù)如下:
NdirObjectType *ndir, //NDIR對象
uint8_t moduleAddress, //模塊地址
NdirSendByteType send, //發(fā)送數(shù)據(jù)操作函數(shù)
NdirDelaymsType delayms //毫秒延時操作函數(shù)
??對于這些參數(shù),對象變量我們已經(jīng)定義了。模塊地址根據(jù)我們實(shí)際的使用情況輸入就好了。主要的是我們需要定義幾個函數(shù),并將函數(shù)指針作為參數(shù)。這幾個函數(shù)的類型如下:
/*發(fā)送一個字節(jié)操作函數(shù)指針類型*/
typedef void (*NdirSendByteType)(uint8_t data);
/*毫秒延時函數(shù)指針類型*/
typedef void (*NdirDelaymsType)(volatile uint32_t nTime);
??對于這幾個函數(shù)我們根據(jù)樣式定義就可以了,具體的操作可能與使用的硬件平臺有關(guān)系。具體函數(shù)定義如下:
static void SendByteForNdir(uint8_t data)
{
HAL_UART_Transmit(&ndirhuart,&data,1,1000);
}
??對于延時函數(shù)我們可以采用各種方法實(shí)現(xiàn)。我們采用的STM32平臺和HAL庫則可以直接使用HAL_Delay()函數(shù)。于是我們可以調(diào)用初始化函數(shù)如下:
/*上位通訊設(shè)備端口初始化配置*/
void Ndir_Init_Configuration(void)
{
NDIR_USART_Init_Configuration(); //配置串口中斷
/*NDIR初始化配置函數(shù)*/
NdirInitialization(&ndir, //NDIR對象
0x02, //模塊地址
SendByteForNdir, //發(fā)送數(shù)據(jù)操作函數(shù)
HAL_Delay //毫秒延時操作函數(shù)
);
/*讀軟件版本*/
ReadNDIRSoftVersion(&ndir,rxBuffer);
}
3.2、基于對象進(jìn)行操作
??我們定義了對象變量并使用初始化函數(shù)給其作了初始化。接著我們就來考慮操作這一對象獲取我們想要的數(shù)據(jù)。我們在驅(qū)動中已經(jīng)封裝了溫度、濃度以及狀態(tài)信息的操作函數(shù),接下來我們使用這一驅(qū)動開發(fā)我們的應(yīng)用實(shí)例。
/*NDIR數(shù)據(jù)操作*/
void Ndir_Comm_Process(void)
{
/*從舒茨非分光紅外氣體檢測模塊讀取濃度值*/
ReadConcentrationData(&ndir,rxBuffer);
/*從舒茨非分光紅外氣體檢測模塊讀取內(nèi)部溫度值*/
ReadTemperatureData(&ndir,rxBuffer);
/*從舒茨非分光紅外氣體檢測模塊讀取狀態(tài)標(biāo)志*/
ReadNDIRStatusflags(&ndir,rxBuffer);
}
4、應(yīng)用總結(jié)
??在我們的氣體分析儀產(chǎn)品上,我們就是用來S-Module遠(yuǎn)紅外氣體傳感器,也是基于我們的這一驅(qū)動實(shí)現(xiàn)的,通訊穩(wěn)定,效果良好。
??在使用驅(qū)動程序時需要注意,驅(qū)動程序?qū)⒔馕龀绦蚍庋b到了數(shù)據(jù)發(fā)送函數(shù)中,可以直接調(diào)用數(shù)據(jù)讀取函數(shù)就可以了,也可以單獨(dú)調(diào)用解析函數(shù)來實(shí)現(xiàn),具體工作方式可應(yīng)需求實(shí)現(xiàn)。
評論