我用的 ESP32 DEVKIT V1
引腳圖
原理圖
【騰訊文檔】ESP32引腳功能篩選器https://docs.qq.com/sheet/DWXpUWVFMZWlQZGl4
一、GPIO
1、初始化GPIO
pinMode(pin, mode)
作用:設(shè)置一個(gè)引腳(pin)作為GPIO時(shí)的I/O模式。
參數(shù):
pin:引腳編號(hào)
mode:GPIO的I/O模式,取值有3種
INPUT :作為數(shù)字輸入
OUTPUT :作為數(shù)字輸出
INPUT_PULLUP:作為數(shù)字輸入,且使能引腳的內(nèi)部上拉電阻
注意:
a、引腳作為PWM輸出時(shí),無(wú)需先前使用pinMode配置其模式,因?yàn)镻WM本身就代表了輸出的意思。且官方庫(kù)源代碼中可以發(fā)現(xiàn),它已經(jīng)幫我們配置為輸出了。
b、模擬引腳也可以作為數(shù)字引腳使用,完全OK。這在數(shù)字引腳不夠用的情況下非常有用。
2、GPIO數(shù)字輸出
digitalWrite(pin,value)
作用:設(shè)置一個(gè)數(shù)字輸出引腳的輸出電平值,HIGH或者LOW。
參數(shù):
pin:引腳編號(hào)。此引腳必須在之前使用pinMode設(shè)置為OUTPUT模式。
value:2個(gè)值
LOW:輸出低電平
HIGH:輸出高電平
3、GPIO數(shù)字輸入
int digitalRead(pin)
作用:讀取一個(gè)數(shù)字輸入引腳的電平值。
返回:HIGH(高電平)或者LOW(低電平)。
參數(shù):
pin:引腳編號(hào)。
示例 : 按鍵控制燈亮滅
void setup()
{
pinMode(2,OUTPUT);
pinMode(0,INPUT_PULLUP);
}
void loop()
{
if(digitalRead(0))
{
while(digitalRead(0));
digitalWrite(2,!digitalRead(2));
}
}
4、GPIO模擬輸入:analogRead(pin)
注意 : 模擬輸入是通過(guò)PWM實(shí)現(xiàn)的, 所以不需要初始化PIN
analogRead(4)
5. 模擬信號(hào)輸入分辨率: analogSetWidth(bit);
| bit的值 | 范圍 |
|---|---|
| 9 | 0~511 |
| 10 | 0~1023 |
| 11 | 0~2047 |
| 12(默認(rèn)) | 0~4095 |
6. 模擬信號(hào)輸出 (基于LEDC)
LEDC是基于PWM調(diào)制實(shí)現(xiàn)模擬輸出的.
與arduino uno主板不同, ESP32的PWM模擬是一個(gè)個(gè)通道 共16個(gè), 通道可以映射到引腳上. 引腳就可以輸出PWM信號(hào)了.

6.1 設(shè)置通道 ledcSetup(channel,freq,bit_num)
參數(shù):
- channel : LEDC的PWM通道參數(shù),可選0~15
- freq : 10Hz到40MHz , 但較高的頻率精確度低
- bit_num: 占空比分辨率(可選1~16), 比如bit_num=8 則范圍 0~2的8次方 , 也就是0~255
推薦的配置:
| 頻率 | 位深 | 過(guò)渡的可用步驟 |
|---|---|---|
| 1220赫茲 | 16 | 65536 |
| 2441赫茲 | 15 | 32768 |
| 4882赫茲 | 14 | 16384 |
| 9765Hz | 13 | 8192 |
| 19531赫茲 | 12 | 4096 |
ledcSetup(1,1200,16);
6.2 通道與引腳映射 ledcAttachPin(pin,channel)
ledcAttachPin(5,1);
注意: 一個(gè)通道可以同時(shí)映射多個(gè)引腳
6.3 取消引腳的PWM映射 ledcDetachPin(pin)
ledcDetachPin(5);
6.4 向指定通道寫(xiě)入占空比 ledcWrite(channel,duty)
例: 呼吸燈
bool add_status = true;
void setup()
{
pinMode(2,OUTPUT);
ledcSetup(2,1200,8);
ledcAttachPin(2,2);
}
void loop()
{
for(int i = 0 ; i<256; i++)
{
if(add_status)
{
ledcWrite(2,i);
}
else
{
ledcWrite(2,256-i);
}
delay(5);
}
add_status = !add_status;
}
例子, 全彩呼吸燈
#include <Arduino.h>
#define LED_R 27
#define LED_G 33
#define LED_B 32
void setup()
{
Serial.begin(115200);
ledcSetup(1, 1200, 8);
ledcSetup(2, 1200, 8);
ledcSetup(3, 1200, 8);
ledcAttachPin(LED_R, 1);
ledcAttachPin(LED_G, 2);
ledcAttachPin(LED_B, 3);
ledcWrite(1, 255);
ledcWrite(2, 255);
ledcWrite(3, 255);
}
void loop()
{
for (int i = 0; i < 510; i++)
{
if (i >= 0 && i < 255)
ledcWrite(1, 255 - i);
if (i >= 255 && i < 510)
ledcWrite(1, i - 255);
if (i >= 0 && i < 170)
ledcWrite(2, 85 + i);
if (i >= 170 && i < 425)
ledcWrite(2, 425 - i);
if (i >= 425 && i < 510)
ledcWrite(2, i - 425);
if (i >= 0 && i < 85)
ledcWrite(3, 85 - i);
if (i >= 85 && i < 340)
ledcWrite(3, i - 85);
if (i >= 340 && i < 510)
ledcWrite(3, 595 - i);
delay(10);
}
}
6.5 向指定通道輸出指定頻率的音符信號(hào) ledcWriteTone(channel, freq)
6.6 向指定通道輸出指定的音符和音階 ledcWriteNote(channel,note,octava)
參數(shù)
- note : 音符 可選(NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_C......)
- octava : 音階 , 可選0~7
7. 模擬信號(hào)輸出函數(shù) (基于DAC)
ESP32提供了兩個(gè)DAC通道, 對(duì)應(yīng)引腳25 , 26. 精度為8位.
dacWrite(pin,value);
- value取值: 0~255
void setup()
{
}
void loop()
{
for(int i = 0 ; i<256; i++)
{
dacWrite(25,i);
delay(10);
}
}
二、串口打印 UART
ESP32共有3個(gè)UART端口, 其中UART1用于Flash讀/寫(xiě).
| 串口名 | Arduino名 | TX | RX |
|---|---|---|---|
| UART0 | Serial | pin1 | pin3 |
| UART1 | Serial1 | pin10 | pin9 |
| UART2 | Serial2 | pin17 | pin16 |
1、串口初始化
Serial.begin(speed, config)
- 參數(shù):
- speed:波特率,一般取值9600,115200等。
- config:設(shè)置數(shù)據(jù)位、校驗(yàn)位和停止位。默認(rèn)SERIAL_8N1表示8個(gè)數(shù)據(jù)位,無(wú)校驗(yàn)位,1個(gè)停止位。
- 返回值:無(wú)。
2、關(guān)閉串口
Serial.end()
- 描述:禁止串口傳輸。此時(shí)串口Rx和Tx可以作為數(shù)字IO引腳使用。
- 原型:Serial.end()
- 參數(shù):無(wú)。
- 返回值:無(wú)。
3、串口打印
Serial.print()
- 描述:串口輸出數(shù)據(jù),寫(xiě)入字符數(shù)據(jù)到串口。
- 原型:
- Serial.print(val)
- Serial.print(val, format)
- 參數(shù):
- val:打印的值,任意數(shù)據(jù)類(lèi)型。
- config:輸出的數(shù)據(jù)格式。BIN(二進(jìn)制)、OCT(八進(jìn)制)、DEC(十進(jìn)制)、HEX(十六進(jìn)制)。對(duì)于浮點(diǎn)數(shù),此參數(shù)指定要使用的小數(shù)位數(shù)。
4、串口輸出數(shù)據(jù)并換行 println() 和 printf()
Serial.println()
Serial.printf()
- 描述:串口輸出數(shù)據(jù)并換行。
- 原型:
- Serial.println(val)
- Serial.println(val, format)
- 參數(shù):
- val:打印的值,任意數(shù)據(jù)類(lèi)型。
- config:輸出的數(shù)據(jù)格式。
- 返回值:返回寫(xiě)入的字節(jié)數(shù)。
附: 常用格式字符及轉(zhuǎn)義字符
| 字符 | 說(shuō)明 |
|---|---|
| %o | 八進(jìn)制整數(shù)輸出 |
| %d | 十進(jìn)制整數(shù)輸出 |
| %x | 十六進(jìn)制整數(shù)輸出 |
| %f | 浮點(diǎn)輸出,默認(rèn)6位小數(shù) |
| %c | 單字符輸出 |
| %s | 字符串輸出 |
| \n | 換行 |
| \r | 回車(chē) |
| \t | Tab制表符 |
5、將二進(jìn)制數(shù)寫(xiě)入串口
Serial.write()
描述
將二進(jìn)制數(shù)據(jù)寫(xiě)入串行端口。該數(shù)據(jù)以字節(jié)或一系列字節(jié)的形式發(fā)送;要發(fā)送代表數(shù)字?jǐn)?shù)字的字符,請(qǐng)改用print()函數(shù)。
句法
*Serial*.write(val)
*Serial*.write(str)
*Serial*.write(buf, len)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
val:要作為單個(gè)字節(jié)發(fā)送的值。
str:作為一系列字節(jié)發(fā)送的字符串。
buf:要作為一系列字節(jié)發(fā)送的數(shù)組。
len:要從數(shù)組發(fā)送的字節(jié)數(shù)。
退貨
write()將返回寫(xiě)入的字節(jié)數(shù),盡管讀取該數(shù)字是可選的。資料類(lèi)型:size_t。
6、判斷串口緩沖區(qū)的狀態(tài)
Serial.available()
- 描述:判斷串口緩沖區(qū)的狀態(tài),返回從串口緩沖區(qū)讀取的字節(jié)數(shù)。
- 原型:Serial.available()
- 參數(shù):無(wú)。
- 返回值:可讀取的字節(jié)數(shù)。
7、讀取串口數(shù)據(jù)
Serial.read()
描述:讀取串口數(shù)據(jù),一次讀一個(gè)字符,讀完后刪除已讀數(shù)據(jù)。
- 原型:Serial.read()
- 參數(shù):無(wú)。
- 返回值:返回串口緩存中第一個(gè)可讀字節(jié),當(dāng)沒(méi)有可讀數(shù)據(jù)時(shí)返回-1,整數(shù)類(lèi)型。
#include <Arduino.h>
char rev;
void setup() {
Serial.begin(115200);
}
void loop() {
if(Serial.available())
{
rev=Serial.read();
Serial.print("rev=");
Serial.println(rev);
}
}
Serial.readBytes()
- 描述:從串口讀取指定長(zhǎng)度的字符到緩存數(shù)組。
- 原型:Serial.readBytes(buffer, length)
- 參數(shù):
- buffer:緩存變量。
- length:設(shè)定的讀取長(zhǎng)度。
返回值:返回存入緩存的字符數(shù)。
Serial.readString()
描述
Serial.readString()從串行緩沖區(qū)讀取字符到字符串。如果超時(shí),該函數(shù)將終止。
Serial.readString()從Stream實(shí)用程序類(lèi)繼承。
句法
*Serial*.readString()
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
返回值
一個(gè)String從串行讀緩沖器
Serial.readStringUntil()
描述
readStringUntil()從串行緩沖區(qū)讀取字符到字符串。如果超時(shí),該函數(shù)將終止(請(qǐng)參見(jiàn)setTimeout())。
Serial.readStringUntil()從Stream實(shí)用程序類(lèi)繼承。
句法
*Serial*.readStringUntil(terminator)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
terminator:要搜索的字符。允許的數(shù)據(jù)類(lèi)型:char。
返回值
String從串行緩沖區(qū)的整個(gè)讀取,直到終止符
注意和警告
終止符將從串行緩沖區(qū)中丟棄。
Serial.find()
描述
Serial.find()從串行緩沖區(qū)讀取數(shù)據(jù),直到找到目標(biāo)為止。true如果找到目標(biāo),函數(shù)將返回false超時(shí)。
Serial.find()從流實(shí)用程序類(lèi)繼承。
句法
*Serial*.find(target)
*Serial*.find(target, length)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
target:要搜索的字符串。允許的數(shù)據(jù)類(lèi)型:char。
length:目標(biāo)的長(zhǎng)度。允許的數(shù)據(jù)類(lèi)型:size_t。
返回值
資料類(lèi)型:bool。
Serial.findUntil()
描述
Serial.findUntil() 從串行緩沖區(qū)讀取數(shù)據(jù),直到找到給定長(zhǎng)度的目標(biāo)字符串或終止符字符串。
如果找到目標(biāo)字符串,則該函數(shù)返回true;如果超時(shí),則返回false。
Serial.findUntil()從Stream實(shí)用程序類(lèi)繼承。
句法
*Serial*.findUntil(target, terminal)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
target:要搜索的字符串。允許的數(shù)據(jù)類(lèi)型:char。
terminal:搜索中的終端字符串。允許的數(shù)據(jù)類(lèi)型:char。
返回值
資料類(lèi)型:bool。
Serial.parseFloat()
描述
Serial.parseFloat()從串行緩沖區(qū)返回第一個(gè)有效的浮點(diǎn)數(shù)。parseFloat()以不是浮點(diǎn)數(shù)的第一個(gè)字符終止。如果超時(shí),該函數(shù)將終止(請(qǐng)參見(jiàn)Serial.setTimeout())。
Serial.parseFloat()從Stream實(shí)用程序類(lèi)繼承。
句法
*Serial*.parseFloat()
*Serial*.parseFloat(lookahead)
*Serial*.parseFloat(lookahead, ignore)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
lookahead:用于在流中向前查詢(xún)浮點(diǎn)數(shù)的模式。允許的數(shù)據(jù)類(lèi)型:LookaheadMode。允許lookahead值:
-
SKIP_ALL:掃描流中的浮點(diǎn)數(shù)時(shí),除負(fù)號(hào),小數(shù)點(diǎn)或數(shù)字以外的所有字符都將被忽略。這是默認(rèn)模式。 -
SKIP_NONE:任何內(nèi)容都不會(huì)被跳過(guò),除非第一個(gè)等待的字符有效,否則流不會(huì)被觸摸。 -
SKIP_WHITESPACE:僅跳過(guò)制表符,空格,換行符和回車(chē)符。
ignore:用于跳過(guò)搜索中指示的字符。例如,用于跳過(guò)數(shù)千個(gè)分頻器。允許的數(shù)據(jù)類(lèi)型:char
返回值:
類(lèi)型:float。
Serial.parseInt()
描述
在輸入的序列中查找下一個(gè)有效整數(shù)。如果超時(shí),該函數(shù)將終止(請(qǐng)參見(jiàn)Serial.setTimeout())。
Serial.parseInt()從Stream實(shí)用程序類(lèi)繼承。
尤其是:
- 如果沒(méi)有讀取到可配置的超時(shí)值的字符,或者讀取了非數(shù)字,則分析停止。
- 如果在發(fā)生超時(shí)(請(qǐng)參見(jiàn)Serial.setTimeout())時(shí)未讀取到有效數(shù)字,則返回0;否則返回0。
句法
*Serial*.parseInt()
*Serial*.parseInt(lookahead)
*Serial*.parseInt(lookahead, ignore)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
lookahead:用于在流中向前搜索整數(shù)的模式。允許的數(shù)據(jù)類(lèi)型:LookaheadMode。允許lookahead值:
-
SKIP_ALL:掃描流中的整數(shù)時(shí),將忽略數(shù)字或減號(hào)以外的所有字符。這是默認(rèn)模式。 -
SKIP_NONE:任何內(nèi)容都不會(huì)被跳過(guò),除非第一個(gè)等待的字符有效,否則流不會(huì)被觸摸。 -
SKIP_WHITESPACE:僅跳過(guò)制表符,空格,換行符和回車(chē)符。
ignore:用于跳過(guò)搜索中指示的字符。例如,用于跳過(guò)數(shù)千個(gè)分頻器。允許的數(shù)據(jù)類(lèi)型:char
返回值
下一個(gè)有效整數(shù)。資料類(lèi)型:long。
8.判斷串口是否就緒** Serial
描述
指示指定的串行端口是否已就緒。
在具有本地USB的板上if (Serial)(或if(SerialUSB)在Due上)指示USB CDC串行連接是否打開(kāi)。對(duì)于所有其他板卡和非USB CDC端口,這將始終返回true。
這是在Arduino IDE 1.0.1中引入的。
句法
if (Serial) while (!Serial) 等等
參量
沒(méi)有
返回值
如果指定的串行端口可用,則返回true。如果在準(zhǔn)備就緒之前查詢(xún)Leonardo的USB CDC串行連接,則僅返回false。類(lèi)型:bool。
9、設(shè)置串口超時(shí)**
Serial.setTimeout()
描述
Serial.setTimeout()設(shè)置等待串行數(shù)據(jù)的最大毫秒數(shù)。默認(rèn)值為1000毫秒。
Serial.setTimeout()從Stream實(shí)用程序類(lèi)繼承。
句法
*Serial*.setTimeout(time)
參量
*Serial*:串行端口對(duì)象。請(qǐng)參閱“ 串行”主頁(yè)上每個(gè)板的可用串行端口列表。
time:超時(shí)時(shí)間(以毫秒為單位)。允許的數(shù)據(jù)類(lèi)型:long。
退貨
沒(méi)有
注意和警告
使用通過(guò)*Serial*.setTimeout()以下方式設(shè)置的超時(shí)值的串行函數(shù):
*Serial*.find()*Serial*.findUntil()*Serial*.parseInt()*Serial*.parseFloat()*Serial*.readBytes()*Serial*.readBytesUntil()*Serial*.readString()*Serial*.readStringUntil()
也可以看看
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
}
void loop() {
//proceed normally
}
/*
Serial
串口通訊實(shí)驗(yàn)
*/
int incomedate = 0;
void setup() {
Serial.begin(9600); //設(shè)置串口波特率9600
Serial.println(78, BIN);// "1001110"
Serial.println(78, OCT);// "116"
Serial.println(78, DEC);// "78"
Serial.println(78, HEX);// "4E"
Serial.println(1.23456, 0);// "1"
Serial.println(1.23456, 2);// "1.23"
Serial.println(1.23456, 4);// "1.2346"
Serial.println('N');// "N"
Serial.println("Hello world.");// "Hello world."
}
void loop() {
if (Serial.available() > 0)//串口接收到數(shù)據(jù)
{
incomedate = Serial.read();//獲取串口接收到的數(shù)據(jù)
if (incomedate == 'H')
{
Serial.println("Good Job!");
}
}
delay(1000);
}
使用的串口Serial其實(shí)是HardwareSerial類(lèi)的實(shí)例化,實(shí)例化過(guò)程中傳入了串口號(hào),實(shí)現(xiàn)過(guò)程如下:


三. Serial1 和 Serial2 的使用
ESP32有三個(gè)串口,串口0,串口1,串口2.
| 名稱(chēng) | 標(biāo)號(hào) | 引腳 | 可用否 |
|---|---|---|---|
| 串口0 | Serial | TX 是 GPIO1, RX 是 GPIO 3 | 可用,很多開(kāi)發(fā)板默認(rèn)用此連接USB/串口換芯片 |
| 串口1 | Serial1 | TX 是 GPIO10, RX 是 GPIO 9 | 不可用,默認(rèn)被Flash占用 |
| 串口2 | Serial2 | TX 是 GPIO17, RX 是 GPIO 16 | 可用 |
arduino-esp32 中定義了 Serial,Serial1,Serial2 三個(gè)對(duì)象, Serial1 是無(wú)法拿來(lái)直接使用, Serial 和 Serial2 可以正常使用,所有除了Serial之外, Serial2 直接使用即可, 引腳接17 ,16
下面, 我們將上面的例子改為Serial2發(fā)送, Serial接受并打印
#include <Arduino.h>
String rev;
void setup() {
Serial.begin(115200);
Serial2.begin(115200);
}
void loop() {
if(Serial2.available())
{
rev=Serial2.readString();
Serial.println("This is ESP32 (serial0)");
Serial.print("rev from serial2: ");
Serial.println(rev);
}
}


