51单片机基础-继电器实验

第二十一章 继电器实验

1. 导入

继电器(Relay)是用小电流控制大电流的电磁开关,常用于电机启停、灯具、阀门等电气隔离控制。其线圈由单片机通过驱动电路(晶体管或驱动芯片)吸合释放,触点侧可开断高电压/大电流负载(与单片机完全隔离)。

本章目标:

  • 理解继电器线圈与触点工作原理(NO/NC/COM)。
  • 学会NPN三极管+续流二极管驱动继电器。
  • 使用ULN2003或成品继电器模块(低/高电平触发)。
  • 实现按键控制、定时控制、互锁控制等功能。
  • 掌握触点抗干扰与安全注意事项。

2. 硬件设计

2.1 继电器基础

  • 线圈:通电产生磁力吸合铁芯,断电释放。线圈是感性负载,关断会产生高反向电压。
  • 触点:常开(NO)、常闭(NC)、公共端(COM)。
    • 断电时:COM--NC导通,COM--NO断开;
    • 吸合时:COM--NO导通,COM--NC断开。

典型器件:SRD-05VDC-SL-C(5V线圈,吸合电流≈70--90mA)。

2.2 NPN驱动+续流二极管(推荐基础)

  • 接线(以S8050/2N2222为例,5V系统):
    • 单片机引脚 P1.0 → 基极(串 1k--2.2k 电阻)
    • 发射极 → GND
    • 集电极 → 线圈一端;线圈另一端 → +5V
    • 续流二极管(1N4148/1N4007)并联在线圈两端,二极管正接线圈GND侧,反向接+5V("反向并联",钳位反电动势)
    • 可选:基极→地并10k电阻,防止上电悬空误吸合
  • 基极电阻估算:
    • 线圈电流约80mA,取饱和放大倍数≈10 → 需要Ib≈8mA。8051口源/灌电流有限(建议≤10mA)。
    • 以安全为先,选R≈(5V--0.7V)/4--8mA → 540--1075Ω。实际多用1k--2.2k配合小功率继电器即可吸合;若边缘不足,用驱动芯片。

2.3 ULN2003阵列驱动(更稳妥)

  • ULN2003内置达林顿管与续流二极管,适合多路继电器。
  • 接线:MCU→IN1...IN7,OUT1...OUT7→线圈一端,线圈另一端→+5V,COM脚接+5V(用于二极管回路),GND共地。

2.4 成品继电器模块(低/高电平触发)

  • 引脚:VCC、GND、IN(有的还有JD-VCC跳帽供电隔离)
  • 低电平触发:IN=0继电器吸合(模块上通常标"LOW")
  • 高电平触发:IN=1吸合
  • 注意:低触发模块输入端多带光耦+下拉,逻辑与裸继电器不同。

2.5 触点侧连接与安全

  • 只要控制低压DC负载即可;涉及市电AC严禁新手直接接触,必须采取安规间隙、绝缘、保险丝、浪涌吸收(MOV/RC snubber)等措施,并由专业人士操作。
  • 触点并联RC吸收(如 100nF X2 电容 + 100Ω 电阻串联)可减少火花,延长寿命(交流负载)。
  • DC电感性负载可在负载并并联续流二极管(仅限DC)。

3. 软件设计与完整代码

下面代码给出三种常见接法的控制方式:

  • 裸继电器+NPN(高电平吸合)
  • ULN2003(高电平吸合)
  • 低电平触发模块(低电平吸合,逻辑取反)

选择其一即可,其他注释掉。

c 复制代码
#include <reg52.h>

/* 任选一种驱动方式,修改以下宏 */
// #define RELAY_HIGH_ACTIVE        // NPN或ULN2003,高电平吸合
#define RELAY_LOW_ACTIVE         // 低电平触发模块,低电平吸合

/* 引脚定义 */
sbit RELAY = P1^0;   // 继电器控制信号
sbit KEY1  = P3^0;   // 按键:手动切换
sbit KEY2  = P3^1;   // 按键:定时1s脉冲
sbit LED   = P1^7;   // 指示灯(可选)

/* 简易延时 */
void delay_ms(unsigned int ms){
    unsigned int i,j;
    for(i=0;i<ms;i++)
        for(j=0;j<125;j++);
}

/* 继电器控制抽象 */
static void relay_on(void){
#ifdef RELAY_HIGH_ACTIVE
    RELAY = 1;
#endif
#ifdef RELAY_LOW_ACTIVE
    RELAY = 0;
#endif
}
static void relay_off(void){
#ifdef RELAY_HIGH_ACTIVE
    RELAY = 0;
#endif
#ifdef RELAY_LOW_ACTIVE
    RELAY = 1;
#endif
}
static bit relay_get(){   // 仅用于软件记录(若接法为开漏或模块,读回未必可信)
#ifdef RELAY_HIGH_ACTIVE
    return (RELAY ? 1 : 0);
#else
    return (RELAY ? 0 : 1);
#endif
}

/* 按键消抖检测:返回1=按下事件 */
static bit key_pressed(sbit key){
    if(key == 0){
        delay_ms(10);
        if(key == 0){
            while(key == 0);  // 等待释放
            return 1;
        }
    }
    return 0;
}

void main(){
    /* 上电默认继电器断开,避免冲击 */
    relay_off();
    LED = 1;   // 高电平灭(按板子定义调整)

    /* 上电延时,等待电源稳定 */
    delay_ms(500);

    while(1){
        /* K1:切换继电器状态(自锁开关) */
        if(key_pressed(KEY1)){
            if(relay_get()){
                relay_off();
            }else{
                relay_on();
            }
        }

        /* K2:输出1秒脉冲(点动) */
        if(key_pressed(KEY2)){
            relay_on();
            LED = 0;
            delay_ms(1000);
            relay_off();
            LED = 1;
        }

        /* 指示灯反映当前状态 */
        if(relay_get()) LED = 0; else LED = 1;
    }
}

要点:

  • 根据硬件选择 RELAY_HIGH_ACTIVERELAY_LOW_ACTIVE 其中一个。
  • 上电默认关闭,避免误吸合。
  • 按键采用消抖与"等待松手"。

4. 扩展示例

4.1 定时器中断做非阻塞定时(单次脉冲)

避免delay_ms阻塞主循环,用T0每1ms节拍做状态机:

c 复制代码
#include <reg52.h>

sbit RELAY = P1^0;
volatile unsigned int tmr_ms = 0;
volatile bit pulse_busy = 0;

void t0_init_1ms(){
    TMOD = (TMOD & 0xF0) | 0x01;
    // 11.0592MHz -> 1ms: TH0/TL0 = 0xFC66
    TH0 = 0xFC; TL0 = 0x66;
    ET0 = 1; EA = 1; TR0 = 1;
}

void t0_isr(void) interrupt 1{
    TH0 = 0xFC; TL0 = 0x66;
    if(pulse_busy && tmr_ms) tmr_ms--;
    if(pulse_busy && tmr_ms==0){
        // 结束脉冲
#ifdef RELAY_LOW_ACTIVE
        RELAY = 1;
#else
        RELAY = 0;
#endif
        pulse_busy = 0;
    }
}

void relay_pulse_ms(unsigned int ms){
    if(pulse_busy) return;       // 正在输出,丢弃请求或排队
    pulse_busy = 1;
    tmr_ms = ms;
#ifdef RELAY_LOW_ACTIVE
    RELAY = 0;
#else
    RELAY = 1;
#endif
}

void main(){
#ifdef RELAY_LOW_ACTIVE
    RELAY = 1;
#else
    RELAY = 0;
#endif
    t0_init_1ms();

    while(1){
        // 每2秒输出一次500ms脉冲(举例)
        static unsigned int tick=0;
        if(!pulse_busy){
            relay_pulse_ms(500);
        }
        // 粗糙的2秒,演示用:此处可用另一个计数器
        // ...省略其他任务
    }
}

4.2 双继电器互锁(电机正反转保护)

  • 电机正转继电器K1、反转继电器K2不能同时吸合,中间要有死区时间(如50--100ms)。
  • 伪代码要点:
    • 若要从正转切到反转:先断K1→延时→吸合K2;反向亦然。
    • 检测当前状态,避免抖动误触发。
  • 硬件上最好用互锁接线(交叉接线或互锁触点)实现硬件级防误。

5. 测试步骤与验证

  • 空载测试:不接触点负载,仅听吸合"嗒"声和测量线圈电流。
  • 低压负载测试:用5--12V小灯泡/直流风扇验证触点工作。
  • 功率负载/市电:仅在安规、隔离、防护完善的前提下进行,建议使用带光耦与电源隔离的成品模块并由专业人员实施。

6. 常见问题与解决

  • 继电器不吸合:
    • 线圈供电不足/压降大(USB取电不稳);驱动晶体管接反;续流二极管极性错误。
  • 上电误吸合:
    • 输入悬空,增加下拉/上拉;上电默认置"关闭"并延时;模块为低触发导致上电低脉冲,需置引脚上拉为稳定态。
  • MCU复位或干扰:
    • 触点侧浪涌干扰电源/地;在触点侧加RC吸收、MOV,数字与功率地分区;给MCU加去耦与复位可靠性设计。
  • 触点粘连/寿命短:
    • 负载电流/种类超过额定;电感负载无吸收网络;选择更大容量继电器或固态继电器(SSR)。

7. 小结

  • 硬件:用NPN或ULN2003驱动继电器,务必并联续流二极管;模块则按"低/高电平触发"正确接线。
  • 软件:提供按键消抖、自锁/点动、定时器非阻塞脉冲、互锁示例。
  • 安全:触点侧高压/大功率必须遵循安规,必要时使用隔离模块、浪涌抑制与保险丝。

相关推荐
美好的事情总会发生11 小时前
FPGA的LVDS接口电压
嵌入式硬件·fpga开发·硬件工程·智能硬件
kaka❷❷11 小时前
STM32中 ESP8266 MQTT ModBus RS482 介绍
stm32·嵌入式硬件·智能路由器
Brianna Home12 小时前
大模型如何变身金融风控专家
人工智能·深度学习·机器学习·自然语言处理·stable diffusion·1024程序员节
hazy1k13 小时前
51单片机基础-TFT LCD 显示(ILI9341,SPI 4线)
c语言·stm32·单片机·嵌入式硬件·51单片机
brave and determined13 小时前
硬件-内存学习DAY14——3DXPoint:存储技术的革命与终结
嵌入式硬件·intel·3d xpoint·内存创新·内存设计·内存应用·内存新技术
奔跑吧邓邓子13 小时前
【C语言实战(63)】从0到1:51单片机GPIO控制实战秘籍
c语言·51单片机·开发实战·gpio控制实战
D.....l15 小时前
STM32学习(MCU控制)(RS485 and ModBus)
stm32·单片机·学习
Jie_jiejiayou16 小时前
按键防抖 — 工业级标准实现总结(STM32)
c语言·stm32·按键消抖
物联网牛七七17 小时前
单片机中的中断
单片机·嵌入式硬件