博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Arduino开发实战指南:LabVIEW卷》——2.2 Arduino程序结构及基本函数
阅读量:6993 次
发布时间:2019-06-27

本文共 10727 字,大约阅读时间需要 35 分钟。

本节书摘来自华章计算机《Arduino开发实战指南:LabVIEW卷》一书中的第2章,第2.2节,作者:余崇梓著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 Arduino程序结构及基本函数

2.2.1 Arduino程序结构

Arduino编程语言的基本结构非常简单,包含至少两个部分或者叫两个函数。其他语句及函数都被包括在这两个不可或缺的函数中。
代码清单2-1:Arduino程序结构

void setup()                                //setup函数{   statements;}Void loop()                                 // loop函数{   statements;}

setup函数负责准备工作,loop函数负责执行。两个函数都是程序正常运行所必需的

部分。
setup函数跟随在程序最开始的变量声明之后,它是程序运行的第一个函数,只运行一次,主要用来设置端口模式(pinMode)或者初始化串口通信。
setup函数只在程序开始的时候调用一次,用它来初始化端口模式,或者开始串口通信。即使程序中没有实际要运行的语句也需要有setup函数。
代码清单2-2:setup函数结构

void setup(){      pinMode(pin,OUTPUT);    //设置“pin”为输出端口}

loop函数跟随其后,主要包含将连续执行的代码,比如:读取(输入)、触发(输出)等。这个函数是所有Arduino程序的核心,它包含了大量的程序任务,使程序能够控制Arduino板。

代码清单2-3:loop函数结构

void loop(){     digitalWrite(pin,HIGH);  // 将“pin”置高电平     delay(1000);             // 保持1s     digitalWrite(pin,LOW);   // 将“pin”置低电平     delay(1000);             // 保持1s}

2.2.2 Arduino数据类型及运算符

Arduino IDE 开发语言使用的是C语言,所以Arduino的数据类型及运算符同基本C语言一样,这里进行简单介绍。
1.数据类型
1)整型
整型数据分为短整型和长整型,关键字分别为int和long,短整型为16位值,范围为32767~-32768;长整型为32位值,范围为2147483647~-2147483648。
2)字符型
字符型关键字为char。char在内存中占一个字节。
3)实型(浮点型)
实型数据分为单精度型和双精度型,关键字分别为float和double,float为32位值,范围为3.4E+38~-3.4E+38;double为64位值,范围为1.7E+308~-1.7E+308。
4)枚举型
枚举型关键字为enum。
2.常量
常量为程序运行中值不能改变的量。如:-1、23、'd'。常量也可以用一个标识符代表,例如:#define n30,定义n代表常量30。
Arduino中有几种特别的常量。
1)TRUE/FALSE常量
对于布尔常量,FALSE一般定义为0;TRUE经常定义为1,有时候也定义为非0。
代码清单2-4:TRUE/FALSE常量

if(b== TRUE);{     doSomething;}

2)HIGH/LOW常量

这些常量定义端口为HIGH或者LOW,经常用来读取或者写入数字端口。HIGH一般定义为逻辑值1、ON或者5V;而LOW一般定义为逻辑值0、OFF或者0V。
如:digitalWrite(13,HIGH)
3)INPUT/OUTPUT
这些常量用在pinMode()函数中,定义端口的模式为输入或者输出。
如:pinMode(13,OUTPUT);
3.变量
变量是一种通过命名及存储数值以便被后面程序使用的方法。下面的代码声明了一个命名为inputVariable的变量,并且将模拟输入端口2的值赋给该变量。所有的变量在使用前必须声明。

int inputVariable = 0;          //声明变量,并赋初始值为0intputVariable = analogRead(2); //将模拟输入端口2的值赋给变量

变量可以在程序最开始即void setup()之前,在某个函数内,或者某个语句(比如for语句)内声明。变量声明的地方决定了变量的作用域。

全局变量在setup()函数之前声明,这个全局变量可以被程序中的所有函数和语句
使用。
局部变量在函数内部或者for循环的一部分中被声明。它的作用域也只有在函数内部或者for循环内部。
代码清单2-5展示了不同的变量使用情况。
代码清单2-5:变量的使用

int value;            //value可以在任何函数中使用void setup(){                       //不需要setup}void loop(){      for(int i=0;i<20;)         {          i++;         //i只能在for loop中使用         }       float f;         //f只能在loop中使用}

4.运算符

运算符按照优先级顺序由上向下排列,如表2-1所示。
image
image
image

5.注释

在Arduino程序中有两种注释符,分别为:
块注释,以“/”开头并以“/”结束的字符串,两者之间的部分为注释。
行注释,使用“//”进行行注释,其后的字符串为注释。
注释可以出现在程序任何位置,添加注释可以帮助理解程序。
2.2.3 Arduino的控制语句
Arduino程序流程控制语句也与C语言中的流程控制语句相同,这里做一下简单介绍。
1.条件选择语句
(1)if语句
一般形式如下:

if (condition) statement;或者if (condition){     compound statement;}

if语句流程图如图2-10所示。

image

代码清单2-6为if语句使用示例。
代码清单2-6:if语句示例

#include 
#define TRUE 1#define FALSE 0main (){ int i; if (TRUE) { printf ("This is always printed"); } if (FALSE) { printf ("This is never printed"); }}

(2)if...else语句

一般形式如下:

if (condition) statement1; else statement2;或者if (condition){     statements;}else{     statements;}

if...else语句的流程图如图2-11所示。

image

图2-11 if...else语句的流程图

代码清单2-7:if...else语句示例

#include 
main(){ int i; scanf ("%ld",i); if (i > 0) { printf ("That number was positive!"); } else { printf ("That number was negative or zero!"); }}

(3)switch语句

一般形式为:

switch (int or char expression){   case constant expression 1 : statement 1;                   break;          /* optional */   case constant expression 2 : statement 2;                   break;          /* optional */   case constant expression n : statement n;                   break;          /* optional */   default : default statement;                   break;}

对于switch条件语句,如果找到相同的结果值则执行case内的程序语句,当执行完case语句后,并不会直接离开switch条件语句,还是会住下继续执行其他case语句和default语句,这种情形称为“失败经过”(Falling Through)现象。

因此,在每一条case语句最后,必须加上break语句来结束switch语句,才可以避免“失败经过”的情况。default语句可放在switch条件语句的任何位置,如果找不到吻合的结果值,最后会执行default语句,除非摆在最后时,才可以省略default语句内的break语句,否则还是必须加上break语句。
代码清单2-8:switch语句示例

#include 
main(){ for(int i=0; i<3; i++) { switch(i) { default: printf("%d", i); case 1: printf("%d", i); break; case 2: printf("%d", i); } } return 0;}

2.循环语句

(1)while循环语句
一般形式为:

while (condition){    statements;}

while语句的流程图如图2-12所示。

image

代码清单2-9:while语句示例

/* count all the spaces in an line of input */#include 
main(){ char ch; short count = 0; printf ("Type in a line of text\n"); while ((ch = getchar()) != '\n') { if (ch == ' ') { count++; } } printf ("Number of space = %d\n",count);}

(2)do...while语句

一般形式为:

do{    statements;}while (condition)

do...while语句的流程图如图2-13所示。

image

代码清单2-10:do...while语句示例

/**********************************************//* do ... while demo                          *//**********************************************/   /* print a string enclosed by quotes " " */   /* gets input from stdin i.e. keyboard  ???*/   /* skips anything outside the quotes    ???*/#include 
/*************************************************//* Level 0 *//*************************************************/main(){ char ch,skipstring(); do { if ((ch = getchar()) == '"') { printf ("The string was:\n"); ch = skipstring(); } } while (ch != '\n') { }}/*************************************************//* Level 1 *//*************************************************/char skipstring () /* skip a string "" */{ char ch; do { ch = getchar(); putchar(ch); if (ch == '\n') { printf ("\nString was not closed "); printf ("before end of line\n"); break; } } while (ch != '"') { } return (ch);}

(3)for循环语句

一般形式为:

for (expression1; condition; expression2){}

for循环的流程图如图2-14所示。

image

代码清单2-11:for语句示例

/************************************************//* Prime Number Generator #1                    *//************************************************/   /* Check for prime number by raw number */   /* crunching. Try dividing all numbers  */   /* up to half the size of a given i, if */   /* remainder == 0 then not prime!       */#include 
#define MAXINT 500#define TRUE 1#define FALSE 0/*************************************************//* Level 0 *//*************************************************/main(){ int i; for (i = 2; i <= MAXINT; i++) { if (prime(i)) { printf ("%5d",i); } }}/*************************************************//* Level 1 *//*************************************************/prime (i) /* check for a prime number */int i;{ int j; for (j = 2; j <= i/2; j++) { if(i%j==0) { return FALSE; } } return TRUE;}

3.中断语句

(1)break语句
break语句的作用是跳出整个循环。如有嵌套的循环,则跳出最近的循环体。
代码清单2-12:break语句示例

/* an expensive way of assigning i to be 12 would be: */for (i = 1; i <= 20; i++){     if(i==12)     {         break;     }}/* another way of making skipgarb() */while(TRUE){     ch = getchar();     if(ch=='\n')     {         break;     }}

(2)continue语句

continue语句的作用是跳出一次循环,即忽略continue后面的其他语句,紧接着执行下一次循环。
代码清单2-13:continue语句示例

/* to avoid dividing by zero */for (i = -10; i <= 10; i++){     if (i==0)     {         continue;     }     printf ("%d", 20/i);}

2.2.4 Arduino的基本函数

函数是包含一个名字和一段语句的代码,当函数被调用的时候,函数里面的语句被执行。前面已经讨论过void setup()和void loop()函数了,后面会讨论更多的函数。
可以自己编写自己的函数,自定义函数格式如下:

type functionName(parameters){     statements;}

type为函数返回值类型,如果没有返回值,函数类型为void。parameters是传递给函数的参数。

“{}”用来定义函数块或语句块的开始和结束。如:

type function(){     statements;}

“;”用来结束一个语句,也用来在for循环中分隔不同的部分。

Arduino程序中有一些特定的函数,用来实现Arduino特定的操作,如下所示。
(1)pinMode(pin,mode)
用在void setup()函数中,用来配置某个端口为输入端口还是输出端口。

pinMode(pin,OUTPUT);            //配置"pin"为输出端口

Arduino的数字端口默认为输入,所以不需要用pinMode()函数专门配置为输入端口。被配置为输入的端口处于高阻的状态。ATmega单片机芯片内部有20 kΩ上拉电阻,可以方便地通过软件来配置。这些上拉电阻可以通过下面的方式配置:

pinMode(pin,INPUT);             //设置"pin"为输入端口digitalWrite(pin,HIGH);         //打开上拉电阻

上拉电阻一般用来连接像开关之类的输入信号。注意,在上面的例子中,并没有把端口配置为输出,而是启用了内部的上拉电阻。

配置为OUTPUT输出类型的端口处于低阻抗的状态,并能提供40mA电流给其他器件或电路。这个电流足够点亮LED,但是不足以驱动继电器、电磁铁及电机。
如果Arduino的端口被短路或者电流过大,会损坏输出端口甚至损坏ATmega芯片。所以,通常在OUTPUT输出端口上串联一个470Ω或者1kΩ的电阻会比较好。
(2)digitalRead(pin)
读取数字端口的值,一般为HIGH或者LOW。
pin可以为变量或者常量(0~13)。如:

value = digitalRead(pin);

(3)digitalWrite(pin,value)

在一个指定的端口输出逻辑HIGH或者LOW,pin可以为变量或者常量(0~13)。如:

digitalWrite(pin,HIGH);         //设置"pin"为高电平

在代码清单2-14中,按键连接到数字输入端口,LED连接到数字输出端口,当数字按键按下的时候将LED点亮。

代码清单2-14:数字输入输出示例

int led =13;int pin =7;int value =0;void setup(){      pinMode(led,OUTPUT);      pinMode(pin,INPUT);}void loop(){      value = digitalRead(pin);      digitalWrite(led,value);}

(4)analogRead(pin)

读取模拟输入端口的数值,模拟输入端口的分辨率为10位,模拟输入端口为A10~A15,函数返回值范围为0~1023。如:

value = analogRead(pin);

注意,模拟输入端口不像模拟输出端口,不需要配置为INPUT或者OUTPUT。

(5)analogWrite(pin,value)
使用带有PWM硬件功能的输出端口产生类似于模拟值的PWM信号。这个函数可以在数字端口3、5、6、9、10、11使用。value数值可以为变量或者常量(0~255)。如:

analogWrite(pin,value);

如果value为0,那么在相应的端口,电压一直保持为0V;如果value为255,那么相应端口的电压一直保持为5V;如果vaule为64,那么端口电压将保持3/4时间为0V,1/4时间为5V;如果value为192,那么端口电压将保持1/4时间为0V,3/4时间为5V。

由于这是一个硬件功能,当analogWrite()被调用后,端口将始终保持稳定的波形,直至下次调用。
在代码清单2-15中,读取模拟输入端口的值,将该值除以4,并将结果通过PWM输出端口输出。
代码清单2-15:模拟采集示例

int led = 10;int pin = 0;int value;void setup(){}void loop(){value = analogRead(pin);value /= 4;analogWrite(led,value);}

(6)delay(ms)

暂停程序等待设定的毫秒数,1000代表1000ms,即1s。如:
delay(1000);//等待1s
(7)millis()
返回Arduino板开始运行当前程序至今的毫秒数(时间),返回值为无符号长整型。如:
value = millis();
注意,这个返回值在9小时后可能溢出(重置为0)。
(8)min(x,y)
比较两个值的大小,返回较小的值。如:
value = min(value,100);
(9)max(x,y)
比较两个值的大小,返回较大的值。如:
value = max(value,100);
(10)randomSeed(seed)
设定一个值,或者种子,作为随机数函数的起始值。
(11)randomSeed(value);
Arduino只能产生伪随机数。seed可以是一个变量、函数返回值(millis())或者模拟端口采集的数值。
(12)random(min,max)
random函数允许返回设定的在最小值和最大值之间的伪随机数。如:
vaule = random(100,200); //设置value为在100~200范围内的一个随机数
注意,该函数需要在randomSeed()函数之后使用。
代码清单2-16创建了一个0~255之间的随机数,并且通过PWM端口将随机数输出。
代码清单2-16:random函数示例

int randNumber;int led = 10;void setup(){}void loop(){      randomSeed(millis());      randNumber = random(255);      analogWrite(led,randNumber);      delay(500);}

(13)Serial.begin(rate)

打开串口,设置串口通信的波特率。Arduino和计算机通信的常用波特率为9600。当然,也支持其他速度。如:

void setup(){      Serial.begin(9600);}

注意,当使用串口通信的时候,数字端口0(RX)和1(TX)不能再被用作其他功能同时使用。

(14)Serial.println(data)
输出数据到串口,并且可以将输出数据返回,可以使用串口监听器读取输出的数据。
(15)Serial.println(analogValue);
在代码清单2-17中,读取模拟输入端口A10的值并且每隔1s将它发送给上位机。
代码清单2-17:println函数示例

void setup(){      Serial.begin(9600);}void loop(){      Serial.println(analogRead(0));      delay(1000);}

转载地址:http://xedvl.baihongyu.com/

你可能感兴趣的文章
Lync 2010与Lync 2013共存及迁移部署参考v1.0
查看>>
Android应用程序组件Content Provider的共享数据更新通知机制分析(2)
查看>>
企业服务经验总结--服务器安全细则1
查看>>
Lync与Exchange 2013 UM集成:Exchange 配置
查看>>
玩转“网上邻居”之WINS解析(一)
查看>>
Lync 小技巧-20-检查-Active Directory Replication Status
查看>>
IT168采访记录
查看>>
微软私有云虚拟化产品
查看>>
Linux下用crontab定时执行PHP程序
查看>>
开启mysql审计后引发的问题
查看>>
终于学会后空翻!历经多次NG,波士顿动力机器人再get新技能
查看>>
检查Linux系统日志error和mysql错误日志的脚本
查看>>
Android -- Service的开启关闭与生命周期
查看>>
结构化项目管理:十步法 [摘自:成功的软件项目管理]
查看>>
cuda并行编程之求解ConjugateGradient(共轭梯度迭代)丢失dll解决方式
查看>>
Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级)
查看>>
Spreadsheet 对象
查看>>
NSubstitute完全手册(十八)检查调用顺序
查看>>
Ubuntu 下使用minicom 的配置过程
查看>>
HDU 5091 线段树扫描线
查看>>