本文共 10727 字,大约阅读时间需要 35 分钟。
本节书摘来自华章计算机《Arduino开发实战指南:LabVIEW卷》一书中的第2章,第2.2节,作者:余崇梓著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
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所示。5.注释
在Arduino程序中有两种注释符,分别为:块注释,以“/”开头并以“/”结束的字符串,两者之间的部分为注释。行注释,使用“//”进行行注释,其后的字符串为注释。注释可以出现在程序任何位置,添加注释可以帮助理解程序。2.2.3 Arduino的控制语句Arduino程序流程控制语句也与C语言中的流程控制语句相同,这里做一下简单介绍。1.条件选择语句(1)if语句一般形式如下:if (condition) statement;或者if (condition){ compound statement;}
if语句流程图如图2-10所示。
代码清单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所示。
图2-11 if...else语句的流程图
代码清单2-7:if...else语句示例#includemain(){ 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语句示例#includemain(){ 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所示。
代码清单2-9:while语句示例/* count all the spaces in an line of input */#includemain(){ 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所示。
代码清单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所示。
代码清单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/