![Arduino项目开发:智能家居](https://wfqqreader-1252317822.image.myqcloud.com/cover/942/31169942/b_31169942.jpg)
1.4 Arduino编程语言
Arduino编程语言是建立在C/C++语言基础上的,即以C/C++语言为基础,把AVR单片机(微控制器)相关的一些寄存器参数设置等进行函数化,以利于开发者更加快速地使用。其主要使用的函数包括数字I/O引脚操作函数、模拟I/O引脚操作函数、高级I/O引脚操作函数、时间函数、中断函数、串口通信函数和数学函数等。
1.4.1 Arduino编程基础
关键字:if、if…else、for、switch、case、while、do…while、break、continue、return、goto。
语法符号:每条语句以“;”结尾,每段程序以“{}”括起来。
数据类型:boolean、char、int、unsigned int、long、unsigned long、float、double、string、array、void。
常量:HIGH或者LOW,表示数字I/O引脚的电平,HIGH表示高电平(1),LOW表示低电平(0);INPUT或者OUTPUT,表示数字I/O引脚的方向,INPUT表示输入(高阻态),OUTPUT表示输出(AVR能提供5V电压,40mA电流);TRUE或者FALSE,TRUE表示真(1),FALSE表示假(0)。
程序结构:主要包括两部分,即void setup()和void loop()。其中,前者是声明变量及引脚名称(如int val;int ledPin=13),在程序开始时使用,初始化变量和引脚模式,调用库函数等[如pinMode(ledPin,OUTPUT)];后者用在函数setup()之后,不断地循环执行,是Arduino的主体。
1.4.2 数字I/O引脚的操作函数
1. pinMode(pin,mode)
pinMode函数用于配置引脚以及设置输出或输入模式,是一个无返回值函数。该函数有两个参数:pin和mode。pin参数表示要配置的引脚;mode参数表示设置该引脚的模式为INPUT(输入)或OUTPUT(输出)。
INPUT用于读取信号,OUTPUT用于输出控制信号。pin的范围是数字引脚0~13,也可以把模拟引脚(A0~A5)作为数字引脚使用,此时引脚14对应模拟引脚0,引脚19对应模拟引脚5。该函数一般会放在setup()里,先设置再使用。
2. digitalWrite(pin,value)
该函数的作用是设置引脚的输出电压为高电平或低电平,也是一个无返回值的函数。
pin参数表示所要设置的引脚;value参数表示输出的电压为HIGH(高电平)或LOW(低电平)。
注意:使用前必须先用pinMode设置。
3. digitalRead(pin)
该函数在引脚设置为输入的情况下,可以获取引脚的电压情况:HIGH(高电平)或者LOW(低电平)。
数字I/O引脚的操作函数使用例程如下:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P23_12799.jpg?sign=1738830746-rmsevEHPbeYOH27KBUoxm9kkcXeBHLrw-0-643538eb910300b2406603c0386a51bf)
1.4.3 模拟I/O引脚的操作函数
1. analogReference(type)
该函数用于配置模拟引脚的参考电压。它有三种类型:DEFAULT是默认模式,参考电压是5V;INTERNAL是低电压模式,使用片内基准电压源2.56V;EXTERNAL是扩展模式,通过AREF引脚获取参考电压。
注意:若不使用该函数,默认参考电压是5V。若使用AREF作为参考电压,需接一个5kΩ的上拉电阻。
2. analogRead(pin)
该函数用于读取引脚的模拟量电压值,每读取一次需要用100μs的时间。参数pin表示所要获取模拟量电压值的引脚,返回为int型。它的精度为10位,返回值为0~1023。
注意:函数参数pin的取值是0~5,对应开发板上的模拟引脚A0~A5。
3. analogWrite(pin,value)
该函数是通过PWM(Pulse-Width Modulation,脉冲宽度调制)的方式在引脚上输出一个模拟量。图1-23所示为PWM输出的一般形式,也就是在一个脉冲的周期内高电平所占的比例。它主要应用于LED亮度控制、直流电机转速控制等方面。
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P24_3599.jpg?sign=1738830746-qmznJybqcsQltFMGbAMF4xo5cbeEk5mD-0-a852ffb53e2fc121bff74d42910a10f3)
图1-23 占空比的定义
注:PWM波形的特点是波形频率恒定,占空比D可以改变。
Arduino中PWM的频率约为490Hz,Arduino UNO开发板支持以下数字引脚(不是模拟输入引脚)作为PWM模拟输出:3、5、6、9、10、11。开发板带PWM输出的都有“~”号。
注意:PWM输出位数为8位,即0~255。
模拟I/O引脚的操作函数使用例程如下:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P24_12801.jpg?sign=1738830746-I5mSmEWuArKy9xApc0bmthsQ7HYCcKHx-0-e61f8021bf29fe2e2c7d27fe0eec11fa)
1.4.4 高级I/O引脚的操作函数
函数PulseIn(pin,state,timeout)用于读取引脚脉冲的时间长度,脉冲可以是HIGH或者LOW。如果是HIGH,该函数先将引脚变为高电平,然后开始计时,直到变为低电平停止计时。返回脉冲持续的时间,单位为ms(毫秒),如果超时没有读到时间,则返回0。
例程说明:做一个按钮脉冲计时器,测量按钮的持续时间,看谁的反应最快,即谁按按钮时间最短,按钮接在引脚3。程序如下:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P25_3610.jpg?sign=1738830746-lS0CtgGrkkSkRF2t3Z0m2eakpxnC4ceP-0-bebe5a288556cae5fc0e5c98534a7faf)
1.4.5 时间函数
1. delay()
该函数是延时函数,参数是延时的时长,单位是ms。延时函数的典型例程是跑马灯的应用,使用Arduino开发板控制4个LED依次点亮。程序如下:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P25_12805.jpg?sign=1738830746-y8agLPjjWUk35miajc3QFdzgRhH2fVUG-0-a19d09c91a3e345807e1096802db22fb)
2. delayMicroseconds()
delayMicroseconds()也是延时函数,单位是μs(微秒),1ms=1000μs。该函数可以产生更短的延时。
3. millis()
millis()为计时函数。应用该函数可以获取单片机通电到现在运行的时间长度,单位是ms。系统最长的记录时间为9小时22分,超出则从0开始。返回值是unsigned long型。
该函数适合作为定时器使用,不影响单片机的其他工作(而使用delay()函数期间无法进行其他工作)。计时时间函数使用示例(延时10s后自动点亮LED)程序如下:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P26_12807.jpg?sign=1738830746-bFVIuDTc1o44qYCHu206eLAt48HGRVyq-0-aefd00e7393e54c288ee8499eaa8e8e1)
4. micros()
micros()也是计时函数。该函数返回开机到现在运行的时间长度,单位为μs。返回值是unsigned long型,70min(分)溢出。程序如下:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P26_3620.jpg?sign=1738830746-XMjMIbdtEtVYzirAyEsnKyRCi1vFIwXQ-0-2089ddc9e90367db945c45cc01ae562b)
以下例程为跑马灯的另一种实现方式:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P27_12826.jpg?sign=1738830746-Km1F7LEX5rvPCWaxcb8RZwFHivExvUVW-0-d9bd1e8b98481eaade00189575ab09b5)
1.4.6 中断函数
如图1-24所示,你在看书,电话铃响,于是在书上做上记号,去接电话,与对方通话;门铃响了,有人敲门,然后让打电话的对方稍等一下,接着去开门,并在门旁与来访者交谈,谈话结束,关好门;回到电话机旁,继续通话,接完电话后再回来从做记号的地方接着看书。
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P28_4504.jpg?sign=1738830746-n3hGHlJfgymrqpOYOfCiAOMenCcvrv6s-0-2fb5bffb20bb600b2102934714bbd147)
图1-24 中断的概念
同样的道理,在单片机中也存在中断概念,如图1-25所示。在计算机或者单片机中,中断是由于某个随机事件的发生,计算机暂停主程序的运行,转去执行另一程序(随机事件),处理完毕又自动返回主程序继续运行的过程。也就是说,高优先级的任务中断了低优先级的任务。在计算机中,中断包括如下几部分。
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P28_4508.jpg?sign=1738830746-0vOufRw56zIVh6bRoKZZDYY3x1TnBmtR-0-688e3b49e11d2dba7e6b913f48996bc6)
图1-25 单片机中的中断
中断源:引起中断的原因,或能发生中断申请的来源。
主程序:计算机现行运行的程序。
中断服务子程序:处理突发事件的程序。
1. attachinterrupt(interrupt,function,mode)
该函数用于设置中断,有3个参数,分别表示中断源、中断处理函数和触发模式。中断源可选0或者1,对应数字引脚2或者3号。中断处理函数是一段子程序,当中断发生时执行该子程序部分。触发模式有4种类型:LOW(低电平触发)、CHANGE(变化时触发)、RISING(低电平变为高电平触发)、FALLING(高电平变为低电平触发)。例程功能如下:
数字引脚2接按钮开关,引脚4接LED1(红色),引脚5接LED2(绿色)。在例程中,LED3为板载的LED,每秒闪烁一次。使用中断0控制LED1,中断1控制LED2。按下按钮,立即响应中断,由于中断响应速度快,LED3不受影响,继续闪烁。使用不同的4个参数,例程1试验LOW和CHANGE参数,例程2试验RISING和FALLING参数。
例程1:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P28_12827.jpg?sign=1738830746-Em1J1J0UOMYKVavC733YaEGh5T0yPl9g-0-1912ca416f3996351055a26292ca9015)
例程2:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P29_12829.jpg?sign=1738830746-Si6BHhSMUXIHNC0yUl5OHhLWm0NZV4O9-0-1249cb784cb69fe79ad3f003754ba49d)
2. detachInterrupt(interrupt)
该函数用于取消中断,参数interrupt表示所要取消的中断源。
1.4.7 串口通信函数
串行通信接口(serial interface)使数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信的接口,如图1-26所示。
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P30_4522.jpg?sign=1738830746-AcoL4x7iHdtrC9vsyqdz02PUGBFTM43p-0-71fce7bf375c389056ea9e327855e084)
图1-26 串行通信接口
串行通信接口出现在1980年前后,数据传输率是115~230kb/s。串行通信接口出现的初期是为了实现计算机外设的通信,初期串口一般用来连接鼠标和外置Modem、老式摄像头和写字板等设备。
由于串行通信接口(COM)不支持热插拔及传输速率较低,因此目前部分新主板和大部分便携计算机已开始取消该接口,串口多用于工控和测量设备以及部分通信设备中,包括各种传感器采集装置、GPS信号采集装置、多个单片机通信系统、门禁刷卡系统的数据传输、机械手控制和操纵面板控制直流电机等,特别是广泛应用于低速数据传输的工程应用。主要函数如下:
1. Serial.begin()
该函数用于设置串口的波特率,即数据的传输速率,指每秒传输的符号个数。一般的波特率有9600、19200、57600、115200等。例如:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P30_12832.jpg?sign=1738830746-FlbhyGAmJmY1EYCIqDl65QCFrJR20I7t-0-5d3fcb9d741bfef12c431e089b6fee03)
2. Serial.available()
该函数用来判断串口是否收到数据,函数的返回值为int型,不带参数。
3. Serial.read()
该函数不带参数,只将串口数据读入。返回值为串口数据,int型。
4. Serial.print()
该函数向串口发送数据,可以发送变量,也可以发送字符串。例如:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P30_12833.jpg?sign=1738830746-IWjSCX7x9nTT5420iSwdewcvMhnm5SQ2-0-6f655a7475470976058547dcd9b1ca12)
5. Serial.println()
该函数与Serial.print()类似,只是多了换行功能。
串口通信函数使用例程:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P30_4528.jpg?sign=1738830746-hlyQrYESXsdZ5kNqCmY4ensMbS9EoxlY-0-eb517ca4f5e1db0fe9ce45f96c319f93)
1.4.8 Arduino的库函数
与C语言和C++一样,Arduino也有相关的库函数提供给开发者使用。这些库函数的使用,与C语言的头文件使用类似,需要#include语句,可将函数库加入Arduino的IDE编辑环境中,如#include“Arduino.h”语句。
在Arduino开发中,主要库函数的类别如下:数学库主要包括数学计算;EEPROM库函数用于向EEPROM中读写数据;Ethernet库函数用于以太网的通信;LiquidCrystal库函数用于液晶屏幕的显示操作;Firmata库函数实现Arduino与计算机串口之间的编程协议;SD库函数用于读写SD卡;Servo库函数用于舵机的控制;Stepper库函数用于步进电机控制;WiFi库函数用于WiFi的控制和使用等。诸如此类的库函数非常多,还包括一些Arduino爱好者自己开发的库函数。例如下列数学库函数:
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P31_12835.jpg?sign=1738830746-200k1VcBNvht37lPwyiNqRh2DHKkpoWc-0-98665ecea42976cb5348e776e23464cb)
举例如下:
数学库函数random(small,big),返回值为long。
![](https://epubservercos.yuewen.com/F75462/16888495404071106/epubprivate/OEBPS/Images/Figure-P31_12836.jpg?sign=1738830746-8CecfuvMUFJ6VLMngm58GrvQP8xhaNDJ-0-c98c083309392e9942cf7fc96fad3162)