目录

  • 4.1 课程说明
  • 4.2 器材:
  • 4.3 重点器材介绍
  • 4.4 电路:
  • 4.5 预备知识
  • 4.5.1 while循环
  • 4.5.2 do ... while循环
  • 4.5.3 for循环
  • 4.5.4 嵌套循环
  • 4.5.5 无限循环
  • 4.5.6 Arduino 数组
  • 1. 数组
  • 2. 声明数组
  • 3. 使用数组的示例
  • 示例1:声明数组并使用循环来初始化数组的元素
  • 示例2:使用初始化器列表在声明中初始化数组
  • 示例3:对数组的元素求和
  • 使用数组注意事项
  • 4.6 流水灯
  • 改写
  • 4.7 补充阅读材料:
  • 1. Arduino 将数组传递给函数
  • 重点
  • 2. 使用数组示例


4.1 课程说明

利用循环和数组语法进一步优化流水灯实验,通过本课实验希望能理解各种循环的语法结构和特点,学会数组的存储与访问方式。

4.2 器材:

名称

数量

规格

Arduino uno控制板

1

R3

LED灯

3

红黄蓝

4.3 重点器材介绍

4.4 电路:

4.5 预备知识

4.5.1 while循环

while循环将会连续、无限循环,直到括号()内的表达式变为false。必须用一些东西改变被测试的变量,否则while循环永远不会退出。
while循环语法

while(expression) {
   Block of statements;
}

arduino SoftwareSerial 只能定义一个 arduinowhile_while循环

4.5.2 do … while循环

do … while循环语句语法

do { 
  Block of statements; 
}  while (expression);

do … while 循环类似于while循环。在while循环中,循环连续条件在循环开始时测试,然后再执行循环体。do … while语句在执行循环体之后测试循环连续条件。因此,循环体将被执行至少一次。
当 do … while 终止时,将使用while子句后的语句继续执行。如果在正文中只有一条语句,则没有必要在do … while语句中使用大括号。但是,大括号通常会包含在内以避免混淆while和do … while语句。

4.5.3 for循环

for循环执行语句预定的次数。循环的控制表达式在for循环括号内完全的初始化,测试和操作。它很容易调试循环结构的行为,因为它是独立于循环内的活动。
每个for循环最多有三个表达式决定其操作。以下示例显示了通用的for循环语法。请注意,在for循环参数括号中的三个表达式用分号分隔。
for循环语句语法

for ( initialize; control; increment or decrement) {
   // statement block
}

例子

for(counter = 2;counter <= 9;counter++) {
   //statements block will executed 10 times
}
4.5.4 嵌套循环

C语言允许你在另一个循环内使用一个循环。下面的例子说明了这个概念。
嵌套循环语句语法

for ( initialize ;control; increment or decrement) {
   // statement block
   for ( initialize ;control; increment or decrement) {
      // statement block
   }
}

例子

for(counter = 0;counter <= 9;counter++) {
   //statements block will executed 10 times
   for(i = 0;i <= 99;i++) {
      //statements block will executed 100 times
   }
}
4.5.5 无限循环

它是没有终止条件的循环,因此循环变为无限。

  1. 使用for循环
for (;;) {
   // statement block
}
  1. 使用while循环
while(1) {
   // statement block
}
  1. 使用do … while循环
do {
   Block of statements;
} while(1);
4.5.6 Arduino 数组
1. 数组

数组是连续的一组相同类型的内存位置。要引用数组中的特定位置或元素,我们指定数组的名称和数组中特定元素的位置编号。
图给出了一个名为C的整数数组,它包含4个元素。通过给出数组名称,后面跟特定元素的位置编号:方括号([]),你可以引用这些元素中的任何一个。位置编号更正式地称为下标或索引(该数字指定从数组开始的元素数)。第一个元素具有下标0(零),有时称为零元素。 因此,数组C的元素是C[0],C[1],C[2]等等。数组C中的最高下标是3,其比数组中的元素数少1。数组名遵循与其他变量名相同的约定。
下标必须是整数或整数表达式(使用任何整数类型)。如果程序使用表达式作为下标,则程序评估表达式以确定下标。下标数组名是一个左值,它可以在赋值的左侧使用,就像非数组变量名一样。

2. 声明数组

数组占用内存中的空间。要指定元素的类型和数组所需的元素数量,请使用以下形式的声明:
type arrayName [ arraySize ] ;
编译器保留适当的内存量(回想一下,保留内存的声明更恰当地被称为定义)。arraySize必须是大于零的整数常量。例如,要告诉编译器为整数数组C保留11个元素,请使用声明:
int C[ 12 ]; // C is an array of 12 integers
数组可以声明为包含任何非引用数据类型的值。例如,可以使用字符串类型的数组来存储字符串。

3. 使用数组的示例
示例1:声明数组并使用循环来初始化数组的元素

程序声明一个4元素的整数数组 n 。行a-b使用 For 语句将数组元素初始化为零。与其他自动变量一样,自动数组不会隐式初始化为零。第一个输出语句(行c)显示在后续for语句(行d-e)中打印的列的列标题,以表格格式打印数组。

int n[ 3 ] ; // n is an array of 10 integers  
  
void setup () {  
  
}  
  
void loop () {  
   for ( int i = 0; i < 3; ++i ) {// initialize elements of array n to 0   
      n[ i ] = 0; // set element at location i to 0  
      Serial.print (i) ;  
      Serial.print (‘\r’) ;  
   }  
   for ( int j = 0; j < 10; ++j ){ // output each array element's value  
      Serial.print (n[j]) ;  
      Serial.print (‘\r’) ;  
   }   
}

它会产生以下结果:

元件


0

0

1

0

2

0

3

0

示例2:使用初始化器列表在声明中初始化数组

数组元素也可以在数组声明中初始化,通过在数组名后面跟随等号和一个用大括号及逗号分隔的初始化器列表。程序使用初始化器列表来初始化一个具有10个值的整数数组(行a),并以表格格式(行b-c)打印数组。
示例

// n is an array of 10 integers  
int n[ 10 ] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 } ;  
  
void setup () {  
  
}  
  
void loop () {  
   for ( int i = 0; i < 10; ++i ) // initialize elements of array n to 0 {  
      Serial.print (i) ;  
      Serial.print (‘\r’) ;  
   }  
   for ( int j = 0; j < 10; ++j ) // output each array element's value {  
      Serial.print (n[j]) ;  
      Serial.print (‘\r’) ;  
}

结果 - 它会产生以下结果:

元件


0

32

1

64

2

18

3

95

示例3:对数组的元素求和

通常,数组的元素表示要在计算中使用的一系列值。例如,如果数组的元素表示考试成绩,教授可能希望将数组的元素进行加总,并使用该总和来计算班级考试的平均成绩。程序将包含在10元素整数数组 a 中的值进行求和。
示例

const int arraySize = 10; // constant variable indicating size of array  
int a[ arraySize ] = { 87, 68, 94, 100, 83, 78, 85, 91, 76, 87 };  
int total = 0;  
void setup () {  
  
}  
void loop () {  
   // sum contents of array a  
   for ( int i = 0; i < arraySize; ++i )  
      total += a[ i ];  
   Serial.print (“Total of array elements : ") ;  
   Serial.print(total) ;  
}

结果 - 它会产生以下结果:
Total of array elements: 849

使用数组注意事项

数组对Arduino很重要,应该需要更多的关注。以下是学习Arduino应该清楚的与数组相关的重要概念:

  1. 将数组传递给函数 要将数组参数传递给函数,请指定没有任何括号的数组的名称。
  2. 多维数组 具有两个维度(即,下标)的数组通常表示由排列在行和列中的信息组成的值的表格。

4.6 流水灯

依次将三个LED灯接入7,8,9引脚,编写程序
代码

const byte LEDs[]={7,8,9};  
const byte total = sizeof(byte);  
byte index = 0;  
void setup() {  
  // put your setup code here, to run once:  
  for(byte i = 0; i < total; i++) {  
    pinMode(LEDs[i], OUTPUT);  //i的值将从0到4,依序设置7,8,9引脚为输出引脚。  
  }  
}  
  
void loop() {  
  // put your main code here, to run repeatedly:  
  for (byte i = 0; i < total; i++) {  
    digitalWrite(LEDs[i], LOW);  
  }  
  digitalWrite(LEDs[index],HIGH);  
  index ++;  
  if (index == total)  
    index = 0;  
  delay  
}
改写

用while、do……while语句改写此程序。

4.7 补充阅读材料:

1. Arduino 将数组传递给函数

要将数组参数传递给函数,请指定没有任何括号的数组的名称。例如,如果数组 hourlyTemperatures 已声明为函数,则调用时会将数组hourlyTemperatures及其大小传递给函数 modifyArray 。

重点

下面是在将数组传递给函数时需要了解的一些重要事项:
1. 当将数组传递给函数时,通常也会传递数组大小,因此函数可以处理数组中特定数量的元素。否则,我们需要将这些知识构建到被调用的函数中,或者更糟的是,将数组大小放在全局变量中。
2. C++通过引用将数组传递给函数,即被调用函数可以修改调用者原始数组中的元素值。
3. 数组名称的值是数组第一个元素在计算机内存中的地址。由于数组的起始地址被传递,所以被调用的函数精确地知道数组存储在内存中的位置。因此,当被调函数修改其函数体中的数组元素时,它是在修改其原始内存位置中数组的实际元素。
4. 尽管整个数组都是通过引用传递的,但是单个数组元素是按照简单变量的值传递的。
5. 要将数组的元素传递给函数,请在函数调用中使用数组元素的下标名称作为参数。
6. 对于通过函数调用接收数组的函数,函数的参数列表必须指定函数期望接收的数组。

例如,函数modifyArray的函数头可能写为:
void modifyArray( int b[], int arraySize )
该语句指示modifyArray期望接收参数b中的整数数组的地址和参数arraySize中的数组元素的数量。数组的大小在数组括号中不是必需的。如果包括它,编译器会忽略它;因此,任何大小的数组都可以传递给函数。
C++通过引用将数组传递给函数。当被调用函数使用数组b时,它指的是调用者中的实际数组(即本节开头讨论的arrayhourlyTemperatures)。
注意modifyArray函数原型的奇怪外观。
void modifyArray( int [] , int ) ;
这个原型可以用下列方式编写,用于文档目的。
void modifyArray( int anyArrayName[], int anyVariableName ) ;
但是,C++编译器会忽略原型中的变量名。请记住,原型告诉编译器参数的数量以及参数预期出现的顺序中的每个参数的类型。

2. 使用数组示例

下面例子中的程序演示了传递整个数组和传递数组元素之间的区别。
例子

void modifyArray( int [], int ); // appears strange; array and size
void modifyElement( int ); // receive array element value

void setup () {
   Serial.begin (9600);
   const int arraySize = 5; // size of array a
   int a[arraySize] = { 0, 1, 2, 3, 4 }; // initialize array a
   Serial.print ( "Effects of passing entire array by reference:" ) ;
   // output original array elements
   for ( int i = 0; i < arraySize ; ++i )
   Serial.print ( a[i] ) ;
   Serial.print ("\r" ) ;
   Serial.print ("The values of the modified array are:\n" );
   // output modified array elements
   for ( int j = 0; j < arraySize; ++j )
   Serial.print ( a[j] ) ;
   Serial.print ("\r" ) ;
   Serial.print ("\r\rEffects of passing array element by value:" );
   Serial.print ( "\r a[3] before modifyElement: " );
   Serial.print ( a[3] );
   Serial.print ( "\r a[3] after modifyElement: " );
   Serial.print ( a[3] );
}

void loop () {

}

// in function modifyArray, "b" points to the original array "a" in memory

void modifyArray( int b[], int sizeOfArray ) {
   // multiply each array element by 2
    for ( int k = 0 ; k < sizeOfArray ; ++k )
        b[ k ] *= 2;
} 
// end function modifyArray

// in function modifyElement, "e" is a local copy of
// array element a[ 3 ] passed from main
void modifyElement( int e ) {
   // multiply parameter by 2
   Serial.print ( "Value of element in modifyElement: " );
   Serial.print ( ( e *= 2 ) );
} 
// end function modifyElement

结果
Effects of passing entire array by reference:01234
The values of the modified array are:01234

Effects of passing array element by value:
a[3] before modifyElement: 3
a[3] after modifyElement: 3
$ is not a hexadecimal digit
f is a hexadecimal digit