
目录一、 ULN2003A 究竟是何方神圣1. 达林顿阵列IO 口的“放大器”2. 核心优势为何选择 ULN2003A3. ULN2003A 引脚解析二、 实战案例STM32 / ESP32 ULN2003A案例一驱动多路继电器如控制家电案例二驱动步进电机如小型 XYZ 平台三、 高效复用与设计考量1. IO 口电平兼容性2. 电源管理3. 驱动负载的电流限制4. 信号隔离与保护四、 总结ULN2003A 是 IoT 开发的“瑞士军刀”如果您喜欢此文章请收藏、点赞、评论谢谢祝您快乐每一天。在物联网 (IoT) 硬件开发中尤其是在使用 STM32 或 ESP32 这类具有一定 IO 口但常常捉襟见肘的微控制器时我们经常会遇到一个尴尬的局面“IO 口不够用了”这时候一个简单、便宜且高效的解决方案就是——ULN2003A 达林顿阵列驱动芯片。它能够将微控制器的 IO 口数量“按需放大”让原本受限的 IO 口驱动更多的外部设备。本指南将结合 STM32 和 ESP32 的实战案例深入讲解 ULN2003A 的工作原理、高效复用技巧以及在 IoT 硬件开发中的应用。一、 ULN2003A 究竟是何方神圣1. 达林顿阵列IO 口的“放大器”工作原理ULN2003A 内部集成了 7 路独立的达林顿晶体管。每一路达林顿晶体管都能将来自微控制器 IO 口的一个低电流信号放大成一个足以驱动高功率设备的高电流输出。“NPN”类型ULN2003A 的输出是 NPN 类型的意味着当输入信号为高电平时输出端导通LED 或其他负载就能工作。内置续流二极管每路输出都内置了续流二极管用于保护芯片免受感性负载如继电器、步进电机在断电时产生的反向电动势损坏。2. 核心优势为何选择 ULN2003AIO 口复用用一个微控制器的 IO 口可以控制 7 个独立的设备。电流放大驱动能力远超微控制器的 IO 口可以驱动继电器、步进电机、LED 阵列等。保护机制内置续流二极管简化了外围电路设计。成本低廉价格非常便宜是 DIY 和原型开发的首选。易于使用引脚定义清晰直接连接即可。3. ULN2003A 引脚解析一个标准的 ULN2003A 芯片DIP-16 封装Pin 1-7: 输入端 (IN1-IN7)。连接到微控制器的 GPIO 口。Pin 8: GND (地)。Pin 9-15: 输出端 (OUT1-OUT7)。连接到外部负载的一端。Pin 16: VCC (电源)。通常连接到外部负载所需的工作电压如 5V, 12V。二、 实战案例STM32 / ESP32 ULN2003A案例一驱动多路继电器如控制家电需求用 STM32/ESP32 的有限 IO 口控制 7 路 5V 继电器实现对不同家电的开关控制。硬件连接ULN2003APin 8 (GND) - STM32/ESP32 的 GND。Pin 16 (VCC) - 外部 5V 电源这个 5V 电源需要能提供所有继电器工作时所需的总电流通常比 STM32/ESP32 的 3.3V/5V IO 供电更强劲。Pin 1-7 (IN1-IN7) - STM32/ESP32 的 7 个 GPIO 口注意电平兼容STM32/ESP32 是 3.3V IOULN2003A 的输入设计在 3.3V 时也能正常驱动。Pin 9-15 (OUT1-OUT7) - 7 个 5V 继电器模块的信号输入端。继电器模块信号端 - ULN2003A 的 OUT1-OUT7。VCC - 外部 5V 电源 (与 ULN2003A 的 VCC 连接)。GND - 外部 5V 电源的 GND。外部负载家电接在继电器模块的常开 (NO) 或常闭 (NC) 端根据需要选择。软件实现 (以 STM32 HAL 库为例)// main.h (或你的头文件)#define RELAY1_PIN GPIO_PIN_0#define RELAY2_PIN GPIO_PIN_1#define RELAY3_PIN GPIO_PIN_2// ... Relay 7 ...#define RELAY_PORT GPIOA // 假设使用 Port A// 控制函数void HAL_GPIO_SetRelay(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint8_t state);// main.cvoid SystemClock_Config(void); // 初始化时钟static void MX_GPIO_Init(void); // 初始化 GPIO// ...void HAL_GPIO_SetRelay(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint8_t state) {if (state 1) { // 开启继电器 (ULN2003A 输入为高电平)HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET);} else { // 关闭继电器 (ULN2003A 输入为低电平)HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_RESET);}}int main(void) {HAL_Init();SystemClock_Config();MX_GPIO_Init();// 示例开启第一个继电器关闭第二个HAL_GPIO_SetRelay(RELAY_PORT, RELAY1_PIN, 1); // 开启 1 号继电器HAL_GPIO_SetRelay(RELAY_PORT, RELAY2_PIN, 0); // 关闭 2 号继电器while (1) {// ... 其他逻辑 ...}}static void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct {0};__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能 GPIOA 时钟// 配置继电器控制引脚为输出模式GPIO_InitStruct.Pin RELAY1_PIN | RELAY2_PIN | RELAY3_PIN | ...; // 添加所有继电器引脚GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; // 推挽输出GPIO_InitStruct.Pull GPIO_NOPULL; // 无上下拉GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; // 低速即可HAL_GPIO_Init(RELAY_PORT, GPIO_InitStruct);// 初始状态关闭所有继电器HAL_GPIO_WritePin(RELAY_PORT, RELAY1_PIN | RELAY2_PIN | RELAY3_PIN | ..., GPIO_PIN_RESET);}ESP32 代码 (Arduino 框架)#define RELAY1_PIN 5 // GPIO 5#define RELAY2_PIN 4 // GPIO 4// ... Relay 7 ...void setup() {Serial.begin(115200);pinMode(RELAY1_PIN, OUTPUT);pinMode(RELAY2_PIN, OUTPUT);// ... other relays ...// 初始状态关闭所有继电器digitalWrite(RELAY1_PIN, LOW);digitalWrite(RELAY2_PIN, LOW);// ...}void loop() {// 示例开启第一个继电器关闭第二个digitalWrite(RELAY1_PIN, HIGH); // 开启 1 号继电器digitalWrite(RELAY2_PIN, LOW); // 关闭 2 号继电器delay(5000); // 延时 5 秒// ...}案例二驱动步进电机如小型 XYZ 平台需求用 ESP32 的 IO 口驱动一个 ULN2003A 来控制一个 5V 步进电机通常是 4 相。硬件连接ULN2003APin 8 (GND) - ESP32 的 GND。Pin 16 (VCC) - 外部 5V/12V 电源取决于你的步进电机电压。Pin 1-4 (IN1-IN4) - ESP32 的 4 个 GPIO 口用于发送步进脉冲。Pin 9-12 (OUT1-OUT4) - 步进电机模块的 4 个相线 (A, B, C, D)。步进电机模块信号端 (IN1-IN4) - ULN2003A 的 OUT1-OUT4。VCC - 外部电源。GND - 外部电源 GND。软件实现 (ESP32 Arduino)通常步进电机需要特定的驱动序列如全步、半步、微步。使用 Arduino 的Stepper库可以简化很多。#include Stepper.h// ULN2003A 连接到 ESP32 的 IO 口#define IN1 2 // GPIO 2#define IN2 4 // GPIO 4#define IN3 16 // GPIO 16#define IN4 17 // GPIO 17// 步进电机的步数 (例如一个标准步进电机每圈 200 步)const int stepsPerRevolution 200;// 创建 Stepper 对象// 参数stepsPerRevolution, out1, out2, out3, out4Stepper myStepper(stepsPerRevolution, IN1, IN2, IN3, IN4);void setup() {Serial.begin(115200);// 设置步进电机的速度 (RPM - Revolutions Per Minute)myStepper.setSpeed(60); // 60 RPM即 1 圈/秒}void loop() {Serial.println(Moving forward 1 revolution);// 顺时针转动 200 步 (1 圈)myStepper.step(stepsPerRevolution);delay(1000);Serial.println(Moving backward 1/2 revolution);// 逆时针转动 100 步 (半圈)myStepper.step(-stepsPerRevolution / 2);delay(1000);}三、 高效复用与设计考量1. IO 口电平兼容性STM32/ESP32 IO (3.3V) vs ULN2003A 输入ULN2003A 的输入设计上3.3V 的高电平通常足以使其导通驱动低电平的设备。如果需要严格的 5V 信号可以使用电平转换器但对于大多数 IO 驱动场景3.3V 输入是可行的。ULN2003A 输出 vs 负载电压ULN2003A 的 VCC (Pin 16) 决定了其输出端的最高电压。你可以给 Pin 16 提供 5V、9V、12V 等来驱动对应电压的负载继电器、电机。2. 电源管理独立的负载电源ULN2003A 的 VCC (Pin 16) 和 GND (Pin 8) 需要连接到外部高功率电源这个电源必须能提供所有被驱动设备所有继电器、所有电机的总电流。不要试图用 STM32/ESP32 的 3.3V/5V 供电引脚直接给 ULN2003A 的 VCC 供电除非你只驱动一个低功耗设备且确认电流足够。共地连接ULN2003A 的 GND、外部电源的 GND、微控制器的 GND 必须互相连接共地否则信号无法正常传输。3. 驱动负载的电流限制ULN2003A 单路输出最大电流通常为 500mA峰值可达 600mA但连续工作建议不超过 300-400mA。总电流限制ULN2003A 内部所有输出同时导通时总电流也有限制具体请查阅数据手册。实际应用继电器大多数 5V/12V 继电器线圈电流在 50-100mA 左右ULN2003A 完全可以驱动。步进电机小型步进电机的单相电流通常在 100-300mAULN2003A 可以驱动但需要注意多相同时工作时的总电流。对于大型步进电机可能需要更专业的电机驱动器如 A4988, DRV8825。LED 阵列LED 的电流需求相对较低20mAULN2003A 可以驱动。4. 信号隔离与保护内置续流二极管对感性负载继电器、电机的保护已经到位无需额外添加。高压/大电流负载对于超过 ULN2003A 驱动能力范围的负载ULN2003A 可以作为前级驱动用于控制一个更大的继电器或功率 MOSFET间接驱动高功率设备。四、 总结ULN2003A 是 IoT 开发的“瑞士军刀”IO 口不够用ULN2003A 帮你把 1 个 IO 口变成 7 个。驱动能力不足达林顿阵列轻松放大电流。担心反向电动势内置续流二极管已为你考虑周全。预算紧张ULN2003A 极其便宜性价比超高。在 STM32 和 ESP32 等微控制器项目中ULN2003A 是一个**“小身材大能量”**的解决方案能够极大地拓展硬件设计的可能性让你在资源受限的情况下也能实现丰富的 IoT 功能。掌握它的使用方法将是每一个嵌入式开发者必备的技能之一。如果您喜欢此文章请收藏、点赞、评论谢谢祝您快乐每一天。