封装好的API,使得程序中的语句更容易被理解,我们不用理会单片机中繁杂的寄存器配置,就能直观的控制Arduino,增强程序可读性的同时,也提高了开发效率。
本篇主要介绍:
一,项目结构
1.setup
2.loop
3.main
二,数字输入输出
1.pinMode ( pin , mode )
2.digitalWrite ( pin , value )
3.digitalRead ( pin )
三,模拟输入输出
1.analogRead
2.analogWrite
四,模拟输入输出
1.tone
2.pulisein
3.外部中断
-----------------------------------------------------------------------------------------------------------
一,项目结构
1.setup
2.loop
3.main
1.setup():
Arduino控制器通电或复位后,即会开始执行setup() 函数中的程序,该部分只会执行一次。 通常我们会在setup() 函数中完成Arduino的初始化设置,如配置I/O口状态,初始化串口等操作。
eg.示例程序
// 给13号引脚连接的设备设置一个别名“led” int led = 13; // 在板子启动或者复位重启后, setup部分的程序只会运行一次 void setup(){ // 将“led”引脚设置为输出状态 pinMode(led, OUTPUT); } // setup部分程序运行完后,loop部分的程序会不断重复运行 void loop() { digitalWrite(led, HIGH); // 点亮LED delay(1000); // 等待一秒钟 digitalWrite(led, LOW); // 通过将引脚电平拉低,关闭LED delay(1000); // 等待一秒钟 }
2.loop():
在setup() 函数中的程序执行完后,Arduino会接着执行loop() 函数中的程序。而loop()函数是一个死循环,其中的程序会不断的重复运行。 通常我们会在loop() 函数中完成程序的主要功能,如驱动各种模块,采集数据等。
eg.示例程序
// 给13号引脚连接的设备设置一个别名“led” int led = 13; // 在板子启动或者复位重启后, setup部分的程序只会运行一次 void setup(){ // 将“led”引脚设置为输出状态 pinMode(led, OUTPUT); } // setup部分程序运行完后,loop部分的程序会不断重复运行 void loop() { digitalWrite(led, HIGH); // 点亮LED delay(1000); // 等待一秒钟 digitalWrite(led, LOW); // 通过将引脚电平拉低,关闭LED delay(1000); // 等待一秒钟 }
3.main():
在进行Arduino开发时,没有像传统C/C++程序使用入口函数main。实际上main函数存在于Arduino核心库中,且仍然是程序的入口。 在Arduino核心库中可见main.cpp文件,其内容如下:
#include <Arduino.h> // Declared weak in Arduino.h to allow user redefinitions. int atexit(void (* /*func*/ )()) { return 0; } // Weak empty variant initialization function. // May be redefined by variant files. void initVariant() __attribute__((weak)); void initVariant() { } void setupUSB() __attribute__((weak)); void setupUSB() { } int main(void) { init(); initVariant(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }
通过以上程序可见,Arduino程序中编写的setup和loop函数,都在main函数中调用了。 loop的循环执行,是通过for循环实现的,且每次loop结束后,都会进行串口事件判断,也正是因为这种设计,串口事件不能实时响应。
二,数字输入输出
1.pinMode ( pin , mode )
2.digitalWrite ( pin , value )
3.digitalRead ( pin )
1.pinMode ( pin , mode ) :
在使用输入或输出功能前,你需要先通过pinMode() 函数配置引脚的模式为输入模式或输出模式。
参数:
参数pin为指定配置的引脚编号 参数mode为指定的配置模式 通常可用模式有三种: INPUT 输入模式 OUTPUT 输出模式 INPUT_PULLUP 输入上拉模式
eg.示例程序
/* Blink 等待一秒钟,点亮LED,再等待一秒钟,熄灭LED,如此循环 */ // 在大多数Arduino控制板上 13号引脚都连接了一个标有“L”的LED灯 // 给13号引脚连接的设备设置一个别名“led” int led = 13; // 在板子启动或者复位重启后, setup部分的程序只会运行一次 void setup(){ // 将“led”引脚设置为输出状态 pinMode(led, OUTPUT); } // setup部分程序运行完后,loop部分的程序会不断重复运行 void loop() { digitalWrite(led, HIGH); // 点亮LED delay(1000); // 等待一秒钟 digitalWrite(led, LOW); // 通过将引脚电平拉低,关闭LED delay(1000); // 等待一秒钟 }
2.digitalWrite ( pin , value ) :
之前我们在Blink程序中使用到了pinMode(13, OUTPUT),即是把13号引脚配置为输出模式。 配置成输出模式后,你还需要使用digitalWrite() 让其输出高电平或者是低电平。
参数:
参数pin为指定输出的引脚编号; 参数value为你要指定输出的电平 使用HIGH指定输出高电平,或是使用LOW指定输出低电平。
eg.示例程序
/* Blink 等待一秒钟,点亮LED,再等待一秒钟,熄灭LED,如此循环 */ // 在大多数Arduino控制板上 13号引脚都连接了一个标有“L”的LED灯 // 给13号引脚连接的设备设置一个别名“led” int led = 13; // 在板子启动或者复位重启后, setup部分的程序只会运行一次 void setup(){ // 将“led”引脚设置为输出状态 pinMode(led, OUTPUT); } // setup部分程序运行完后,loop部分的程序会不断重复运行 void loop() { digitalWrite(led, HIGH); // 点亮LED delay(1000); // 等待一秒钟 digitalWrite(led, LOW); // 通过将引脚电平拉低,关闭LED delay(1000); // 等待一秒钟 }
Arduino中输出的低电平为0V,输出的高电平为当前Arduino的工作电压。 例如Arduino UNO的工作电压为5V,其高电平输出也是5V;Arduino Uno工作电压为3.3V,所以高电平输出也就是3.3V。
3.digitalRead ( pin ) :
在使用输入或输出功能前,你需要先通过pinMode() 函数配置引脚的模式为输入模式或输出模式。
参数:
参数pin为指定读取状态的引脚编号。
返回值:
返回值为获取到的信号状态,1为高电平,0为低电平。
eg.示例程序
1 /* 2 通过2号引脚连接的按键,控制13号引脚连接的LED 3 */ 4 5 // 设置各引脚别名 6 const int buttonPin = 2; // 连接按键的引脚 7 const int ledPin = 13; // 连接LED的引脚 8 9 // 变量定义 10 int buttonState = 0; // 存储按键状态的变量 11 12 void setup() { 13 // 初始化LED引脚为输出状态 14 pinMode(ledPin, OUTPUT); 15 // 初始化按键引脚为输入状态 16 pinMode(buttonPin, INPUT); 17 } 18 19 void loop(){ 20 // 读取按键状态并存储在变量中 21 buttonState = digitalRead(buttonPin); 22 23 // 检查按键是否被按下 24 // 如果按键按下,那buttonState应该为高电平 25 if (buttonState == HIGH) { 26 // 点亮LED 27 digitalWrite(ledPin, HIGH); 28 } 29 else { 30 // 熄灭LED 31 digitalWrite(ledPin, LOW); 32 } 33 }
三,模拟输入输出
1.analogRead
2.analogWrite
1.analogRead ( pin ) :
模拟输入引脚是带有ADC(Analog-to-Digital Converter,模数转换器)功能的引脚。 它可以将外部输入的模拟信号转换为芯片运算时可以识别的数字信号,从而实现读入模拟值的功能。 模拟输入功能需要使用analogRead() 函数。
参数:
参数pin是指定要读取模拟值的引脚,被指定的引脚必须是模拟输入引脚。如analogRead(A0),即是读取A0引脚上的模拟值。
返回值:
Arduino Uno模拟输入功能有10位精度,即可以将0~5V的电压信号转换为0~1023的整数形式表示。
eg.示例程序
/* 光敏电阻检测环境光 http://www.arduino.cn/ */ void setup() { // 初始化串口 Serial.begin(9600); } void loop() { // 读出当前光线强度,并输出到串口显示 int sensorValue = analogRead(A0); Serial.println(sensorValue); delay(1000); }
2.analogWrite ( pin , value ) :
使用analogWrite() 函数实现PWM输出功能。
在Arduino Uno中,提供PWM功能的引脚为3、5、6、9、10、11。
在analogWrite() 和analogRead() 函数内部,已经完成了引脚的初始化,因此不用在Setup() 函数中进行初始化操作。
参数:
参数pin是指定要输出PWM波的引脚;参数value指定是PWM的脉冲宽度,范围为0~255。
返回值:
Arduino Uno模拟输入功能有10位精度,即可以将0~5V的电压信号转换为0~1023的整数形式表示。
eg.示例程序
/* Fading 通过analogWrite() 函数实现呼吸灯效果 */ int ledPin = 9; // LED连接在9号引脚上 void setup() { // Setup部分不进行任何处理 } void loop() { // 从暗到亮,以每次加5的形式逐渐亮起来 for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { // 输出PWM analogWrite(ledPin, fadeValue); // 等待30ms,以便观察到渐变效果 delay(30); } // 从亮到暗,以每次减5的形式逐渐暗下来 for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { // 输出PWM analogWrite(ledPin, fadeValue); // 等待30ms,以便观察到渐变效果 delay(30); } }
四,模拟输入输出
1.tone
2.pulisein
3.外部中断
1.调声函数
1)tone ( ) :
可以让指定引脚产生一个占空比为50%的指定频率的方波。
语法:
tone(pin, frequency) tone(pin, frequency, duration)
返回值:
Arduino Uno模拟输入功能有10位精度,即可以将0~5V的电压信号转换为0~1023的整数形式表示。
2)no Tone ( pin ):
停止指定引脚上的方波输出。
语法:
noTone(pin)
参数:
pin : 余姚停止方波输出的引脚
eg.示例程序
/* Melody Plays a melody This example code is in the public domain. http://arduino.cc/en/Tutorial/Tone */ #include "pitches.h" // 记录曲子的音符 int melody[] = { NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4}; // 音符持续时间 4为四分音符, 8为八分音符 int noteDurations[] = { 4, 8, 8, 4,4,4,4,4 }; void setup() { // 遍历整个曲子的音符 for (int thisNote = 0; thisNote < 8; thisNote++) { // noteDurations[]数组中存储的是音符的类型 // 我们需要将其换算为音符持续时间,方法如下: // 音符持续时间=1000ms / 音符类型 // 例如,四分音符=1000 / 4,8分音符 = 1000/8 int noteDuration = 1000/noteDurations[thisNote]; tone(8, melody[thisNote],noteDuration); // 为了能辨别出不同的音调,你需要在两个音调间设置一定的延时 // 增加30%延时时间是比较合适的 int pauseBetweenNotes = noteDuration * 1.30; delay(pauseBetweenNotes); // 停止发声 noTone(8); } } void loop() { // 程序并不重复,因此这里为空 }
2.pulisein() :
检测指定引脚上的脉冲信号宽度。
例如当要检查高电平脉冲时,pulseln()会等待指定引脚输入的电平变高,当变高后开始记时,知道输入电平变低,停止计时。
pulseln()函数会返回这个脉冲信号的持续时间,即这个脉冲的宽度。
函数还可以设定超时时间,如果超时设定时间,仍未检测到脉冲,则会退出pulseln()函数并返回0.
当没有设定超时时间时,pulseln()会默认1秒钟的超时时间。
语法:
1)pulseln ( pin , value )
2)pulsein ( pin , value , timeout )
参数:
pin : 需要读取脉冲的引脚
value :需要读取的脉冲类型, HIGH OR LOW
timeout :超时时间 ,单位微秒 ,数据类型为无符号长整型。
返回值:
返回脉冲宽度 , 单位微秒 ,数据类型为无符号长整型 。 如果在指定时间内没有检测到脉冲,则返回0 .
eg.示例程序
/* SR04超声波传感器驱动 串口显示检测距离 */ // 设定SR04连接的Arduino引脚 const int TrigPin = 2; const int EchoPin = 3; float distance; void setup() { // 初始化串口通信及连接SR04的引脚 Serial.begin(9600); pinMode(TrigPin, OUTPUT); // 要检测引脚上输入的脉冲宽度,需要先设置为输入状态 pinMode(EchoPin, INPUT); Serial.println("Ultrasonic sensor:"); } void loop() { // 产生一个10us的高脉冲去触发TrigPin digitalWrite(TrigPin, LOW); delayMicroseconds(2); digitalWrite(TrigPin, HIGH); delayMicroseconds(10); digitalWrite(TrigPin, LOW); // 检测脉冲宽度,并计算出距离 distance = pulseIn(EchoPin, HIGH)/ 58.00; Serial.print(distance); Serial.print("cm"); Serial.println(); delay(1000); }
3.外部中断
影响中断的处理程序——中断函数,当中断触发后,Arduino便会进行这个函数。
该函数不能带任何参数,且返回类型为空。如:
void Hello () { flag = ture ; }
1)attachlneterrupt ( pin , ISR , mode )
对中断引脚进行初始化设置,以开启Arduino的外部中断功能
示例:
attachinterrupt ( 2 , Hello , LOW ) ;该语句会开启Arduino Uno 的 2 号引脚(中断编号0)的外部中断功能,并指定下降沿时触发该中断。
当2号引脚上电平由高变低后,该中断会被触发,Arduino即会运行Hello ()函数中的语句。
2) detachlnterrupt ( pin )
如果你不需要使用外部中断了,你可以用中断分离函数detachlnterrupt()来关闭中断功能。
参数:
pin : 需要禁用中断的引脚。
示例:
detachlnterrupt( 2 )
eg.示例程序
/* Arduino外部中断的使用 外部中断触发警报声 */ // 默认无遮挡,蜂鸣器发声 volatile boolean RunBuzzer = true; void setup() { Serial.begin(9600); // 初始化外部中断 // 当2号引脚输入的电平由高变低时,触发中断函数warning attachInterrupt(2, warning, CHANGE); } void loop() { if(RunBuzzer) { tone(8,1000); } else { noTone(8); } } // 中断函数 void warning () { RunBuzzer=!RunBuzzer; }