赞
踩
最近有小伙伴私信我,他是学电子信息的,老师让他们做一个关于红外遥控控制智能家居的小项目,没有设计思路,也不知道用啥芯片,自己只会写一些单片机代码,和使用AD-PCB设计软件。
我记得很久以前做过一个类似的项目大概是16年,于是找了大半个下午,终于找出来,现在把它分享出来,供大家参考一下,希望小伙伴们能从中学到东西。
PCB原理图如下,我记得当时还是用protel画的
电路原理图如下:画图软件同上
实验参考C语言代码
#include “stc12c2052ad.h”
#include “wifi_IR.h”
#include <intrins.h>
//#define ENABLE_IAP 0x83 //if SYSCLK<20MHz
#define FOSC 11059200UL//12M晶振
#define CMD_IDLE 0 //Stand-By
#define CMD_READ 1 //Byte-Read
#define CMD_PROGRAM 2 //Byte-Program
#define CMD_ERASE 3 //Sector-Erase
uint addr;//EPPROM地址
//uchar cou;
bit study_send_switch,LED_state;
void SaveLevelTimeLength(uint addr);//存储电平时长
void IrSend();//红外发射
void Read_Key();
void IrStudy();
void IapIdle();
void byte_write(uint addr, uchar dat);
void SectorErase(uint sector_addr);
uchar byte_read(uint addr);
void TIMER0_RELOAD(uint addr)//装入定时器
{
TR0=0;
TF0=0;
TH0=byte_read(addr);//从指定的地址读出电平的长度
TL0=byte_read(addr+1);//从指定的地址读出电平的长度
TR0=1;//启动定时器
}
//---------------------------------------------------
void IrSend()//红外发射
{
uchar level_cnt; //电平个数
level_cnt=byte_read(addr);//读出电平个数
addr++;//地址后移一位
while (1)
{
F38_4KHZ_ON();//因为红外码大部分都是起始一段高电平,所以此处一开始就打开。
TIMER0_RELOAD(addr);//时长装入定时器,开始计时
addr+=2;// 地址移到没有取过的地方,TIMER0_RELOAD函数取了两个地址的数据
while (!TF0);//等待定时器0溢出
if(level_cnt–==0)break;//判断是否取完
F38_4KHZ_OFF(); IR_SEND = 1;//停止发射
TIMER0_RELOAD(addr);//时长装入定时器,开始计时
addr+=2;//地址移到没有取过的地方,TIMER0_RELOAD函数取了两个地址的数据
while (!TF0);//等待定时器0溢出
if(level_cnt–==0)break;//电平数是否完毕
}
F38_4KHZ_OFF(); IR_SEND = 1;//停止发射
}
//---------------------------------------------------
void SaveLevelTimeLength(uint addr)//存电平时长
{
TR0=0;
byte_write(addr, ~TH0);
byte_write(addr+1, ~TL0); //电平时长存入eeprom中
TH0=0;//定时器初值归0
TL0=0x65;//查手册知道,编程一个字节需要55us,编程两个字节,所以此处需要110us。
TR0=1;//开始计数
}
void IrStudy()
{
uint level_cnt;
uint addrtmp;
TF0 = 0;
SectorErase(addr);
addrtmp=addr;//记录第一个地址,存储电平个数
addr++;
TR0=0;//停止计数
while (IR_REV);//等待红外接收管脚为低电平
//编码与解码是一对逆过程,不仅在原理上是一对逆过程,在码的发收过程也是互反的,即以前发射端原始信号是高电平,那接收头输出的就是低电平
TH0=0;
TL0=0;
TR0=1;//开启定时器
while (1)
{
while (!IR_REV) //等待高电平,等待超时;超过70MS退出
{
if (TF0)
{
goto StudyFinish;
}
}
SaveLevelTimeLength(addr); //高电平到来,存低电平时长到eeprom}
level_cnt++;
addr += 2;
while (IR_REV) //等待低电平,等待超时;超过70MS退出
{
if (TF0)
{
goto StudyFinish;
}
}
SaveLevelTimeLength(addr);//低电平到来存高电平电平时长
level_cnt++;//存储的电平个数加11
addr+=2;//地址后移两位
}
StudyFinish:
TF0=0;
TR0=0;
byte_write(addrtmp,level_cnt);
level_cnt = 0;
}
void Delay100ms() //@11.0592MHz
{
unsigned char i, j, k;
nop();
nop();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (–k);
} while (–j);
} while (–i);
}
void IapIdle()
{
IAP_CONTR = 0; //Close IAP function
IAP_CMD = 0; //Clear command to standby
IAP_TRIG = 0; //Clear trigger register
IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area
IAP_ADDRL = 0; //Clear IAP address to prevent misuse
}
/************************************************************************
函数名称:字节写
全局变量:无
参数说明:addr:写入地址, dat:写入数据
************************************************************************/
void byte_write(uint addr,uchar dat)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_DATA = dat; //Write ISP/IAP/EEPROM data
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
nop();
nop();
nop();
nop();
IapIdle();
}
鉴于篇幅限制只能写部分代码
最后,如果有什么意见或者建议欢迎您留言给我,让我们共同学习一起进步,
如果需要完整代码或设计文件,请加QQ分享群,本博客所有代码开源下载,或私信我,看到后会第一时间回复。
谢谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。