标题:
51单片机38k红外解码程序与制作
[打印本页]
作者:
1091212269
时间:
2019-6-8 20:49
标题:
51单片机38k红外解码程序与制作
上次大神指点后做了一些改进显示16位16进制的数据,二进制就是64位。频率是38k的。空调,电视,风扇,只要是家电的红外95%以上都可以解码,如果解码空调,建议每次使用前复位一次,清空数组的程序一直写失败,大神可以来改一下。另外发现部分手机(测试荣耀9)打开相机的时候会触发中断,让数据变得不正常。
制作出来的实物图如下:
微信图片_20190608204008.jpg
(130.52 KB, 下载次数: 47)
下载附件
2019-6-8 20:40 上传
单片机源程序如下:
/*********************************************************************************************
程序名: DHT11-1602
编写人: fby
硬件支持: STC89C52RC DHT11 LCD1602
接口说明: DHT11:VCC DATA NC GND
*********************************************************************************************
说明:1、单片机是STC89C52RC,晶振频率11.0592MHz,实验成功。
2、好东西要共享,大家随意折腾~~
*********************************************************************************************/
#include<reg51.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char //无符号字符型类型数据
#define uint unsigned int //无符号整型数据
#define ulong unsigned long //无符号整型数据
#define xiao float //xiaoshu
#define IODATA P0
unsigned char IrValue[24]; //接收收据
unsigned char Time;
sbit RS=P2^6; //定义rs端口
sbit RW=P2^5; //定义rw端口
sbit E=P2^7;
sbit IRIN=P3^2;//红外数据io
/*******************************************************************************
* 函数名 : DelayMs()
* 函数功能 : 延时
* 输入 : x
* 输出 : 无
*******************************************************************************/
void DelayMs(unsigned int x) //0.14ms误差 0us
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++)
{}
}
}
/*******************************************************************************
* 函数名 : IrInit()
* 函数功能 : 初始化红外线接收
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void IrInit()
{
IT0=1;//下降沿触发
EX0=1;//打开中断0允许
EA=1; //打开总中断
IRIN=1;//初始化端口
}
/*******************************************************************************
* 函数名 : ReadIr()
* 函数功能 : 读取红外数值的中断函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
//数据处理
void sjcl()
{
IrValue[8]=IrValue[0]>>4; //高位 用户码
IrValue[9]=IrValue[0]&0x0f; //低位
IrValue[10]=IrValue[1]>>4; //高位 用户反码
IrValue[11]=IrValue[1]&0x0f; //低位
IrValue[12]=IrValue[2]>>4; //高位 数据码
IrValue[13]=IrValue[2]&0x0f; //低位
IrValue[14]=IrValue[3]>>4; //高位 数据反码
IrValue[15]=IrValue[3]&0x0f; //低位
IrValue[16]=IrValue[4]>>4; //高位 数据反码
IrValue[17]=IrValue[4]&0x0f; //低位
IrValue[18]=IrValue[5]>>4; //高位 数据反码
IrValue[19]=IrValue[5]&0x0f; //低位
IrValue[20]=IrValue[6]>>4; //高位 数据反码
IrValue[21]=IrValue[6]&0x0f; //低位
IrValue[22]=IrValue[7]>>4; //高位 数据反码
IrValue[23]=IrValue[7]&0x0f; //低位
}
void ReadIr() interrupt 0
{
unsigned char j,k;
unsigned int err;
Time=0;
DelayMs(70);
if(IRIN==0) //确认是否真的接收到正确的信号
{
err=1000; //1000*10us=10ms,超过说明接收到错误的信号
/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
侯,程序死在这里*/
while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
{
DelayMs(1);
err--;
}
if(IRIN==1) //如果正确等到9ms低电平
{
err=500;
while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
{
DelayMs(1);
err--;
}
for(k=0;k<8;k++) //共有8组数据
{
for(j=0;j<8;j++) //接收一组数据
{
err=60;
while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
// while (!IRIN)
{
DelayMs(1);
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
DelayMs(1);//0.14ms
Time++;
err--;
if(Time>30)
{
EX0=1;
return;
}
}
IrValue[k]>>=1; //k表示第几组数据
if(Time>=8) //如果高电平出现大于565us,那么是1
{
IrValue[k]|=0x80;
}
Time=0; //用完时间要重新赋值
}
}
}
return;
}
sjcl(); //数据处理
}
/*********************************************************************************************
函数名:延时函数
调 用:Delay30us();/Delay20ms();/Delay1s();
参 数:无
返回值:无
结 果:延时相应时间
备 注:振荡晶体为11.0592MHz(所有延时函数Copy自STC-ISP(v6.85).exe)
**********************************************************************************************/
void Delay30us() //@11.0592MHz-40
{
unsigned char i;
i = 11;
while (--i);
}
void Delay20ms() //@11.0592MHz
{
unsigned char i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
void Delay1s() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/********************************************************************
* 名称 : bit Busy(void)
* 功能 : 这个是一个读状态函数,读出函数是否处在忙状态
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void Busy(void)
{
bit busy_flag = 1;
IODATA = 0xff;
RS = 0; //指令关
Delay30us();
RW = 1; //读状态
Delay30us();
E = 1; //使能高电平
while(1)
{
busy_flag = (bit)(IODATA & 0x80); //强制取最高位
if(busy_flag == 0)
{
break;
}
}
E = 0; //E 1->0,rs=0,rw=1,
//将数据寄存器内的数据读到DB0~DB7,分别将状态标志BF和地址计数器(AC)内容读到DB7和DB6~DB0。
}
/********************************************************************
* 名称 : lcd1602_write_cmd(uchar del)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void lcd1602_write_cmd(uchar del)
{
RS = 0;
Delay30us();
RW = 0;
Delay30us();
E = 0;
Delay30us();
IODATA = del;
Delay30us();
E = 1;
Delay30us();
E = 0; //E 1->0,rs=0,rw=0, 将指令代码写入指令寄存器中
}
/********************************************************************
* 名称 : lcd1602_write_data(uchar del)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void lcd1602_write_data(uchar del)
{
Busy();
Delay30us();
RS = 1;
Delay30us();
RW = 0;
Delay30us();
E = 0;
Delay30us();
IODATA = del;
Delay30us();
E = 1;
Delay30us();
E = 0; //E 1->0,rs=1,rw=0, 数据写入数据寄存器中
}
/********************************************************************
* 名称 : lcd1602_init()
* 功能 : 1602初始化,请参考1602的资料
* 输入 : 无
* 输出 : 无
***********************************************************************/
void lcd1602_init(void)
{
Delay20ms();
lcd1602_write_cmd(0x38); //8位数据,双列,5*7字形
Delay20ms();
lcd1602_write_cmd(0x38);
Delay20ms();
lcd1602_write_cmd(0x38);
Busy();
lcd1602_write_cmd(0x08);// 只开显示
Busy();
lcd1602_write_cmd(0x01); //清屏
Busy();
lcd1602_write_cmd(0x06);//显示地址递增,即写一个数据后,显示位置右移一位
Busy();
lcd1602_write_cmd(0x0c); //开启显示屏,关光标,光标不闪烁
}
/********************************************************************
* 名称 : lcd1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
L1602_char(1,5,'b')
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void lcd1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1)
{
a = 0x80;
}
if(hang == 2)
{
a = 0xc0;
}
a = a + lie - 1;
Busy();
lcd1602_write_cmd(a); //置数据存贮器地址
Busy();
lcd1602_write_data(sign);
}
/********************************************************************
* 名称 : lcd1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void lcd1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1)
{
a = 0x80;
}
if(hang == 2)
{
a = 0xc0;
}
a = a + lie - 1;
while(1)
{
Busy();
lcd1602_write_cmd(a);
Busy();
lcd1602_write_data(*p);
a++;
p++;
if((*p == '\0')||(a==0x90)||(a==0xd0)) //字符结束或每行最后一个字符
{
break;
}
}
}
/*********************************************************************************************
函数名:主函数
调 用:无
参 数:无
返回值:无
结 果:读DHT11数据并送到1602显示
备 注:
**********************************************************************************************/
void main (void)
{
unsigned char k;
Delay20ms();
lcd1602_init(); //LCD初始化
IrInit(); //红外初始化
while(1)
{
//LcdWriteData(0x37+IrValue[4]); //将数值转换为该显示的ASCII码
//LcdWriteData(IrValue[4]+0x30); //将数值转换为该显示的ASCII码
lcd1602_string(1,1,"HWJM:");
for(k=0;k<16;k++)
{
if(IrValue[k+8]>9)
{
lcd1602_char(2,k+1,IrValue[k+8]+0x37);
}
else
{
lcd1602_char(2,k+1,IrValue[k+8]+0x30);
}
}
}
}
复制代码
所有资料51hei提供下载:
红外解码.zip
(57.38 KB, 下载次数: 55)
2019-6-8 20:24 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
1091212269
时间:
2019-6-8 20:50
后面为0的是没有数据,可以不用看
作者:
1025119291
时间:
2019-6-9 17:02
虽然看不懂,还是默默点个赞
作者:
玉萌业余发展
时间:
2023-3-2 15:16
我试了我只风扇遥控器,按同样的键,每次显示的码都不一样
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1