单片机学习小组
直播中

王静

7年用户 684经验值
私信 关注

如何实现基于STC8的红外遥控灯设计?

如何实现基于STC8的红外遥控灯设计?

回帖(1)

李长鹰

2022-2-14 14:01:29
这个东西吧,就是单片机红外解码,然后控制继电器吸合从而控制灯产品,其实挺简单的,
我都在犹豫要不要发出来,想了想还是发上来吧,毕竟还是很实用的(我一直在用,因为床头没开关,这样随手遥控开关灯还是很方便的)。
其实遥控方式多种多样,蓝牙,WIFI,RF433,ZigBee,红外等等。
考虑到实用,以及成本等各种因素,最终选择了红外遥控。
因为不管是蓝牙,WIFI,RF433还是ZigBee,都需要手机遥控或者单独做一个遥控器,比如用蓝牙或者WIFI的时候,着急开灯,还得找到手机,解锁手机,打开APP,连接上设备,开灯。。。
太繁琐了,RF433和ZigBee呢则需要专门的遥控器,成本高,待机时间也不一定长。
红外则简单多了,这种遥控器简单又实惠,学单片机的几乎人人都有,对于开关灯这种只需要几个信号的设计来说是最好不过的了
同样接收电路也是相当的简单,一个接收头就搞定了。

选定了方案,接下来就是单片机了,这个设计太简单了,性能方面是没要求的,直接考虑最便宜又小巧的芯片。


说到价格和体积小巧,首先想到的就是STC8,STM8S003F3还有它的新唐替代品N76E003。


合计了一下还是选择STC8F2K08S2了,毕竟51太熟悉了,工程也简单。


然后就是代码,红外解析,串口打印,确保解码正确。。。


/********************************************************************************
*  描述:                                                                       *
*         遥控器接p3.2                                             *
                                                                    *
*******************************************************************************/
#include
#include
#define PD              0x02                    //PCON.1
***it IRIN = P3 ^ 2;       //红外接收器数据线
//***it RELAY= P1^4;         //继电器驱动线
//***it BEEP = P1^5;         //蜂鸣器驱动线
***it lr = P1 ^ 1;       //红外接收器数据线
***it lr1 = P1 ^ 2;       //红外接收器数据线
extern char flag;
void IRdelay(char x);  //x*0.14MS
//void beep();

unsigned char  IRCOM[7];
//extern unsigned char Y0;
//extern  char busy;
/*******************************************************************/
void IRInit()
{
    IT0 = 1;                                    //使能INT1下降沿中断
    EX0 = 1;                                    //使能INT1中断
    //    IE |= 0x81;                 //允许总中断中断,使能 INT0 外部中断
    //    TCON |= 0x01;               //触发方式为脉冲负边沿触发

    IRIN = 1;                  //I/O口初始化
    //    RELAY=1;
}

/**********************************************************/
void IR_IN(void) interrupt 0
{
    unsigned char j, k, N = 0;
    EX0 = 0;
    IRdelay(15);
    if (IRIN == 1)
    {
        EX0 = 1;
        return;
    }
    //确认IR信号出现
    while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
    {
        IRdelay(1);
    }

    for (j = 0; j < 4; j++)   //收集四组数据
    {
        for (k = 0; k < 8; k++)  //每组数据有8位
        {
            while (IRIN)            //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
            {
                IRdelay(1);
            }
            while (!IRIN)          //等 IR 变为高电平
            {
                IRdelay(1);
            }
            while (IRIN)           //计算IR高电平时长
            {
                IRdelay(1);
                N++;
                if (N >= 30)
                {
                    EX0 = 1;
                    return;
                }                  //0.14ms计数过长自动离开。
            }                        //高电平计数完毕
            IRCOM[j] = IRCOM[j] >> 1;                //数据最高位补“0”
            if (N >= 8)
            {
                IRCOM[j] = IRCOM[j] | 0x80;   //数据最高位补“1”
            }
            N = 0;
        }
    }

    if (IRCOM[2] != ~IRCOM[3])
    {
        EX0 = 1;
        return;
    }

    IRCOM[5] = IRCOM[2] & 0x0F;   //取键码的低四位
    IRCOM[6] = IRCOM[2] >> 4;     //右移4次,高四位变为低四位

    if(IRCOM[5] > 9)
    {
        IRCOM[5] = IRCOM[5] + 0x37;
    }
    else
        IRCOM[5] = IRCOM[5] + 0x30;

    if(IRCOM[6] > 9)
    {
        IRCOM[6] = IRCOM[6] + 0x37;
    }
    else
        IRCOM[6] = IRCOM[6] + 0x30;

    /*
    ;================================
    ;******  红外遥控器键值表  ******
    ;  4c     0e      4d      0d
    ;  0f     4f      4e      0c
    ;  0b     4b      4a      08
    ;  48     12      16      4C
    ;  40     48      04      00
    ;  02     05      54      4D
    ;  0A     1E      0E      1A
    ;  1C     14      0F      0C
             0x45                0x46                0x47
             0x44                0x40                0x43
             0x07                0x15                0x09
             0x16                0x19                0x0d
             0x0c                0x18                0x5e
             0x08                0x1c                0x5a
             0x42                0x52                0x4a
    ;================================  */
    //SBUF=IRCOM[2];
    switch(IRCOM[2])
    {
    case 0x45:
    //           case 0x46:
    //           case 0x47: lr=1;lr1=1;flag=1; break;

    case 0x44:
    case 0x07: //lr=1;lr1=1;flag=1; break;
    case 0x16:
        if(flag == 1)
        {
            lr = 0;
            lr1 = 0;
            flag = 0;
        }
        else
        {
            lr = 1;
            lr1 = 1;
            flag = 1;
        }
        break;
    default:
        lr = 0;
        lr1 = 0;
        flag = 0;

    }
    EX0 = 1;
    _nop_();
    _nop_();
    //    PCON = IDL;                                 //MCU进入IDLE模式
    PCON = PD;                                  //MCU进入掉电模式
    _nop_();
    _nop_();
}


/**********************************************************/
void IRdelay(unsigned char x)    //x*0.14MS
{
    unsigned char i;
    while(x--)
    {
        for (i = 0; i < 100; i++) {}
    }
}


然后就是去掉串口程序(不去也没事儿,考虑到没啥用处了,本着低功耗原则就去掉了)加上继电器,指示灯(继电器吸合时,指示灯熄灭,继电器断开时,指示灯点亮),进行吸合判断,进入低功耗。。。


/********************************************************************************
*  描述:                                                                       *
*         遥控器接p3.2                                             *
*         LED接p1.1  继电器接p1.2                                             *
*                                                                              *
*******************************************************************************/
#include
#include
#define  NOP() _nop_()  /* 定义空指令 */

sfr     VOCTRL      =   0xbb;
#define IDL             0x01                    //PCON.0
#define PD              0x02                    //PCON.1

//测试工作频率为6MHz

sfr     T2L         =   0xd7;
sfr     T2H         =   0xd6;
sfr     AUXR        =   0x8e;
sfr     P1M0        =   0x92;
sfr     P1M1        =   0x91;
***it lr = P1 ^ 1;       //红外接收器数据线
***it lr1 = P1 ^ 2;       //红外接收器数据线
***it key = P3 ^ 3;       //红外接收器数据线

char flag = 0;


extern void IRdelay(unsigned char x);      //函数声名
extern void IRInit();    //extern 是引用IR.C中的函数



void IR_IN1(void) interrupt 2
{
    IRdelay(10);
    if(key == 0)
    {
        if(flag)
        {
            lr = 0;
            lr1 = 0;
            flag = 0;
        }
        else
        {
            lr = 1;
            lr1 = 1;
            flag = 1;
        }
    }
    while(key == 0);
}

main()
{
    lr = 0;
    lr1 = 0;
    VOCTRL = 0x00;                              //掉电模式时使用内部SCC模块,功耗约1.5uA
    //  VOCTRL = 0x80;                              //掉电模式时使用外部SCC模块,功耗约0.15u
    IRInit();
    P1M0 = 0xff;                                //设置P1.0~P1.7为推挽输出模式
    P1M1 = 0x00;
    IT1 = 1;                                    //使能INT1下降沿中断
    EX1 = 1;                                    //使能INT1中断
    key = 1;
    EA = 1;
    lr = 0;
    lr1 = 0;
    while(1)
    {

        _nop_();
        _nop_();
        //    PCON = IDL;                                 //MCU进入IDLE模式
        PCON = PD;                                  //MCU进入掉电模式
        _nop_();
        _nop_();

    }


}



就这么简单,完事儿啦,接着进行画PCB,集成化,小型化


因为涉及到220V家庭用电,所以还得考虑安全性,于是使用了集成封装的220转5V电源模块,继电器使用的是10A 250VAC   SRD-05VDC




焊接好实物图如下

测试功能没问题,由于程序功能简单,使用STC8的内部IRC晶振频率6MHz,如果使用其他频率,修改红外时序IRdelay()函数里的延时即可。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分