http://www.geek-workshop.com/thread-1884-1-1.html
我们在上一讲中实现了一个TN901红外温度传感器51程序到Arduino程序的转换,如果代码越来越多这样程序的可维护性会随之降低,也不适合团度开发。我们应该把常用的文件封装成C++库,这样在复用的时候就会方便很多。 首先让我们来看下官方的C++类库是怎样的结构,以官方的LCD类库为例,如下图所示:
上面的文件大体是这样的结构:
文件名文件类型文件说明keywords.txtkeywords.txtArduino库色标文件LiquidCrystal.h.hC++头文件LiquidCrystal.cpp.cppC++程序文件以下几种文件的作用如下: .h 头文件:头文件作为一种包含功能函数、数据接口声明的载体文件,用于保存程序的声明(declaration),而定义文件用于保存程序的实现 (implementation)。 .cpp 文件:C++程序源文件主要的逻辑写在这里。 keywords.txt 文件:用来定义库在程序中显示关键字的颜色。 下面让我们来做个实际的例子将我们昨天写的程序改造成C++类库 可以点击这里
TH901.rar (992 Bytes, 下载次数: 174)
下载上一讲中的程序 首先我们来尝试下头文件的编写 有关宏定义的具体用法可以参见5楼zcbzjx的详细说明:)
#ifndef TH901_H //根据条件进行编译 #define TH901_H //我们在这中间添加程序 #endif //条件编译结束
#ifndef TH901_H //根据条件进行编译 #define TH901_H //我们在这中间添加程序 #endif //条件编译结束
我们在这中间添加程序主体的代码部分,首先来添加程序的头文件,需要引用什么都可以加进来
#include //引用相关的头文件
#include //引用相关的头文件
之后我们可以预定义一些需要的常量,这样维护起来比较方便,如果常量值改变只要统一修改这里就好
#define TN901_OTADDRESS 0x4c #define TN901_ETADDRESS 0x66 #define TN901_ENDADDRESS 0x0d
#define TN901_OTADDRESS 0x4c #define TN901_ETADDRESS 0x66 #define TN901_ENDADDRESS 0x0d
接下来我们来定义变量和声明程序的方法,需要外部调用和访问的就声明成public,不需要外部访问的就声明为private
class 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 ]; //数据数组 };
class 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 ]; //数据数组 };
这样我们一个头文件就写好了
/** * TN901 Library * 说明: 台湾燃太红外TN901传感器库 * 作者: 水乐天 * Email: [email]45268175@qq.com[/email] */ #ifndef TH901_H #define TH901_H #include //引用相关的头文件 #define TN901_OTADDRESS 0x4c #define TN901_ETADDRESS 0x66 #define TN901_ENDADDRESS 0x0d class 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 //程序结束
/** * TN901 Library * 说明: 台湾燃太红外TN901传感器库 * 作者: 水乐天 * Email: [email]45268175@qq.com[/email] */ #ifndef TH901_H #define TH901_H #include //引用相关的头文件 #define TN901_OTADDRESS 0x4c #define TN901_ETADDRESS 0x66 #define TN901_ENDADDRESS 0x0d class 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"
之后我们引用一些需要的库文件,需要哪些可以参见标准C++的库文件说明
#include "TN901.h" #include #include #include #include "Arduino.h"
#include "TN901.h" #include #include #include #include "Arduino.h"
然后我们逐一实现在头文件中定义的方法,注意类型要与定义类型相对应。所有的方法都要属于你定义的类名,格式如下
类名::方法名
类名::方法名
另外i啊我们要为程序的封装考虑程序应有的结构,总之是怎样使你的库使用起来最方便,在一般的逻辑中尽量减少调用的次数。我们可以把程序的逻辑分割为几个部分来书写。如:
1.初 始 化 2.实现功能 3.显示数据
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 ); }
//初始化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 ); //环境温度的第一个字节为0x66 if ( (Data [ 0 ]==TN901_ETADDRESS )&& (Data [ 4 ]==TN901_ENDADDRESS ) ) //每帧的最后一个字节为0x0d { GetData_ET ( ); } }
//读取数据 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 ); //环境温度的第一个字节为0x66 if ( (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 ]关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录