基于STC8的红外遥控灯
这个东西吧,就是单片机红外解码,然后控制继电器吸合从而控制灯产品,其实挺简单的,
我都在犹豫要不要发出来,想了想还是发上来吧,毕竟还是很实用的(我一直在用,因为床头没开关,这样随手遥控开关灯还是很方便的)。
其实遥控方式多种多样,蓝牙,WIFI,RF433,ZigBee,红外等等。
考虑到实用,以及成本等各种因素,最终选择了红外遥控。
因为不管是蓝牙,WIFI,RF433还是ZigBee,都需要手机遥控或者单独做一个遥控器,比如用蓝牙或者WIFI的时候,着急开灯,还得找到手机,解锁手机,打开APP,连接上设备,开灯。。。
太繁琐了,RF433和ZigBee呢则需要专门的遥控器,成本高,待机时间也不一定长。
红外则简单多了,这种遥控器简单又实惠,学单片机的几乎人人都有,对于开关灯这种只需要几个信号的设计来说是最好不过的了
同样接收电路也是相当的简单,一个接收头就搞定了。
选定了方案,接下来就是单片机了,这个设计太简单了,性能方面是没要求的,直接考虑最便宜又小巧的芯片。
说到价格和体积小巧,首先想到的就是STC8,STM8S003F3还有它的新唐替代品N76E003。
合计了一下还是选择STC8F2K08S2了,毕竟51太熟悉了,工程也简单。
然后就是代码,红外解析,串口打印,确保解码正确。。。
/********************************************************************************
* 描述: *
* 遥控器接p3.2 *
*
*******************************************************************************/
#include <reg51.h>
#include <intrins.h>
#define PD 0x02 //PCON.1
sbit IRIN = P3 ^ 2; //红外接收器数据线
//sbit RELAY= P1^4; //继电器驱动线
//sbit BEEP = P1^5; //蜂鸣器驱动线
sbit lr = P1 ^ 1; //红外接收器数据线
sbit 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 <reg51.h>
#include <intrins.h>
#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;
sbit lr = P1 ^ 1; //红外接收器数据线
sbit lr1 = P1 ^ 2; //红外接收器数据线
sbit 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()函数里的延时即可。
下载地址https://download.csdn.net/download/qq_22848695/13107865。
最后提醒:由于涉及到220V家庭用电,请一定一定要小心,万不可大意。
本文地址:https://blog.csdn.net/qq_22848695/article/details/109643091