[toc]
Quick reference card for Arduino UNO
以下是一份简洁实用的 Arduino Uno 开发快速参考卡(Quick Reference Card),涵盖硬件配置、核心函数、常用库及调试技巧:
🛠️ 硬件配置
| 项目 | 参数 |
|---|---|
| 主控芯片 | ATmega328P (8位 AVR) |
| 工作电压 | 5V |
| 输入电压 | 7-12V (推荐) |
| 数字 I/O 引脚 | 14 (6个支持PWM ~) |
| 模拟输入引脚 | 6 (A0-A5, 10位分辨率) |
| Flash 存储器 | 32KB (0.5KB用于Bootloader) |
| SRAM | 2KB |
| EEPROM | 1KB |
| 时钟频率 | 16 MHz |
| UART | 1 (TX:0, RX:1) |
| SPI | 引脚 (SS:10, MOSI:11, MISO:12, SCK:13) |
| I²C | 引脚 (SDA:A4, SCL:A5) |
⚡ 核心函数
1. 引脚控制
pinMode(pin, INPUT/OUTPUT); // 设置引脚模式
digitalWrite(pin, HIGH/LOW); // 数字输出
int val = digitalRead(pin); // 数字输入
analogWrite(pin, 0-255); // PWM输出 (引脚3,5,6,9,10,11)
int val = analogRead(A0); // 模拟输入 (0-1023)
注意,arduino IDE 中,对于arduino原生开发板的输入是pin号,但是其他ESP8266/ESP32等项目,这里pin指的是GPIO号,不是单板的pin脚.
2. 时间控制
delay(ms); // 毫秒级延时
delayMicroseconds(us); // 微秒级延时
unsigned long t = millis(); // 获取运行时间(ms)
unsigned long t = micros(); // 获取运行时间(us)
3. 串口通信
Serial.begin(9600); // 初始化串口
Serial.print("Hello"); // 发送数据
Serial.println(value); // 发送数据+换行
if(Serial.available()) { // 检测接收数据
char c = Serial.read(); // 读取数据
}
4. 中断控制
attachInterrupt(0, ISR, MODE); // 中断0(引脚2)
attachInterrupt(1, ISR, MODE); // 中断1(引脚3)
// MODE: LOW, CHANGE, RISING, FALLING
detachInterrupt(0); // 禁用中断
📚 常用库速查
1. EEPROM (掉电存储)
#include <EEPROM.h>
EEPROM.write(addr, val); // 写单字节
byte b = EEPROM.read(addr); // 读单字节
EEPROM.put(addr, floatVal); // 写任意类型
EEPROM.get(addr, floatVal); // 读任意类型
2. Servo (舵机控制)
#include <Servo.h>
Servo myservo;
myservo.attach(9); // 绑定引脚
myservo.write(90); // 0-180度
3. Wire (I²C通信)
#include <Wire.h>
Wire.begin(); // 主机模式
Wire.begin(0x55); // 从机模式(地址)
Wire.requestFrom(addr, len); // 请求数据
Wire.write(data); // 发送数据
4. SPI (高速通信)
#include <SPI.h>
SPI.begin(); // 初始化
SPI.transfer(val); // 发送/接收
digitalWrite(SS, LOW); // 启用从机
digitalWrite(SS, HIGH); // 禁用从机
🐞 调试技巧
-
LED状态指示
#define LED_BUILTIN 13 // 板载LED digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // 状态翻转 -
内存监测
extern int __heap_start, *__brkval; int freeRam() { // 获取剩余RAM int v; return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval); } -
复位操作
void(* resetFunc) (void) = 0; // 声明复位函数 resetFunc(); // 执行软复位
🔌 引脚复用功能
| 引脚 | 复用功能 |
|---|---|
| 0 (RX) | 串口接收 |
| 1 (TX) | 串口发送 |
| 2, 3 | 外部中断 |
| 3, 11 | PWM (Timer2) |
| 9, 10 | PWM (Timer1) |
| 5, 6 | PWM (Timer0) |
| 10 | SPI片选 (SS) |
| 11 | SPI数据输出 (MOSI) |
| 12 | SPI数据输入 (MISO) |
| 13 | SPI时钟 (SCK) |
| A4 | I²C数据线 (SDA) |
| A5 | I²C时钟线 (SCL) |
💡 最佳实践提示:
- PWM频率调整:
TCCR0B = TCCR0B & 0b11111000 | 0x01;(62.5kHz)- 降低功耗:
set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_cpu();- 看门狗复位:
wdt_enable(WDTO_4S); while(1);
将此卡片打印为PDF或保存为图片,可随时查阅核心功能!🖨️
完整文档参考:Arduino Uno官方文档
arduino的Duemilanove
pin map

用TXS0108E 八位双向电压转换小板子,让arduino支持3.3v和1.8v输入输出接口
IO口可以用firmata工具操作:
arduino 代码快速参考
arduino 的library参考
arduino 单步调试的方法
来自抖音中up主的分享,以Blink为例:
int debug=1;
#define BP(x) { \
if(debug) { char wtbuf[1000]; delay(1);\
sprintf(wtbuf,"\r\n******断点位于函数 %s()",__FUNCTION__ );\
Serial.print(wtbuf);Serial.print("\r\n=>");sprintf(wtbuf,"第%03d行 ",__LINE__);\
Serial.print(wtbuf);Serial.print(#x);Serial.println(" <==== (已经进入断点,请按回车继续执行)"); \
while(!Serial.available()) delay(1);if(Serial.parseInt()==999) debug=0;Serial.read();}} x
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
BP(digitalWrite(LED_BUILTIN, HIGH);) // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
BP(digitalWrite(LED_BUILTIN, LOW);) // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
arduino使用中断的步骤
在Arduino中使用中断是一种强大的技术,可以让你在特定事件发生时立即执行代码,而不需要不断检查事件是否发生。这对于需要快速响应的场合非常有用,例如检测按钮按下、读取传感器数据等。以下是如何在Arduino中使用中断的基本步骤和示例:
1. 定义中断服务例程(ISR)
在Arduino代码中定义一个函数,该函数将在中断发生时被调用。ISR函数必须是void类型的,并且不能有参数。
void handleInterrupt() {
// 在这里编写中断发生时要执行的代码
// 例如,切换LED的状态
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
2. 设置中断
在setup()函数中使用attachInterrupt()函数来设置中断。你需要指定中断引脚、ISR函数和触发中断的条件。
void setup() {
pinMode(LED_PIN, OUTPUT); // 设置LED引脚为输出
pinMode(INTERRUPT_PIN, INPUT); // 设置中断引脚为输入
// 设置中断
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), handleInterrupt, RISING);
}
- 参数说明:
digitalPinToInterrupt(INTERRUPT_PIN):将数字引脚转换为中断号。INTERRUPT_PIN是你连接到外部事件的引脚。handleInterrupt:ISR函数的名称。RISING:触发中断的条件。可以是以下几种之一:LOW:当引脚为低电平时触发。CHANGE:当引脚电平发生变化时触发。RISING:当引脚从低电平变为高电平时触发。FALLING:当引脚从高电平变为低电平时触发。
3. 主循环
在loop()函数中,你可以继续执行其他任务,而不需要不断检查中断事件。
void loop() {
// 主循环中的代码
// 例如,执行其他任务
}
示例代码
以下是一个完整的示例,展示了如何使用中断来检测按钮按下并切换LED状态:
const int LED_PIN = 13; // LED连接到引脚13
const int INTERRUPT_PIN = 2; // 中断引脚连接到引脚2
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(INTERRUPT_PIN, INPUT_PULLUP); // 使用内部上拉电阻
// 设置中断
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), handleInterrupt, FALLING);
}
void loop() {
// 主循环中的代码
// 例如,执行其他任务
}
void handleInterrupt() {
// 切换LED状态
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
注意事项
- ISR的执行时间:ISR应该尽可能短小,因为长时间的ISR会阻塞其他中断和主程序的执行。
- 全局变量:在ISR中使用全局变量时,需要特别小心,以避免与主程序中的变量冲突。
- 中断数量:不同的Arduino型号支持的中断数量不同,例如,Arduino Uno支持两个外部中断(引脚2和3)。
通过使用中断,你可以使Arduino更有效地响应外部事件,提高程序的响应速度和可靠性。
i2c
i2c扫描参考
https://playground.arduino.cc/Main/I2cScanner/
的代码,串口9600波特率会显示类似如下:
Scanning...
I2C device found at address 0x3F !
done
I2C 1602LCD 的调试
1.使用i2c扫描先确认LCD的地址,比如我从淘宝买的LCD1602 的I2C转接板的地址不是0x27,而是0x3f
2.打开 IDE 的工具–>管理程式库 
搜寻 LiquidCrystal_PCF8574 与下载安装
3.打开示例代码,修改i2c地址从0x27为0x3f后,编译并上传即可:

[i2c]dht 12温湿度传感器
原理:顺序读5个数字,方便表示温度和湿度,具体如下:
在树莓派中i2cdump的值如下,仍然是0d + 03 + 1c + 89 =b5 用于校验.
nisy@raspberrypi:~ $ i2cdump -f -y 1 0x5c
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 0d 03 1c 89 b5 dc XX dc 5c dc dc dc dc b9 ff dc ??????X?\?????.?
10: dc dc ff dc dc dc 8c dc dc dc 76 5c dc dc 5c dc ??.???????v\??\?
20: dc 5c e9 b0 dc b9 ff dc dc dc 5c 76 dc 5c ff dc ?\????.???\v?\.?
30: dc 08 34 XX 07 6b 00 85 81 21 ff ff ff ff ff ff ??4X?k.??!......
40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
70: ff ff ff XX XX ff ff ff ff ff ff ff ff ff ff ff ...XX...........
80: ff ff ff ff ff XX XX ff XX ff ff ff ff ff XX ff .....XX.X.....X.
90: ff ff XX ff ff ff XX ff ff ff XX ff ff ff ff ff ..X...X...X.....
a0: ff ff ff ff ff XX ff ff ff XX ff XX ff ff ff ff .....X...X.X....
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
c0: ff ff ff XX ff ff ff ff ff ff ff ff ff ff XX ff ...X..........X.
d0: ff ff ff XX ff ff ff ff ff XX ff ff XX ff XX ff ...X.....X..X.X.
e0: ff ff ff ff ff ff ff XX ff ff ff ff ff ff ff ff .......X........
f0: 5c ff ff ff ff ff ff ff ff ff XX ff ff ff ff ff \.........X.....
树莓派的参考代码:
import smbus
import time
# I2C bus
bus = smbus.SMBus(1) # 使用I2C bus 1
# DHT12 I2C address
dht12_address = 0x5C # 根据你的模块实际情况可能不同
def read_dht12(bus, address):
# 发送测量命令
bus.write_byte(address, 0x00)
time.sleep(1) # 等待数据准备
# 读取数据
data = bus.read_i2c_block_data(address, 0, 5)
humidity1 = data[0]
humidity2 = data[1]
temperature1 = data[2]
temperature2 = data[3]
# 校验数据
if (data[0] + data[1] +data[2]+data[3]) & 0xFF == data[4]:
return humidity1, humidity2, temperature1 ,temperature2
else:
return None, None
# 读取数据
while True:
hum1, hum2,temp1 ,temp2 = read_dht12(bus, dht12_address)
if hum1 is not None and temp1 is not None and hum2 is not None and temp2 is not None:
print("湿度: %d.%d " % (hum1, hum2), end=' ')
print("温度: %d.%d ℃" % (temp1, temp2))
else:
print("读取失败")
time.sleep(2) # 等待2秒再次读取
执行效果:
nisy@raspberrypi:~ $ python3 ./_dht12_module.py
湿度: 95.0 温度: 35.2 ℃
湿度: 95.0 温度: 33.1 ℃
湿度: 95.0 温度: 32.5 ℃
湿度: 95.0 温度: 32.0 ℃
湿度: 95.0 温度: 31.5 ℃
湿度: 95.0 温度: 31.0 ℃
或者可以使用ch347demo.exe 来直接读寄存器的值,参考如下从0x02地址读,读出来2个字节,分别就是温度的整数和小数部分(DHT 12的7bit地址是0x5c,对应8bit的读地址就是 0x5c<<1 = 0xb8):
使用proteus仿真arduino
//新建项目时,如果选择"From Development Board",则后面只能用类似arduino IDE的代码编程;如果选择"New Project",则后面可以选择"Create Firmware Project"(即代码编程)或者"Create Flowchart Project"(即流程图编程,实际调试的源代码类似在
C:\Users\MateBook Xpro\AppData\Local\Temp\VSM Studio
路径里).
//新建工程时如果是流程图方式,可以选择:
,流程图方式可以转成代码方式(Project->Convert to source project),但是不能从代码转化成流程图方式.
流程图编程支持的模块 在代码中路径:
D:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\DATA\VSM Studio\drivers\arduino
也即如下:



Q:proteus中仿真arduino的程序,怎么在实体arduino上实现? A:点击upload按钮.
Q:arduino 如何使用中断? A:在Arduino中使用中断是一种强大的技术,可以让你在特定事件发生时立即执行代码,而不需要不断检查事件是否发生。这对于需要快速响应的场合非常有用,例如检测按钮按下、读取传感器数据等。以下是如何在Arduino中使用中断的基本步骤和示例:
中断的基本概念
- 中断:是一种机制,允许外部事件(如按钮按下、传感器信号变化)触发Arduino的代码执行。
- 中断服务例程(ISR):当中断发生时,Arduino会暂停当前正在执行的代码,转而执行ISR。ISR执行完毕后,再继续执行原来的代码。
使用中断的步骤
1. 定义中断服务例程(ISR)
在Arduino代码中定义一个函数,该函数将在中断发生时被调用。ISR函数必须是void类型的,并且不能有参数。
void handleInterrupt() {
// 在这里编写中断发生时要执行的代码
// 例如,切换LED的状态
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
2. 设置中断
在setup()函数中使用attachInterrupt()函数来设置中断。你需要指定中断引脚、ISR函数和触发中断的条件。
void setup() {
pinMode(LED_PIN, OUTPUT); // 设置LED引脚为输出
pinMode(INTERRUPT_PIN, INPUT); // 设置中断引脚为输入
// 设置中断
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), handleInterrupt, RISING);
}
- 参数说明:
digitalPinToInterrupt(INTERRUPT_PIN):将数字引脚转换为中断号。INTERRUPT_PIN是你连接到外部事件的引脚。handleInterrupt:ISR函数的名称。RISING:触发中断的条件。可以是以下几种之一:LOW:当引脚为低电平时触发。CHANGE:当引脚电平发生变化时触发。RISING:当引脚从低电平变为高电平时触发。FALLING:当引脚从高电平变为低电平时触发。
3. 主循环
在loop()函数中,你可以继续执行其他任务,而不需要不断检查中断事件。
void loop() {
// 主循环中的代码
// 例如,执行其他任务
}
示例代码
以下是一个完整的示例,展示了如何使用中断来检测按钮按下并切换LED状态:
const int LED_PIN = 13; // LED连接到引脚13
const int INTERRUPT_PIN = 2; // 中断引脚连接到引脚2
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(INTERRUPT_PIN, INPUT_PULLUP); // 使用内部上拉电阻
// 设置中断
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), handleInterrupt, FALLING);
}
void loop() {
// 主循环中的代码
// 例如,执行其他任务
}
void handleInterrupt() {
// 切换LED状态
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
注意事项
- ISR的执行时间:ISR应该尽可能短小,因为长时间的ISR会阻塞其他中断和主程序的执行。
- 全局变量:在ISR中使用全局变量时,需要特别小心,以避免与主程序中的变量冲突。
- 中断数量:不同的Arduino型号支持的中断数量不同,例如,Arduino Uno支持两个外部中断(引脚2和3)。
通过使用中断,你可以使Arduino更有效地响应外部事件,提高程序的响应速度和可靠性。
arduino nano板
pin map
Arduino Pro Mini (DEV-11114)板(8MHz / 3.3V)
注意:8MHz / 3.3V的Arduino Pro Mini 不要使用115200的波特率,会出现不准的情况:
| 晶振频率 | 安全波特率 | 临界波特率 |
|---|---|---|
| 16MHz | ≤115200 | 250000+ |
| 8MHz | ≤38400 | 57600+ |