arduino教程-04.利用循环、数组制作流水灯

4.1 课程说明

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

4.2 器材:

名称数量规格
Arduino uno控制板1R3
LED灯3红黄蓝

4.3 重点器材介绍

4.4 电路:

4.5 预备知识

4.5.1 while循环

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

while(expression) {
   Block of statements;
}

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’) ;  
   }   
}  

它会产生以下结果:

元件
00
10
20
30
示例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’) ;  
}   

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

元件
032
164
218
395
示例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

1、一盏一盏:第一盏灯先亮--延时--熄灭--延时--下一盏灯; 2、利用数组方法点亮:定义一个数组(即0xfe,0xfd,0xfb,0xf7,0xef,oxdf,0xbf,0x7f:依次代表只有第一盏灯,第二盏灯....亮),再利总线,按顺序点亮八盏灯; 3、利用移位方法点亮:(1)、利用移位运算和按位或运算,依次点亮八盏灯; (2)、包含intrins头文件(里面含有移位函数),使用相应的左移或右移函数进行移位, 下面是代码和注释,详细解释了点亮流水灯的思路,附件含有源代码和仿真文件,有需要的可以下载 //方式0控制流水灯循环点亮 #include //包含51单片机寄存器定义的头文件 #include //包含函数_nop_()定义的头文件 unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码,该数组被定义为全局变量 sbit P17=P1^7; /************************************************************** 函数功能:延时约150ms **************************************************************/ void delay(void) { unsigned char m,n; for(m=0;m<200;m++) for(n=0;n<250;n++) ; } /************************************************************** 函数功能:发送一个字节的数据 **************************************************************/ void Send(unsigned char dat) { P17=0; //P1.7引脚输出清0信号,对74LS164清0 _nop_(); //延时一个机器周期 _nop_(); //延时一个机器周期,保证清0完成 P17=1; //结束对74LS164的清0 SBUF=dat; //将数据写入发送缓冲器,启动发送 while(TI==0) //若没有发送完毕,等待 ; TI=0; //发送完毕,TI被置“1”,需将其清0 } /******************************************* 函数功能:主函数 ******************************************/ void main(void) { unsigned char i; SCON=0x00; //SCON=0000 0000B,使串行口工作于方式0 while(1) { for(i=0;i<8;i++) { Send(Tab[i]); //发送数据 delay(); //延时 } } }
Arduino的8位呼吸流水灯是一种通过调整LED的亮度来模拟呼吸和水效果的LED灯通过使用PWM(脉冲宽度调制)技术,可以控制LED的亮度。PWM是利用微处理器的数字输出来对LED进行调光的一种技术。 以下是一个示例的源代码,可以实现呼吸流水灯效果: ```c++ void setup() { pinMode(3, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); } int level = 0; // 设置LED亮度水平变量 int ports = {3, 5, 6, 9, 10, 11}; // 设置数组(为了使不规律的接口被简洁地调用) int idx = 0; // 设置作为数组调用序数的变量 void loop() { analogWrite(ports[idx], level); delay(10); level %= 7; // 先除以7取余数,再1(有范围内的数规律循环的意思) idx %= 6; } ``` 以上代码定义了6个LED引脚并设置为输出模式,然后通过使用analogWrite函数来控制LED的亮度。level变量用于控制亮度的水平,idx变量用于选择要控制的LED引脚。代码中的delay函数用于控制每个LED的亮度变化的延迟时间。 你也可以使用不同的引脚和延迟时间来调整呼吸流水灯的效果。只需更改代码中的引脚和延迟时间的设置即可实现自定义的呼吸流水灯效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [arduino呼吸流水灯](https://blog.csdn.net/weixin_43322322/article/details/107772779)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Arduino笔记-呼吸流水灯](https://blog.csdn.net/qq78442761/article/details/90111717)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Arduino-PWM-4位水呼吸灯](https://download.csdn.net/download/deer_vickey/88241321)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔚蓝慕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值