以下為摘抄的例子,已經親自驗證過,例子是正確的
我們在上一講中實現了一個TN901紅外溫度傳感器51程序到Arduino程序的轉換,如果代碼越來越多這樣程序的可維護性會隨之降低,也不適合團度開發。我們應該把常用的文件封裝成C++庫,這樣在復用的時候就會方便很多。
首先讓我們來看下官方的C++類庫是怎樣的結構,以官方的LCD類庫為例,如下圖所示:
上面的文件大體是這樣的結構:
文件名 | 文件類型 | 文件說明 |
keywords.txt | keywords.txt | Arduino庫色標文件 |
LiquidCrystal.h | .h | C++頭文件 |
LiquidCrystal.cpp | .cpp | C++程序文件 |
以下幾種文件的作用如下:
.h 頭文件:頭文件作為一種包含功能函數、數據接口聲明的載體文件,用于保存程序的聲明(declaration),而定義文件用于保存程序的實現 (implementation)。
.cpp 文件:C++程序源文件主要的邏輯寫在這里。
keywords.txt 文件:用來定義庫在程序中顯示關鍵字的顏色。
首先我們來嘗試下頭文件的編寫
#ifndef TH901_H //根據條件進行編譯
#define TH901_H//我們在這中間添加程序主體的代碼部分,首先來添加程序的頭文件,需要引用什么都可以加進來
#include <inttypes.h> //引用相關的頭文件//之后我們可以預定義一些需要的常量,這樣維護起來比較方便,如果常量值改變只要統一修改這里就好
#define TN901_OTADDRESS 0x4c
#define TN901_ETADDRESS 0x66
#define TN901_ENDADDRESS 0x0d//接下來我們來定義變量和聲明程序的方法,需要外部調用和訪問的就聲明成public,不需要外部訪問的就聲明為privateclass TN901 //定義類主體及類名
{
public: //以下定義為公共方法
short ET; //環境溫度輸出
short OT; //目標溫度輸出
void Init(int TN_Data,int TN_Clk,int TN_ACK); //程序初始化
void Read(); //讀取方法
void ReadData(char flag); //讀取指定地址的數據
int GetData(); //獲取數據
private: //以下定義為私有方法
int _dataPin; //數據引腳
int _clkPin; //時鐘引腳
int _ackPin; //反饋引腳
unsigned char Data[5]; //數據數組
};
#endif//程序結束
這樣我們一個頭文件就寫好了. 接下來我們來書寫程序的主體,就是CPP文件。
//首先我們引用已經寫好的程序頭文件
#include "TN901.h"
//之后我們引用一些需要的庫文件
#include "TN901.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"
然后我們逐一實現在頭文件中定義的方法,注意類型要與定義類型相對應。所有的方法都要屬于你定義的類名,格式如下 類名::方法名
另外i啊我們要為程序的封裝考慮程序應有的結構,總之是怎樣使你的庫使用起來最方便,在一般的邏輯中盡量減少調用的次數。我們可以把程序的邏輯分割為幾個部分來書寫。如:
1.初 始 化
2.實現功能
3.顯示數據
當然這個邏輯以具體的程序為準。
我們來嘗試寫第一個初始化的方法,這樣我們可以自己定義程序的端口。
//初始化TN901傳感器
void TN901::Init(int TN_Data,int TN_Clk,int TN_ACK)
{
//定義私有端口
_dataPin=TN_Data;
_clkPin=TN_Clk;
_ackPin=TN_ACK;pinMode(_clkPin, INPUT);
pinMode(_ackPin, OUTPUT);
digitalWrite(_ackPin,HIGH);
}
然后我們書寫程序的主要邏輯部分
//讀取數據
void TN901::Read()
{
digitalWrite(_ackPin,LOW);
ReadData(TN901_OTADDRESS);//目標溫度的第一個字節為0x4c
if((Data[0]==TN901_OTADDRESS)&&
(Data[4]==TN901_ENDADDRESS))//每幀的最后一個字節為0x0d
{
GetData_OT();
}delay(1); //等待1毫秒digitalWrite(_ackPin,LOW);
ReadData(TN901_ETADDRESS);//環境溫度的第一個字節為0x66if((Data[0]==TN901_ETADDRESS)&&
(Data[4]==TN901_ENDADDRESS))//每幀的最后一個字節為0x0d
{
GetData_ET();
}
}
最后我們逐一實現程序的運算過程
//讀取數據
void TN901::ReadData(char flag)
{
char i,j,k;
byte BitState = 0; //每次發七幀
for(k=0;k<7;k++)
{
for(j=0;j<5;j++) //每幀5個字節
{
for(i=0;i<8;i++)
{
int temp= digitalRead(_clkPin);
while(temp)
{
temp = digitalRead(_clkPin);
}
temp= digitalRead(_clkPin);
BitState= digitalRead(_dataPin);
Data[j]= Data[j]<<1;
Data[j]= Data[j]|BitState;while(!temp)
{
temp = digitalRead(_clkPin);
}
}
}
if(Data[0]==flag) k=8;
}digitalWrite(_ackPin,HIGH);
}//計算環境溫度
void TN901::GetData_ET()
{
ET=(Data[1]<<8)|Data[2];
ET = int(((float)ET/16 - 273.15)*100);
}//計算目標溫度
void TN901::GetData_OT()
{
OT=(Data[1]<<8)|Data[2];
OT = int(((float)OT/16 - 273.15)*100);
}
之后我們來嘗試為我們的庫編寫一個范例程序來測試我們的程序是否運行正常。
#include <TN901.h> //引用庫文件
TN901 tn; //實 例 化
void setup()
{
Serial.begin(9600);
tn.Init(7,9,8); //初 始 化
}void loop()
{
tn.Read(); //數據讀取
SerialValue();
delay(200);
}void SerialValue()
{
Serial.print("OT: ");
Serial.print(tn.OT, DEC); //輸出目標溫度
Serial.println(" C");
Serial.print("ET: ");
Serial.print(tn.ET, DEC); //輸出環境溫度
Serial.println(" C");
}
好了,我們看到雖然我們花了一點時間編寫了庫文件,但是在我們使用程序的時候可以非常方便的調用,而且這樣邏輯會比較清晰。呵呵。
最后送給大家一個小禮物,就是如何為我們的庫編寫色標文件,色標文件就是定義你的庫中的方法在編譯器中顯示的顏色
沒有色標文件的庫顯示起來是這樣的:
我們可以看到庫文件的類名和方法名都是黑色的這樣看起來不是很清楚。加上色標文件之后是這樣的
我們可以看到TN901這樣的類名都被加亮了這樣看起來要清楚許多。
實現這個需要定義一個色標文件放在庫文件的目錄中,格式如下
#######################################
# Syntax Coloring Map For 你的類名
##############################################################################
# Datatypes (KEYWORD1) 數據類型關鍵字
#######################################TN901 KEYWORD1#######################################
# Methods and Functions (KEYWORD2) 方法類型關鍵字
#######################################Init KEYWORD2
Read KEYWORD2
ReadData KEYWORD2
GetData KEYWORD2#######################################
# Constants (LITERAL1) 常量類型關鍵字
#######################################ET LITERAL1
OT LITERAL1
這樣我們的色標文件就寫好了,我們把它保存成文件名為keywords.txt的文件放在庫文件目錄下就可以了。
當我們些庫文件全部做好了之后我們就可以把這些文件放在,這樣的目錄下
energia:energia-0101E0008\hardware\msp430\libraries\
arduino:arduino-1.0.1-windows\arduino-1.0.1\libraries\
這樣當你重新打開官方編譯器的時候可以看到如下的內容