文章目录

  • 单片机是什么?
  • 如何学习单片机
  • Arduino系列单片机介绍
    • 官网文件
    • 其他问题汇总 /* 2021.10.24更新 */
  • Arduino语言
    • 1. C语言基础
    • 2. 数据类型
      • (1)各数据类型占用字节数
      • (2)Arduino中特有的数据类型
        •    i) boolean ··· 布尔类型
        •    ii) byte ··· 字节类型
        •    iii) word ··· 字类型
        •    iv) String ··· 特殊的字符串
    • 3. 程序结构
    • 4. 函数总结
      • (1)数字 I/O(GPIO)
        • pinMode()
        • digitalWrite()
        • digitalRead()
      • (2)模拟 I/O(ADC & Timer)
        • analogRead()
        • analogWrite()
      • (3)高级 I/O(Soft USART)
        • shiftOut()
        • shiftIn()
        • pulseIn()
        • tone()
        • noTone()
      • (4)时间函数(Timer)
        • millis()
        • micros()
        • delay()
        • delayMicroseconds()
      • (5)数学函数
        • min()
        • max()
        • constrain()
        • map()
        • pow()
        • sqrt()
        • 三角函数
      • (6)字符判断函数
      • (7)随机函数
        • random()
        • randomSeed()
      • (8)字节函数
      • (9)外部中断函数(GPIO Interrupt)
        • interrupts()
        • noInterrupts()
        • attachInterrupt()
        • detachInterrupt()
  • 串行通讯(Hardware)
    • UART
      • if (Serial)
      • available()
      • availableForWrite()
      • begin()
      • end()
      • write()
      • read()
      • peek()
      • print()
      • println()(ln为"line"的缩写)
      • readBytes()
      • readBytesUntil()
      • readString()
      • readStringUntil()
      • find()
      • findUntil()
      • flush()
      • setTimeout()
      • parseFloat()
      • parseInt()
    • SPI
    • I2C
  • 高级应用:用AVR开发Arduino
  • 其他操作
    • 1. Arduino IDE的“高级用法”——串口绘图器
    • 2. Arduino IDE的替代编辑器——Visual Studio Code
    • 3. Arduino IDE v2.0 Beta版本
    • 4. 记录两个写得非常好的教程

单片机是什么?

  单片机,全称单片微型计算机(英语:Single-chip Microcomputer),又称微控制器单元(Microcontroller Unit),是把中央处理器存储器定时/计数器(timer/counter)、各种输入输出接口等都集成在一块集成電路芯片上的微型计算机。与应用在个人电脑中的通用型微处理器相比,它更强调自供应(不用外接硬件)和节约成本。它的最大优点是体积小,可放在仪表内部,但存储量小,输入输出接口简单,功能较低。由于其发展非常迅速,旧的定义已不能满足,所以在很多应用场合被称为微控制器,中文翻译为“单片机”,英文缩写为MCU

参考: 单片机-维基百科

如何学习单片机

  在经过电赛那段时间的培训之后,我突然觉得,想要真正掌握一款单片机,首先是要理解单片机的原理,这也是最重要的,不理解单片机的工作原理只是不断地套代码,确实也可以做成一些项目,但如果遇到比较底层的问题想要解决可能就会很困难。
  其次的话,我觉得就是要学会看官方手册,和真正理解示例代码。很多人包括我,在入门的时候往往会被官方手册中大段的英文以及示例中几百行代码(或注释)吓得有点怕,但后来我的老师告诉了我一个很简单但却被忽略的方法:根据自己学过的知识抓住关键,不求全部看懂,先理解框架。所以:先求完成,再求完美,切勿好高骛远。 与君共勉!

Arduino系列单片机介绍

官网文件


  注:Arduino主要编写语言为C/C++。
  为了详细了解Arduino单片机的信息,我们需要到官网去查找更详细的资料,首先打开官网:https://www.arduino.cc/,在搜索栏中搜索对应的型号,这里以UNO R3这个型号为例(其他型号类似)进入详情页面:

  这里截取官网提供的引脚图,建议一定要保存一份!!!


  继续往下翻,可以看到Features(UNO的特性介绍)板块:

  在最后的Resource板块还可以下载Arduino相关的资料及集成开发环境,这里方便起见,汇总一下:

  1. DataSheet:数据手册
  2. Arduino IDE:集成开发环境
  3. Full PinOUT:引脚图(一共3张,比上面的引脚图更加全面)
  4. Schematics:原理图(不可编辑)
  5. Eagle Files:原理图和PCB,Eagle格式,可编辑,如果不想装Eagle也对PCB没有兴趣的可以不下

  到此,官方的相关文件初步下载完毕了,IDE也安装完毕,现在就可以开始学习Arduino的语言了。

其他问题汇总 /* 2021.10.24更新 */

  之前一直以为这篇教程写得非常完善了,但还有一些电气特性没有交代好,下面补充一下。

  • Arduino数字引脚是TTL电平,这个在使用的时候还是需要注意一下。具体可以参考这篇链接。
  • Arduino一共有3种供电方案,相信这也是很多人开始使用Arduino时非常关注的点。第一种是最常见的,也就是用USB供电,比如插在电脑上或者充电宝等。第二种是使用直流稳压5V供电,方法是接入5V和GND,这种一定要保证电源电压的稳定性。第三种是Vin输入,输入7-12V,如果低于7V,可能会导致Arduino工作不稳定。第四种是黑色端子输入电压,要求输入电压为9-12V,如果低于9V,可能会导致Arduino工作不稳。具体可以参考这篇文章。
  • 这里有一个比较完整的介绍文件,可以参考一下,链接。

Arduino语言

1. C语言基础

  此处一些C语言的基本用法(包括基本数据变量,基本程序结构等)就不再介绍了,如果有需求的可以去网上找一些资料复习一下,也可以看看这个链接。

2. 数据类型

(1)各数据类型占用字节数


  注意:在单片机的程序中,很多时候只会关注数据的字节数,而不关心它到底是什么类型的。另外,数据类型占用的字节数与单片机的位数无关!!!而是与编译器的类型有关,详情可以参见这篇博客:int字节问题说明

(2)Arduino中特有的数据类型

   i) boolean ··· 布尔类型

   布尔类型占用1个字节,其值只能为1(true)或 0(false)。关于bool和boolean可以参考这篇文章。

   ii) byte ··· 字节类型

   储存的数值范围为0到255占用1个字节

   iii) word ··· 字类型

   在UNO等基于ATMEGA芯片的板子上,word为无符号16位整数,其他型号为无符号32位整数。

   iv) String ··· 特殊的字符串

   String类型(首字母为大写)本质上为一个类,允许以比字符数组更复杂的方式使用和操作文本字符串。 可以连接字符串、附加、搜索和替换子字符串等。 它比简单的字符数组需要更多的内存,但也更有用
   另外需要注意的是,双引号内的一个字符串会被看作字符数组,而不是String类的实例。

   构建一个String类有很多种方法,如下所示:

String stringOne = "Hello String";                    // using a constant String
String stringOne =  String('a');                      // converting a constant char into a String
String stringTwo =  String("This is a string");       // converting a constant string into a String object
String stringOne =  String(stringTwo + " with more"); // concatenating two strings
String stringOne =  String(13);                       // using a constant integer
String stringOne =  String(analogRead(0), DEC);       // using an int and a base
String stringOne =  String(45, HEX);                  // using an int and a base (hexadecimal)
String stringOne =  String(255, BIN);                 // using an int and a base (binary)
String stringOne =  String(millis(), DEC);            // using a long and a base
String stringOne =  String(5.698, 3);                 // using a float and the decimal places(保留3位小数)

   String类相关操作函数总结

string.charAt(n);  //访问第n+1个字符,返回该字符
string.setCharAt(index, c); //将string中的index位置的字符设为c
string.compareTo(string2);  //按字母比较两个字符串,如果string > string2,返回正值,如果
//string < string2,返回负值,如果相等,返回0。另外,string这种类型可以用运算符进行比较和运算
//比如 ==, !=,>, < ,>=, <=
string.equals(string2);  //判断string和string2是否相等,相当于 string == string2
string.equalsIgnoreCase(string2); //忽略字符大小写的比较,返回一个布尔值
string3 = string.concat(string, string2); //string3 = string + string2;
string.concat(string2); //string += string2;
/*string类型还可以加上字符(常、变)、整数(常、变)、字符串(常),但要注意不能混用:
stringThree = stringOne + 123456789;
stringThree =  stringOne + 'A';
stringThree =  stringOne +  "abc";
*/
string.c_str();//将string转换成C风格的无终止符的字符串,返回的是字符串首地址,一个指针。
string.endsWith(string2);//判断string是否以string2中的字符结尾,返回一个布尔值
string.startsWith(string2, n);//判断从第n+1个字符开始,string是不是以string2开头,n默认为0,返回一个布尔值
string.getBytes(buf, len);//将string存入len长度的缓存区buf中。string.indexOf(val);    //在string中搜索字符或字符串val,默认从头开始搜索
string.indexOf(val, from);//如果加上了from,则从from处开始检索,返回val所在的位置,如果没找到,返回-1
string.lastIndexOf(val);//和上面一样,只是从后开始检索
string.lastIndexOf(val, from);string.length();//求字符串的长度
string.remove(index);  //移除从index开始后的count个数的字符,若没有count,则默认到末尾
string.remove(index, count);  //就地转换,无返回值
string.replace(substring1, substring2);//将string中的子字符串substring1替换为substring2,返回新的字符串
string.reserve(size);//给string申请size大小的存储空间
string.substring(from);  //截取string的子字符串,从from(包含)到to(不包含),
string.substring(from, to);  //如果没有to,则默认到末尾,返回子字符串
string.toCharArray(buf, len); //将字符串由String类型转换成char[]类型,其中buf为转换后的字符数组,len为buf的长度
string.toInt(); //将字符串转换为整型,要求string第一个字符必须为数字,如果遇到非数字字符,转换将停止,函数返回一个long类型,如果字符串开头不是数字,则返回0
string.toFloat(); //将字符串转换为浮点型,和上面一样,要求字符串第一个字符为数字,如果遇到非字符数字或小数点,转换将停止,如果只有整数,后面默认加上“.00”,返回一个浮点数,注意数字有效数字为6-7位
string.toLowerCase(); //将字符串转换为小写字母,就地转换,无返回值
string.toUpperCase(); //将字符串转换为大写字母,就地转换,无返回值
string.trim();  //获取删除开头和结尾whitespace的字符串版本,就地转换,无返回值
char thisChar = string1[n]; //用[]访问特定位置的元素

3. 程序结构

  每次新建一个uno程序时,都可以看到如下这个界面,

  由此可知,程序预置了两个函数,分别是setup()和loop()。

  • setup() :每次Arduino上电或按下reset按钮时,程序会 执行一遍 setup中的内容,因此一般用来初始化变量(不能声明变量!),设置引脚模式,开始使用库等操作。
  • loop() :运行完setup函数后,程序会 反复执行 loop中的内容,所以如果在loop程序中放置死循环(比如while(1)),那么死循环前的程序只会执行一次。

  注意:uno程序中没有main函数

4. 函数总结

(1)数字 I/O(GPIO)

pinMode()

a. 功能
设置 数字引脚(GPIO) 的输入输出模式
b. 语法

pinMode(pin, mode);

c. 参数解释
pin:GPIO引脚号(参考上文中的引脚图 D开头的引脚)
mode:输入输出模式,有以下选项:

  • INPUT:输入模式,禁用上拉电阻
  • INPUT_PULLUP:输入模式,使能上拉电阻
  • OUTPUT:输出模式

d. 返回值

e. 说明

  1. 虽然这个函数的针对对象是数字引脚,但其实模拟引脚也可以使用,观察引脚图即可知,模拟引脚A0 ~ A5分别对应D14 ~ D19(也可以直接写“A0”)
  2. 数字引脚13(D13) 因为在板子上连接了一个电阻和LED,因此如果要设置为输入引脚,上拉电阻需要另外接入,不能用内部上拉电阻(否则5V会变成1.7V左右—二极管的电压钳位作用)
  3. 如果GPIO设置为输出模式,其输出电流最大为 ±40 mA(拉电流或灌电流负载) 可以直接连接LED(要串联电阻)或连接传感器,但不足以驱动继电器,螺线管线圈,电机等。
  4. 以上参考链接:Digital Pins

digitalWrite()

a. 功能
设置GPIO引脚的输出电平(高低)
b. 语法

digitalWrite(pin, value);

c. 参数解释
pin:GPIO引脚号(参考上文中的引脚图 D开头的引脚)
value:电平值,有以下选项:

  • HIGH:输出高电平,5V(如果是3.3V的板子则是3.3V)
  • LOW:输出低电平(0V,ground)

d. 返回值

e. 说明

  1. 调用该函数前一定要调用pinMode函数,即必须确定输入输出模式,否则可能会得到错误电平
  2. 如果设置为输入模式,则调用该函数可以使能上拉电阻——HIGH为enable,LOW为disable,不过不推荐这样写,建议调用pinMode函数时使用INPUTINPUT_PULLUP

digitalRead()

a. 功能
读取GPIO引脚电平
b. 语法

digitalRead(pin);

c. 参数解释
pin:GPIO引脚号(参考上文中的引脚图 D开头的引脚)
d. 返回值
引脚电平值,为HIGH(对应高电平)或LOW(对应低电平)
e. 说明
如果该引脚为空,则返回值是随机的,HIGH或LOW。

(2)模拟 I/O(ADC & Timer)

analogRead()

a. 功能
读取引脚模拟值
b. 语法

analogRead(pin);

c. 参数解释
pin:模拟引脚号(0 ~ 5或A0 ~ A5
d. 返回值
一个整型数,0 ~ 1023,对应电压值为0 ~ 5V,每增加4.88mV,返回值增加1。
e. 说明

  1. Arduino上带有6通道10位ADC(有些板子通道数更多),每次DA转换耗时约0.1ms,即ADC频率最高为10,000HZ
  2. 若引脚为空,返回值为0 ~ 1023中的随机值(用法见后面)
  3. 返回值计算公式
    NADC=1023⋅VinVrefN_{ADC}=1023\cdot \frac{V_{in}}{V_{ref}} NADC​=1023⋅Vref​Vin​​
    其中参考电压Vref默认值为5V,如果需要设置其他的参考电压,可以使用 analogReference(type) 函数,其参数type如下所示

    • DEFAULT:默认参考电压值
    • INTERNAL:一个内置的参考电压,ATmega168和ATmega328为1.1V;ATmega8为2.56V(Mega不适用)
    • INTERNAL1V1:内置的1.1V参考电压(只有Mega适用)
    • INTERNAL2V56:内置的2.56V参考电压(只有Mega适用)
    • EXTERNAL:外接参考电压(AREF引脚),但电压范围必须在 0 ~ 5V之间!

analogWrite()

a. 功能
特定的数字引脚输出PWM波
b. 语法

analogWrite(pin, value);

c. 参数解释
pin:特定的数字引脚,在Arduino UNO中只有引脚3、5、6、9、10、11支持PWM输出(即引脚数字前有波浪线的引脚)。
value:PWM占空比(the duty cycle),一个整型数,范围在0 ~ 255之间。
d. 返回值

e. 说明

  • PWM输出其本质是调用定时器的比较模块,而Arduino UNO中内置了三个定时器,分别是Timer0,Timer1、Timer2。

    • Timer08位定时器,对应引脚5和6,其产生的PWM频率为490HZ
    • Timer116位定时器,对应引脚9和10,其产生的PWM的频率为980HZ
    • Timer28位定时器,对应引脚3和11,其产生的PWM频率为490HZ
  • 此外,由于delay()、millis()、delayMicroseconds() 等函数依赖于定时器Timer0,因此5、6引脚输出的PWM波的占空比可能会高于预期值(higher-than-expected)
  • 调用analogWrite()函数前可以不调用pinMode()函数。
  • analogWrite()函数虽然和analogRead()函数很相近,但二者没有任何关系,一个是定时器的比较模块,一个是ADC模块。

(3)高级 I/O(Soft USART)

shiftOut()

a. 功能
串行输出数据,一次一位(one bit a time)
b. 语法

shiftOut(dataPin, clockPin, bitOrder, value);

c. 参数解释
dataPin: 串行输出数据的引脚号(int)
clockPin: 时钟引脚号(int)
bitOrder: 串行传输数据的顺序,有以下选项:

  • MSBFIRST(Most Significant Bit First):从左往右传输,大数优先
  • LSBFIRST(Least Significant Bit First):从右往左传输,小数优先

value: 需要传输的数据(byte)
d. 返回值

e. 说明

  1. dataPin和clockPin必须用pinMode函数设置为输出模式。
  2. value值只能是一个字节,如果需要传输多字节数据,需要考虑分字节传输。
  3. 传输数据的步骤:clockPin来一个脉冲(低-高-低),传输一位数据。因此如果连接的外设是上升沿触发,则在调用该函数前最好手动将clockPin置低。

shiftIn()

a. 功能
串行读取数据,一次一位(one bit a time)
b. 语法

byte_incoming = shiftIn(dataPin, clockPin, bitOrder);

c. 参数解释
dataPin: 串行输出数据的引脚号(int)
clockPin: 时钟引脚号(int)
bitOrder: 串行传输数据的顺序,有以下选项:

  • MSBFIRST(Most Significant Bit First):从左往右传输,最高位优先
  • LSBFIRST(Least Significant Bit First):从右往左传输,最低位优先

d. 返回值
读取的数据(byte)
e. 说明
参考shiftOut

pulseIn()

a. 功能
读取脉冲(高脉冲或低脉冲)的时间宽度
b. 语法

pulseIn(pin, value);
pulseIn(pin, value, timeout);

c. 参数解释
pin:脉冲读取引脚;
value:读取脉冲的形式(高脉冲、低脉冲):

  • HIGH:读取高脉冲(高电平持续时间)
  • LOW:读取低脉冲(低电平持续时间)

timeout(optional):等待时间(unsigned long,单位:μs)
d. 返回值
脉冲的时间宽度(单位:μs),如果在timeout时间内没有读取到脉冲则返回0.
e. 说明
脉冲长度读取范围为 10μs~3min,超过这个范围读取值会发生错误

tone()

a. 功能
产生特定频率的方波(即音调)
b. 语法

tone(pin, frequency);
tone(pin, frequency, duration);

c. 参数解释
pin:产生音调的引脚
frequency:音调的频率(单位:Hz)
duration(optional):持续时间(单位:μs),如果没有则音调直到调用noTone函数时停止。
d. 返回值

e. 说明

  1. 该函数是调用定时器Timer2,因此使用该函数会影响引脚3和11的PWM输出
  2. 频率不能低于31HZ
  3. 该函数用法:连接无源蜂鸣器时输出音频。
  4. 若该引脚已经在输出音频,那么调用该函数只能改变音调的频率,如果其他引脚正在输出音频,调用该函数无效,只能先调用noTone函数停止其他引脚的音频,再调用该引脚上的tone函数。

noTone()

a. 功能
停止引脚上的音频输出
b. 语法

noTone(pin);

c. 参数解释
pin:需要停止输出音频的引脚。
d. 返回值

(4)时间函数(Timer)

millis()

a. 功能
返回定时器的计数值(单位:ms)——自程序运行开始计时,大约50天溢出 (根据unsigned long数据大小算出来的,因此返回值必须用unsigned long类型接收
b. 语法

nowTime_ms = millis();

c. 参数解释

d. 返回值
定时器的计数值(单位:ms,unsigned long)

micros()

a. 功能
返回定时器的计数值(单位:μs)——自程序运行开始计时,大约70min溢出 (根据unsigned long数据大小算出来的,因此返回值必须用unsigned long类型接收
b. 语法

nowTime_us = micros();

c. 参数解释

d. 返回值
定时器的计数值(单位:μs,unsigned long)

delay()

a. 功能
延时(ms级)
b. 语法

delay(ms);

c. 参数解释
ms:延时时间,单位为ms(unsigned long)
d. 返回值

delayMicroseconds()

a. 功能
延时(μs级)
b. 语法

delayMicroseconds(us);

c. 参数解释
us:延时的微秒数(unsigned long)
d. 返回值

e. 说明

  1. 目前的Arduino版本只支持 <16383的微秒延时,如果需要更长的延时时间,需要调用delay函数;而且延时时间最好大于3μs,这样的延时更加精确。
  2. 新版本(0018)的Arduino中,调用该函数不会禁用中断(表明这个函数不是用定时器中断写的)

(5)数学函数

min()

a. 功能
取两个数中的较小值
b. 语法

z = min(x, y);

c. 参数解释
x,y:需要比较的数,数据类型任意
d. 返回值
两个数中的较小值。

max()

a. 功能
取两个数中的较大值
b. 语法

z = max(x, y);

c. 参数解释
x,y:需要比较的数,数据类型任意
d. 返回值
两个数中的较大值。
e. 说明

  1. 也许与直觉相反,max() 通常用于限制变量范围的下限,而 min() 用于限制范围的上限。
  2. 参数x,y不能用表达式代替,比如 x++y- - 等。

constrain()

a. 功能
限制数据的范围。
b. 语法

constrain(x, a, b);

c. 参数解释
x:需要限制的范围,任意数据类型;
a:限制下限,任意数据类型;
b:限制上限,任意数据类型。
d. 返回值

  • 如果a<=x<=b,返回x
  • 如果x>b,返回b
  • 如果x<a,返回a

map()

a. 功能
将一个整数从一个范围映射到另一个范围。
b. 语法

map(value, fromLow, fromHigh, toLow, toHigh);

c. 参数解释
value:需要映射的值,long类型
fromLow:原范围下限,long类型
fromHigh:原范围上限,long类型
toLow:映射的范围下限,long类型
toHigh:映射范围上限,long类型
d. 返回值
映射后的值(long)
e. 说明

  1. 鉴于这个函数表述不够明白,这里给出定义,非常简单:
long map(long x, long in_min, long in_max, long out_min, long out_max)
{return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
  1. 根据定义可知,上下限可以颠倒;可以是负数;如果出现分数会自动取整(不会四舍五入)

pow()

a. 功能
指数运算函数
b. 语法

pow(base, exponent);

c. 参数解释
base:底数(float)
exponent:指数(float)
d. 返回值
运算结果(double)

sqrt()

a. 功能
求平方根
b. 语法

sqrt(x);

c. 参数解释
x:需要求平方根的数,任意数据类型
d. 返回值
运算结果(double)
e. 说明
注意与 sq(x) 函数进行区分,sq(x) 是求x的平方,x为任意数据类型。

三角函数

sin(rad); //rad为弧度,float类型,计算结果为double类型
cos(rad); //rad为弧度,float类型,计算结果为double类型
tan(rad); //rad为弧度,float类型,计算结果为double类型

(6)字符判断函数

  字符判断函数取自C语言的库<ctype.h>,函数格式相同:

bool fun_name(char c)

即参数都是char类型,返回值均为布尔型,注意:Arduino中的char类型默认是unsigned char!,参考链接

isAlphaNumeric(thisChar); //判断字符是否为数字或字母('0'~'9','A'~'Z','a'~'z')
isAlpha(thisChar);  //判断字符是否为字母Alphabetical('A'~'Z','a'~'z')
isLowerCase(thisChar);  //判断字符是否为小写字母
isUpperCase(thisChar);  //判断字符是否为大写字母
isSpace(thisChar);   //判断字符是否为空格
isAscii(thisChar);  //判断字符是否为ASCII字符(0~127)
isWhitespace(thisChar); //判断字符是否为whitespace
isControl(thisChar); //判断字符是否为控制字符
isDigit(thisChar); //判断字符是否为数字
isGraph(thisChar); //判断字符是否为可打印字符
isPrintable(thisChar); //判断字符是否为可打印字符
isPunct(thisChar); //判断字符是否为标点符号
isHexadecimalDigit(thisChar); //判断字符是否为有效的十六进制数字

(7)随机函数

random()

a. 功能
生成一定范围内的随机数(整数
b. 语法

random(max);
random(min, max);

c. 参数解释
max:随机数的上限,不包含(long)
min(optional):随机数的下限,包含在内,没有默认为0
d. 返回值
一个随机数(long),范围 [min, max-1]
e. 说明
这个函数产生的随机数确实是符合随机分布,但每次产生的随机数的序列都是一样的,所以本质上是一个伪随机函数,如果需要产生真随机函数,就需要改变随机数的序列,方法就是利用 randomSeed() 生成一个随机“种子”,或者叫随机源,详情见后面。

randomSeed()

a. 功能
初始化随机数源
b. 语法

randomSeed(seed);

c. 参数解释
seed:为一个整形数(long or int),但为了保持随机性,一般设置为空引脚的analogRead值,比如analogRead(A0)
d. 返回值

(8)字节函数

  在单片机中传输数据时,往往最关心的就是数据的字节数,因此掌握字节操作函数对传输数据处理有很大帮助。

lowByte(x); //获取x的最低字节,x为任意数据类型,返回一个字节
highByte(x); //获取x的最低字节,x为任意数据类型,返回一个字节
bitRead(x, n); //读取x的第n-1位,最低位为0,从右至左依次增加。返回1或0
bitWrite(x, n, b); //将x的第n-1位写为b,b为0或1,无返回值
bitSet(x, n); //将x的第n-1位置1
bitClear(x, n); //将x的第n-1位清0

(9)外部中断函数(GPIO Interrupt)

interrupts()

a. 功能
打开总中断
b. 语法

interrupts();

c. 参数解释

d. 返回值

e. 说明
Arduino的中断默认是打开的,只有当中断被关闭时才会使用该函数重新打开。

noInterrupts()

a. 功能
关闭总中断
b. 语法

noInterrupts();

c. 参数解释

d. 返回值

attachInterrupt()

a. 功能
设置中断服务程序(Interrupt Service Routine,简称ISR)
b. 语法

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);  (recommended)
/*digitalPinToInterrupt(pin)是将实际的引脚号转换为中断对应的引脚号*/
attachInterrupt(interrupt, ISR, mode);  (not recommended)
attachInterrupt(pin, ISR, mode) ;   (not recommended Arduino Due, Zero only)

c. 参数解释
pin:中断引脚,在UNO型号中,只支持2、3引脚
ISR:中断服务程序(一个无参数无返回值的函数)
mode:中断模式,有以下选项:

  • LOW:在引脚为低电平时,产生中断
  • CHANGE:引脚电平改变时(上升沿或下降沿),产生中断
  • RISING:上升沿中断
  • FALLING:下降沿中断
  • HIGH:引脚为高电平时,发生中断 (只支持Due,Zero)

interrupt:或者叫interrupt number,与引脚号一一对应但不相同,如下图所示:

d. 返回值

e. 说明
  中断服务程序(ISR)是一种特殊的函数没有参数,没有返回值,当程序进入中断服务程序时,总中断会关闭,只有在执行完毕当前的ISR才能去执行下一个ISR,因此一次只能执行一个ISR,且ISR内不能再嵌套ISR。因此,需要依赖中断的函数在ISR内将失效,比如delay(), millis(), micros() ,而函数delayMicroseconds() 仍然有效。
  当程序有多个中断时,且执行频率较高的话,就需要将ISR写得尽可能简洁。由于ISR没有参数,如果需要传递变量,需要将变量定义为全局变量,且要加上volatile 关键字,表明在ISR中可以进行修改。

detachInterrupt()

a. 功能
关闭特定的中断
b. 语法

detachInterrupt(interrupt);
detachInterrupt(digitalPinToInterrupt(pin));
detachInterrupt(pin);   (Arduino Due, Zero only)

c. 参数解释
pin:中断引脚
interrupt:中断数字,参见上面的解释
d. 返回值

e. 说明
注意和noInterrupt() 函数区分,后者是关闭总中断,而该函数是关闭某个外部中断。

串行通讯(Hardware)

UART

  在Arduino UNO中,只有一个UART模块,对应数字引脚0和1,程序中,用Serial这个类表示串口,其内部预置了很多函数,用来实现串口通讯的各种功能。以下将一一介绍

if (Serial)

a. 功能
指示某个串口是否连接(比如打开电脑上的串口)(但只适用于Leonardo, Yun中连接USB的端口)
b. 语法

if (Serial){}

c. 参数解释

d. 返回值
一个布尔值,连接为true,未连接为false。

available()

a. 功能
返回到达 串行缓存区(64 byte) 中但未被读取的字节的个数
b. 语法

Serial.available()Serial1.available()  // Arduino Mega only
Serial2.available()
Serial3.available()

c. 参数解释

d. 返回值
未被读取的字节数

availableForWrite()

a. 功能
在不阻塞写操作的情况下获取可用于写入串行缓冲区的字节数。
b. 语法

Serial.availableForWrite();

c. 参数解释

d. 返回值
待写字节数。

begin()

a. 功能
串口初始化设置(波特率,数据传输格式)
b. 语法

Serial.begin(speed)
Serial.begin(speed, config)

c. 参数解释
speed:波特率(1s传输多少位)与电脑的连接一般是300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200中的一种,在引脚0和1连接时可以根据外设任意设置。
config:数据传输格式:数据位(7位,8位或其他),校验位(奇校验Odd,偶校验Even,无校验None),停止位(1位或2位),一般有如下选项:

  • SERIAL_5N1
  • SERIAL_6N1
  • SERIAL_7N1
  • SERIAL_8N1 (the default)
  • SERIAL_5N2
  • SERIAL_6N2
  • SERIAL_7N2
  • SERIAL_8N2
  • SERIAL_5E1
  • SERIAL_6E1
  • SERIAL_7E1
  • SERIAL_8E1
  • SERIAL_5E2
  • SERIAL_6E2
  • SERIAL_7E2
  • SERIAL_8E2
  • SERIAL_5O1
  • SERIAL_6O1
  • SERIAL_7O1
  • SERIAL_8O1
  • SERIAL_5O2
  • SERIAL_6O2
  • SERIAL_7O2
  • SERIAL_8O2

d. 返回值

end()

a. 功能
禁用串口
b. 语法

Serial.end();

c. 参数解释

d. 返回值

write()

a. 功能
将二进制数据写入串口。
b. 语法

Serial.write(val);
Serial.write(str);
Serial.write(buf, len);

c. 参数解释
val:单字节数据(char, byte)
str:字符数组, 字符串(char[], byte[] )
buf:字符数组
len:buf的长度
d. 返回值
被写入的字节数(char)

read()

a. 功能
读取缓存区中第一个字节,并在缓存区中删除
b. 语法

Serial.read();

c. 参数解释

d. 返回值
第一个字节或-1(未读到数据)

peek()

a. 功能
读取缓存区中第一个字节,但不在缓存区中删除
b. 语法

Serial.peek();

c. 参数解释

d. 返回值
第一个字节或-1(未读到数据)如果反复调用该函数,读取到的数据是一样的

print()

a. 功能
按格式输出各种类型的数据,将各种数据输出为可见的ASCII码格式
b. 语法

Serial.print(val);
Serial.print(val, format);

c. 参数解释
val:需要输出的数据(多种格式)
format(optional):数据输出格式(或小数点位数)详情参照以下实例:

Serial.print(78); // "78"
Serial.print(1.23456); // "1.23"
Serial.print('N'); // "N"
Serial.print("Hello world."); // "Hello world."Serial.print(78, BIN); // "1001110"
Serial.print(78, OCT); // "116"
Serial.print(78, DEC); // "78"
Serial.print(78, HEX); // "4E"
Serial.println(1.23456, 0); // "1"
Serial.println(1.23456, 2); // "1.23"
Serial.println(1.23456, 4); // "1.2346"Serial.print(F(“Hello World”));  //利用F()将基于flash的字符串输出

d. 返回值
返回输出字节的个数(可以不读取)

println()(ln为"line"的缩写)

a. 功能
和print函数一样,但输出的内容自带换行符( ‘\r’ 和 ‘\n’ )
b. 语法

Serial.println(val);
Serial.println(val, format);

c. 参数解释
参考print函数
d. 返回值
返回输出字节的个数(可以不读取)

readBytes()

a. 功能
读取缓存区中的字符并放在设定长度的缓存区中,当buffer装满或超时,则函数终止。
b. 语法

Serial.readBytes(buffer, length);

c. 参数解释
buffer:用来储存字符的缓存区(char[],or byte[])
length:buffer的长度(int)
d. 返回值
放入buffer的字节数(char),如果没有合法字符,返回 A0

readBytesUntil()

a. 功能
和readBytes函数一样,读取缓存区中的字符并放在设定长度的缓存区中,但终止条件多了一个——检测到终止字符character。
b. 语法

Serial.readBytesUntil(character, buffer, length);

c. 参数解释
character:终止字符(char)
buffer:缓存区(char[] or byte[] )
length:buffer的长度
d. 返回值
放入buffer的字节数,如果没有合法字符,返回 A0

readString()

a. 功能
读取缓存区中的字符串,直到时间times out才停止
b. 语法

Serial.readString();

c. 参数解释

d. 返回值
读取到的字符串(char[] )

readStringUntil()

a. 功能
读取缓存区的字符串,直到终止符出现或时间到才停止
b. 语法

Serial.readStringUntil(terminator);

c. 参数解释
terminator:终止字符
d. 返回值
整个字符串(char[] )

find()

a. 功能
在串行缓存区中查找对应的字符
b. 语法

Serial.find(target);

c. 参数解释
target:需要查找的字符(char)
d. 返回值
布尔值,找到为true,未找到为false。

findUntil()

a. 功能
在串行缓存区中查找字符直到设定的终止字符被找到
b. 语法

Serial.findUntil(target, terminal);

c. 参数解释
target:目标字符
terminal:终止字符
d. 返回值
布尔值,找到为true,没找到或超时为false。

flush()

a. 功能
等待串口传输完成
b. 语法

Serial.flush();

c. 参数解释

d. 返回值

setTimeout()

a. 功能
设置超时时间(单位为ms),默认为1000ms
b. 语法

Serial.setTimeout(time);

c. 参数解释
time:时间值,单位为ms。
d. 返回值

parseFloat()

a. 功能
读取缓存区中第一个浮点数(终止于第一个非浮点数)
b. 语法

Serial.parseFloat();

c. 参数解释

d. 返回值
读取到的浮点数(float)

parseInt()

a. 功能
在缓存区中查找下一个有效整数。
b. 语法

Serial.parseInt();
Serial.parseInt(char skipChar);

c. 参数解释
skipChar:用于跳过搜索中指定的字符。 例如用于跳过千位分隔符。
d. 返回值
下一个有效整数(long类型)

SPI

(有缘再写)

I2C

(有缘再写)

注:以上内容主要参考自官方的手册,介绍两种方法寻找该文件:

  • 方法一:到IDE安装根目录下找。参考:C:/Program Files (x86)/Arduino/reference/www.arduino.cc/en/Reference/PulseIn.html
  • 方法二:打开IDE写一个常用的函数,然后右键,选择在参考文件中查找

高级应用:用AVR开发Arduino

  我们都知道,单片机的程序,本质上就是对内置的寄存器的读和写,虽然Arduino的集成度很高,但是仍然可以用寄存器的方法来开发,但程序的麻烦程度将陡增。
  很多人一想到用寄存器开发,第一反应就是:太麻烦。确实,用寄存器开发在初始阶段确实很麻烦,需要去了解某个模块是由哪些寄存器控制的,这是一个需要花费较多时间精力去熟悉的过程,但是如果熟悉了寄存器,也积累了一些自己写的库之后,其实和用库函数开发是差不多的。但是用寄存器写,可以让你最大程度了解该单片机的各种模块。
  对于Arduino来说,一般的开发确实没有必要,只要大致理解函数用的是哪些模块即可,但是如果想要编写自己的库(比如Timer库)或者查看函数源码,就必须要懂寄存器语言了。

附:

  • AVR开发 Arduino方法(一) 端口子系统
  • AVR开发 Arduino方法(二) 中断子系统
  • AVR开发 Arduino方法(三) 定时/计数器子系统
  • AVR开发 Arduino方法(四) 串行通信子系统
  • AVR开发 Arduino方法(五) 模数转换子系统
  • AVR开发 Arduino方法(六) 内存子系统
  • AVR开发 Arduino方法(七) 嵌入式操作系统FreeRTOS
  • AVR开发 Arduino方法(附一) 工具链与调试技术
  • AVR开发 Arduino方法(附二) 故障排除:烧录引导程序
  • AVR开发 Arduino方法(附三) 附件列表
  • AVR开发 Arduino方法(附四) 参考文献与网址
  • arduino 定时器、定时中断与PWM使用以及注意事项

其他操作

1. Arduino IDE的“高级用法”——串口绘图器

  谈到Arduino的串口,我们第一时间想到的就是IDE右上角的那个串口图标,但其实Arduino还有一个串口绘图器的功能,也在工具菜单栏里面。

  使用的方法也很简单,和串口输出一样,使用Serial.println() 函数即可。有其他绘图需求的可以参考这篇文章。

2. Arduino IDE的替代编辑器——Visual Studio Code

  Arduino IDE缺少一个很重要的功能,那就是代码补全的功能,这严重降低了写代码的效率,而且Arduino IDE的UI也差强人意,因此很多人都不用Arduino IDE编程,转而寻找替代品,而用得最多的,就是VS Code 。这个网上有很多配置方法,也比较简单,可以参考这个链接,如果遇到什么问题,可以在浏览器点对点搜索,不再赘述。

  其他教程:

  • VScode配置Arduino开发环境 保姆级教程 - CSDN
  • Arduino头文件在VS code中提示错误红色波浪线的解决办法 - CSDN

3. Arduino IDE v2.0 Beta版本

  最近才知道Arduino IDE出2.0版本了,据说增加了代码补全和代码高亮 的功能。附: 下载链接

4. 记录两个写得非常好的教程

  • 极速入门教程(上)
  • 极速入门教程(下)

【单片机】Arduino(以UNO R3为例)相关推荐

  1. 单片机学习笔记(Arduino Uno r3)

    单片机学习笔记(Arduino  Uno r3) Aduino是什么? 分为硬件和软件两个部分,硬件和软件共同组成了Arduino,使用时须将Arduino硬件和软件配合使用 硬件:Arduino系列 ...

  2. arduino uno r3单片机封装图_Arduino提高篇22—实时时钟DS1302

    关注.星标公众号,不错过精彩内容 编辑:Tony 来源:公众号TonyCode 很多电子爱好者都热衷制作电子时钟来练手,这些时钟会使用数码管.点阵屏.LCD液晶屏.OLED屏.TFT屏等显示模块,所使 ...

  3. 基于Arduino UNO R3的植物管家开发过程(一)

    前言 最近时不时收到CSDN粉丝的留言,忍不住打开了尘封已久的博客.自从工作以后,已经整整四年没有在CSDN中发过文章了.一打开博客,看着曾经记录的点点滴滴,回想起自己刚高中毕业的时候,连打字都不会, ...

  4. Arduino Uno R3 communication

    文章目录 Introduction Aim 目标 Objectives Device 设备 Arduino Uno Technical specifications 技术规格 General pin ...

  5. 新手必读:Arduino UNO R3教程,原理图,引脚图,详细介绍

    刚入门的学习Arduino的朋友都会有个疑问Arduino UNO R3是什么?为什么要从Arduino UNO R3开始学起? Arduino概述: Arduino是一个开放源码电子原型平台,拥有灵 ...

  6. arduino的esp32程序无法上传_原装正版arduino uno R3无法上传程序

    RT,本人在网络上买的原装意大利产正版Arduino uno R3(售价159RMB,坏了很可惜,实在找不到问题所在.)无法上传程序. 已排除问题如下:1.驱动已正确安装 端口.PNG (2.12 K ...

  7. 基于arduino UNO R3的远程可控的红外热释传感器 (转)

    首先实物图奉上,比较简陋别见怪啦哈哈 <ignore_js_op> ●实验名称:基于机智云平台的红外热释传感器的应用 ●实验目的:1. 能够在云平台下,手机实时观测传感器返回的AD值:   ...

  8. arduino步进电机程序库_Arduino入门教程15(步进电机驱动库的使用):Arduino Uno R3+ULN2003+步进电机 使用Stepper驱动库,控制步进电机转动角度...

    本篇介绍步进电机驱动库的使用,通过读取电位器输入,控制步进电机转动相应角度. Stepper库是官方提供的驱动库,我们启动Arduino IDE,点击「文件」-「示例」就能找到Stepper库,官方提 ...

  9. RFID模块+WIFI模块+振动传感器+有源蜂鸣器+舵机+Arduino UNO R3所构成的门禁系统模块

    该系统模块主要由RFID模块+WIFI模块+振动传感器+有源蜂鸣器+舵机+Arduino UNO R3组成的门禁系统模块.这里使用舵机充当门锁,用户可以刷卡开门,也可以通过APP控制舵机状态达到开门的 ...

最新文章

  1. 设计模式之代理模式(Proxy)摘录
  2. HTML标签大全(三)
  3. BZOJ4893: 项链分赃 BZOJ4895: 项链分赃(增强版)
  4. Java和C语言的语句对比
  5. 【技术教程】SequoiaDB对接Kafka
  6. 程序人生:无他,唯心向尔
  7. python爬虫面试问题_Python爬虫面试总结
  8. RN自定义组件封装 - 播放类似PPT动画
  9. mybatis_user_guide(6) Java API
  10. jmeter web监听结果_Jmeter性能测试
  11. JavaScript replace string 替换字符
  12. 公司的Java框架应具备的通用功能
  13. 短信猫前台群发短信的示例程序
  14. django初体验 学习笔记
  15. iQOO5G手机卡槽公布
  16. 【java】getWriter() has already been called for this
  17. Linux -- 查找文件内容或文件位置
  18. 深圳大厂程序员自述:我37岁,年薪百万,等着被公司干掉!
  19. 如何打造高端的数据报表?
  20. python陆股通_沪股通、深股通、港股通、陆股通都是什么鬼?傻傻分不清

热门文章

  1. crx2rnx格式转换
  2. 为什么计算机领域没有诺贝尔奖,为什么没有数学家获得诺贝尔奖
  3. 使用计算机需要准备硬件和什么,当个人计算机需要使用ADSL访问Internet时,所需的基本硬件设施是什么?...
  4. 一起去追寻那大漠孤烟
  5. 对全职高手的自然语言处理
  6. Tushare + Backtrader实现双均线策略 以工商银行为例
  7. 相位式激光测距法中相位产生原理
  8. 致终将逝去的2021
  9. 就算是假期也全力以赴,学习不能停
  10. 使用飞信VMDotNet使C#程序脱离.NET FRAMEWORK也能运行的一些心得 ------(我复制别个的)