Quick reference card - 8位单片机开发板Arduino Duemilanove/UNO

297 阅读10分钟

[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)
SRAM2KB
EEPROM1KB
时钟频率16 MHz
UART1 (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);          // 禁用从机

🐞 调试技巧

  1. LED状态指示

    #define LED_BUILTIN 13        // 板载LED
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // 状态翻转
    
  2. 内存监测

    extern int __heap_start, *__brkval;
    int freeRam() {               // 获取剩余RAM
      int v;
      return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval);
    }
    
  3. 复位操作

    void(* resetFunc) (void) = 0; // 声明复位函数
    resetFunc();                  // 执行软复位
    

🔌 引脚复用功能

引脚复用功能
0 (RX)串口接收
1 (TX)串口发送
2, 3外部中断
3, 11PWM (Timer2)
9, 10PWM (Timer1)
5, 6PWM (Timer0)
10SPI片选 (SS)
11SPI数据输出 (MOSI)
12SPI数据输入 (MISO)
13SPI时钟 (SCK)
A4I²C数据线 (SDA)
A5I²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

image

用TXS0108E 八位双向电压转换小板子,让arduino支持3.3v和1.8v输入输出接口

IMG_20241205_214937.jpg

IMG_20241205_215014.jpg

IO口可以用firmata工具操作:

gitee.com/nsynet/firm…

图片.png

arduino 代码快速参考

www.arduino.cc/reference/e…

arduino 的library参考

www.arduino.cc/reference/e…

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个数字,方便表示温度和湿度,具体如下:

图片.png

在树莓派中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):

图片.png

使用proteus仿真arduino

//新建项目时,如果选择"From Development Board",则后面只能用类似arduino IDE的代码编程;如果选择"New Project",则后面可以选择"Create Firmware Project"(即代码编程)或者"Create Flowchart Project"(即流程图编程,实际调试的源代码类似在 C:\Users\MateBook Xpro\AppData\Local\Temp\VSM Studio 路径里). //新建工程时如果是流程图方式,可以选择: image,流程图方式可以转成代码方式(Project->Convert to source project),但是不能从代码转化成流程图方式.

流程图编程支持的模块 在代码中路径:

D:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\DATA\VSM Studio\drivers\arduino

也即如下: image

image image image

image image image

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

图片.png

Arduino Pro Mini (DEV-11114)板(8MHz / 3.3V)

注意:8MHz / 3.3V的Arduino Pro Mini 不要使用115200的波特率,会出现不准的情况:

晶振频率安全波特率临界波特率
16MHz≤115200250000+
8MHz≤3840057600+

pin map

图片.png

升级方法

图片.png