编写Arduino支持的C++类库

以下为摘抄的例子,已经亲自验证过,例子是正确的

我们在上一讲中实现了一个TN901红外温度传感器51程序到Arduino程序的转换,如果代码越来越多这样程序的可维护性会随之降低,也不适合团度开发。我们应该把常用的文件封装成C++库,这样在复用的时候就会方便很多。
首先让我们来看下官方的C++类库是怎样的结构,以官方的LCD类库为例,如下图所示:

image

上面的文件大体是这样的结构:

文件名文件类型文件说明
keywords.txtkeywords.txtArduino库色标文件
LiquidCrystal.h.hC++头文件
LiquidCrystal.cpp.cppC++程序文件

以下几种文件的作用如下:

.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");
}

好了,我们看到虽然我们花了一点时间编写了库文件,但是在我们使用程序的时候可以非常方便的调用,而且这样逻辑会比较清晰。呵呵。

最后送给大家一个小礼物,就是如何为我们的库编写色标文件,色标文件就是定义你的库中的方法在编译器中显示的颜色
没有色标文件的库显示起来是这样的:

image

我们可以看到库文件的类名和方法名都是黑色的这样看起来不是很清楚。加上色标文件之后是这样的

image

我们可以看到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\

这样当你重新打开官方编译器的时候可以看到如下的内容

image

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

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

相关文章

函数,游标与存储过程的综合应用

--在TOY数据库中完成以下操作use toygo--1、编写一个存储过程&#xff0c;接收任意一个订单号&#xff0c;打印订单的表头数据。格式如下&#xff1a;--(其中订单编号由订单日期订单号的字符串组成)--订单编号:20010520000001 订货日期:2001-05-20 订货人:拉尔森create pro…

HALCON示例程序check_blister.hdev药品胶囊检测

HALCON check_blister.hdev药品胶囊检测 示例程序源码&#xff08;加注释&#xff09; 显示、读入图片、设置显示字体等&#xff0c;之前的帖子已经介绍过了 dev_close_window () dev_update_off () read_image (ImageOrig, ‘blister/blister_reference’) dev_open_window_f…

【机器学习实战】——常见函数积累

目录 第二章 k近邻算法 1、array.sum(axies 1) : 2、array.argsort(axies0/1) 3、array.tile(mat,(m,n)) 4、dict.get(key,value) 5、sorted函数 6、string.strip()函数 7、string.split() 8、scatter&#xff08;&#xff09;函数 9、min()&max() 10、enumera…

安装oracle 11g 客户端,检查过程中报物理内存不足的解决

今早接到同事电话&#xff0c;说安装oracle 11g客户端的时候&#xff0c;在检查先决条件的时候&#xff0c;报错&#xff0c;说内存不足&#xff0c;但是本机的内存是2G&#xff0c;肯定够用&#xff1a;如图&#xff1a; 找了一圈&#xff0c;原来Oracle执行先决条件检查是依赖…

智能时代 软件赋能——2017中国软件技术大会

由中国科学院软件研究所、中科软科技股份有限公司联合主办&#xff0c;北京中科凯亚科技有限公司协办的第15届中国软件技术大会将于2017年12月在北京 国家会议中心隆重举行。 毋庸置疑&#xff0c;我们正在迈入智能时代&#xff0c;伴随着物联网、云计算、大数据、人工智能等智…

Arduino 代码机制

新建一个Arduino程序。可是建完就郁闷了&#xff0c;因为只看到了setup和loop函数&#xff0c;却没有基本的c函数。 void setup() {// put your setup code here, to run once: }void loop() {// put your main code here, to run repeatedly: }于是好奇心就来了&#xff0c;当…

Codeforces Round #401 (Div. 2) D. Cloud of Hashtags

题目链接&#xff1a;D. Cloud of Hashtags 题意&#xff1a; 给你n个字符串&#xff0c;让你删后缀&#xff0c;使得这些字符串按字典序排列&#xff0c;要求是删除的后缀最少 题解&#xff1a; 由于n比较大&#xff0c;我们可以将全部的字符串存在一个数组里面&#xff0c;然…

HALCON示例程序check_blister_mixed.hedv药品胶囊缺陷检测

HALCON示例程序check_blister_mixed.hedv药品胶囊缺陷检测 示例程序源码&#xff08;加注释&#xff09; 读入图片与显示相关设置 dev_close_window () read_image (Image, ‘blister/blister_mixed_reference’) dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHan…

php类与对象

1.类与对象 对象&#xff1a;实际存在该类事物中每个实物的个体。$a new User(); 实例化后的$a 引用&#xff1a;php的别名&#xff0c;两个不同的变量名字指向相同的内容 封装: 把对象的属性和方法组织在一个类&#xff08;逻辑单元&#xff09;里 继承&#xff1a;以原有的类…

【深度学习系列】基础知识、模型学习

基础知识 原创 【深度学习】——训练过程 原创 【深度学习】——BN层&#xff08;batch normalization&#xff09; 原创 【深度学习】——激活函数&#xff08;sigmoid、tanh、relu、softmax&#xff09; 原创 【深度学习】——损失函数 原创 【深度学习】——梯度下…

史陶比尔机器人的 LLI (Low Level Interface)

史陶比尔机器人的 LLI &#xff08;Low Level Interface&#xff09; 史陶比尔机器人拥有 Low Level Interface (LLI)接口选项. 在CS8C控制器的时代&#xff0c;LLI 接口仍然可用。这是一个选项接口。.这是除了VAL3编程语言之外的替代操作系统。通过C程序替代你的程序。 这里的…

阳狮集团与阿里巴巴全域营销伙伴关系再升级:数据和业务合作将更紧密

3月6日&#xff0c;阿里巴巴集团与全球领先的广告传播集团阳狮集团在上海开启了主题为“新局面新高度”新阶段的合作沟通&#xff0c;未来双方将进行更紧密的数据和业务层面的合作。阿里巴巴集团CMO、阿里妈妈总裁董本洪及阳狮媒体大中华区首席执行官张敬鸾就开放共赢达成共识&…

HALCON示例程序check_bottle_crate.hdev啤酒箱内酒瓶数检测

HALCON示例程序check_bottle_crate.hdev啤酒箱内酒瓶数检测 示例程序源码&#xff08;加注释&#xff09; 获取系统关于“空白区域储存的设置” get_system (‘store_empty_region’, StoreEmptyRegion)系统“空白区域储存”设置为 ‘false’ set_system (‘store_empty_regi…

#undef 标识符

#undef 是在后面取消以前定义的宏定义 该指令的形式为 #undef 标识符 其中&#xff0c;标识符是一个宏名称。如果标识符当前没有被定义成一个宏名称&#xff0c;那么就会忽略该指令。一旦定义预处理器标识符&#xff0c;它将保持已定义状态且在作用域内&#xff0c;直到程序结束…

[转]OpenGL库介绍

原帖地址&#xff1a;http://blog.csdn.net/yyyuhan/archive/2008/01/15/2045009.aspx 开发基于OpenGL的应用程序&#xff0c;必须先了解OpenGL的库函数。它采用C语言风格&#xff0c;提供大量的函数来进行图形的处理和显示。OpenGL库函数的命名方式非常有规律。所有OpenGL函数…

SQL Server优化50法

查询速度慢的原因很多&#xff0c;常见如下几种&#xff1a; 1、没有索引或者没有用到索引(这是查询慢最常见的问题&#xff0c;是程序设计的缺陷) 2、I/O吞吐量小&#xff0c;形成了瓶颈效应。 3、没有创建计算列导致查询不优化。 4、内存不足 5、网络速度慢 …

HALCON示例程序check_fish_stick_dimension.hdev生鱼棒尺寸测量;基于形态学的像素级精度尺寸测量

HALCON示例程序check_fish_stick_dimension.hdev基于形态学的像素级精度尺寸测量 示例程序源码&#xff08;加注释&#xff09; 关闭实时显示更新 dev_update_off () 关闭窗口 dev_close_window () 读入图片 read_image (Image, ‘food/fish_sticks_raw_01’) 根据给定长宽…

单片机平台的最小偏差圆弧插补算法

在CNC机床的G代码中&#xff0c;最常见的有G0、G1、G2、G3代码&#xff0c;分别表示直线和圆弧插补&#xff0c;直线插补对于单片机来说&#xff0c;比较容易实现&#xff0c;只需要将位移增量转换为脉冲增量然后输出给步进电机就可以了&#xff0c;但对于圆弧插补&#xff0c;…

javascript基础--数组排序

字符串的排序 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>数组排序</title><script>var arr [fliar, asdf, dfe, loii, yhhl];arr.sort();alert(arr);</script> </head>&…

【转】JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信&#xff0c;比如用ajax向一个不同的域请求数据&#xff0c;或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同&#xff0c;都被当作是不同的域。 下表给出了相对http://store.…