《Arduino开发实战指南:LabVIEW卷》——2.2 Arduino程序结构及基本函数-阿里云开发者社区

开发者社区> 华章出版社> 正文

《Arduino开发实战指南:LabVIEW卷》——2.2 Arduino程序结构及基本函数

简介:

本节书摘来自华章计算机《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;          //声明变量,并赋初始值为0
intputVariable = 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 <stdio.h>
#define TRUE    1
#define FALSE   0
main ()
{ 
    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 <stdio.h>
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 <stdio.h>
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 <stdio.h>
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 <stdio.h>
/*************************************************/
/* 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 <stdio.h>
#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);
}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接