迅维网

查看: 10293|回复: 52
打印 上一主题 下一主题

自制STC80C51红外遥控电路板

  [复制链接]
跳转到指定楼层
1#
发表于 2013-11-8 20:35:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 来自: 四川自贡 来自 四川自贡

马上注册,获取阅读精华内容及下载权限

您需要 登录 才可以下载或查看,没有帐号?注册

x
/*
此程序为红外遥控,按遥控器上的按键后在数据管上显示相应的地址码和指令码

*/

#include "reg52.h"
#define uchar unsigned char
sbit hwx=P3^3;                      //中断1端口P3.3
uchar irtime,irdata[32],ircord[4];  //irtime:收集IR1838数据引脚低电平脉冲宽度的计数变量,根据此变量数值大小判断是0还是1
                                                                        //irdata数组:地址码和指令码每位的存储数组,地址码16位,指令码8位,指令码反码8位,共32位,引导码丢弃没用
                                                                        //ircord数组:将地址码和指令码做转后存储为字节的数组,以便查询num数组里面的值,在数码管上显示码值的十六进制
uchar code num[]={                                        //数码管显示所有数组
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
bit irok;                                                 //将位数转为字节数后的标志位

void delay(unsigned int k)                //执行一次为50ms左右
{
        uchar i;
        unsigned int j;
        i=250;
        while(i)
        {
                j=k;
                while(j)j--;
                i--;
        }
}
void tim0init()                          //定时器0初始化函数
{
        TMOD=0x02;
        ET0=1;
        EA=1;
}
void ex1init()                        //中断1初始化函数
{
        IT1=1;
        EX1=1;
}
void tim0ir() interrupt 1                        //定时器0中断函数
{
        irtime++;                                           //irtime为低电平宽度变量,每加1,时间将增加256微秒
}
void ex1ir() interrupt 2                  //中断1中断函数
{
        static uchar i;                                //i变量为局部静态变量,第二次进入函数时,其值不会被置0,而是接着上一次调用函数后的值运行
        static bit startflag;                //startflag变量:判断是引导码后,其值置1,表示接收码数据开始.接收32个位后,被置0,停止接收
        uchar tmp;
        tmp=10;
        while(tmp) tmp--;                   //延时函数,消除干扰
        if(hwx)                                           //再次判断是干扰还是数据,hwx为0表示数据,为1表示是干扰产生的中断
        {
                return;
        }                  
        TH0=TL0=0;
        TR0=1;                                         //每位中断产生时,计数清零
        if(startflag)
        {
                irdata=irtime;         
                irtime=0;
                i++;
                if(i==32)                         //当计满32位后,将相关变量清0,准备接收第二次按键
                {
                       
                        EX1=0;                        //关闭中断,延时400ms,消除有用数据后的干扰数据
                        TR0=0;
                        startflag=0;
                        irok=1;                         //接收完时,将irok置1,表示可以进行位到字节的转换
                        delay(200);                  //延时25为50ms左右,延时200既为400ms
                        EX1=1;                         //延时消除干扰后,打开中断,准备接收第二次按键
                        return;
                }
        }
        if((irtime>=47)&&(irtime<56))        //如果irtime在47和56之间,确定为引导码,准备接收数据
        {
                i=0;
                irtime=0;
                startflag=1;                   //startflag置1后,下一次的中断既为接收址码开始
        }

}
void irpro()
{
        uchar i,j,k,value;
        value=k=0;                          //此处需注意加赋值语句,不然第二次调用函数时,两个变量的初值有时不会是0
        for(i=0;i<4;i++)          //共四个字节需要转
        {
                for(j=0;j<8;j++)   //每字节八位
                {
                        value=value>>1;
                         if(irdata[k]>5) value=value|0x80;
                        k++;
                }
           ircord=value;                 //将位转为字节后的数据存入ircord数组
           value=0;
        }
        irok=0;           //转换结束标志
}
void irdisplay()                //数码管显示函数
{
       
        P1=0;
        P2=num[ircord[0]/16];         //以16进制显示
        delay(1);

        P1=1;
        P2=num[ircord[0]%16];
        delay(1);

        P1=3;
        P2=num[ircord[2]/16];
        delay(1);

        P1=4;
        P2=num[ircord[2]%16];
        delay(1);
}
void main(void)
{
        tim0init();
        ex1init();
        while(1)
        {
                if(irok)
                {
                        irpro();          //位数转换为字节
                }
                irdisplay();        //显示码值
               
       
        }
       
}



点评

还看不懂正在努力学习C中,顺便请教下楼主,学单片机是不是学好C和汇编就可以不用再单独学习其他的东西  发表于 2013-11-11 11:16

评分

参与人数 5下载分 +110 威望 +1 原创币 +1 收起 理由
ptmanager + 20 赞一个!
小小学徒工 + 10 很给力!
wxf + 10 很给力!
兄弟电脑电器 + 10 外星入侵地球,不知何物。。。
yzz163 + 60 + 1 + 1 有理论、有实物、对红外遥控协议理解有深度

查看全部评分

本文由 会员844227 原创或被授权转载制作,其他机构或个人未经许可严禁转载。
2#
发表于 2013-11-8 21:15:26 | 只看该作者 来自: 陕西西安 来自 陕西西安
闲得没事做得人,还不如再设计点火药什么什么得,哪样才有实用性

回复 支持 反对

使用道具 举报

3#
发表于 2013-11-8 22:35:21 | 只看该作者 来自: 广东广州 来自 广东广州
学习了

回复 支持 反对

使用道具 举报

4#
发表于 2013-11-8 22:42:40 | 只看该作者 来自: 陕西西安 来自 陕西西安
原来遥控器这么麻烦啊!

回复 支持 反对

使用道具 举报

5#
发表于 2013-11-8 22:48:07 | 只看该作者 来自: 广东广州 来自 广东广州
牛人  不错 不错

回复 支持 反对

使用道具 举报

6#
发表于 2013-11-8 23:12:52 | 只看该作者 来自: 北京 来自 北京
看那些指令看的眼花缭乱,好像天书一样,没看懂,只看懂楼主编了个程序,制作了一个电路板,装好测试,波形正常,说明制作成功,不知我理解对否

回复 支持 反对

使用道具 举报

7#
发表于 2013-11-8 23:59:31 | 只看该作者 来自: 广西南宁 来自 广西南宁
现在手头有点紧,修本本赚点盘缠先,暂时没时间研究这么高深的东西,楼主厉害!!

回复 支持 反对

使用道具 举报

8#
发表于 2013-11-9 20:57:45 | 只看该作者 来自: 四川 来自 四川
我是两年前学的,到现在隔了两年没搞了,这段时间也在学维修笔记本。找算有机会自己开个店

补充内容 (2013-11-11 22:19):
可以呀,多多交流

点评

咱们有空多交流,我正在学单片机,这方面可以多向你学习  发表于 2013-11-11 11:17
回复 支持 反对

使用道具 举报

9#
匿名  发表于 1970-1-1 08:00:00 来自
post_deleted

10#
发表于 2013-11-9 20:59:50 | 只看该作者 来自: 四川 来自 四川
发表于 2013-11-8 21:15:26 |只看该作者
闲得没事做得人,还不如再设计点火药什么什么得,哪样才有实用性
=============================
你说对的,当时的确很闲 。单片机很费时间的。

回复 支持 反对

使用道具 举报

11#
发表于 2013-11-10 18:26:56 | 只看该作者 来自: 广西桂林 来自 广西桂林
楼主牛B

回复 支持 反对

使用道具 举报

12#
发表于 2013-11-10 18:43:05 | 只看该作者 来自: 北京 来自 北京
楼主太牛逼了

回复 支持 反对

使用道具 举报

13#
发表于 2013-11-10 18:44:20 | 只看该作者 来自: 广东云浮 来自 广东云浮
输出部分没有

回复 支持 反对

使用道具 举报

14#
发表于 2013-11-10 19:27:30 | 只看该作者 来自: 广西 来自 广西
太有才了,但没什么价值

回复 支持 反对

使用道具 举报

15#
发表于 2013-11-10 20:52:38 | 只看该作者 来自: 四川 来自 四川

输出部分没有
================
明眼人,这个代码一看就没输出,我也是贴上代码后才发觉贴了另一个程序的代码,不好意思

回复 支持 反对

使用道具 举报

16#
发表于 2013-11-10 20:54:01 | 只看该作者 来自: 四川 来自 四川
贴上属于本身的代码
/*
此程序为红外遥控开关,可使用一般的家电遥控器进行控制,无须专门配置遥控器。按任一遥控器上的某一按键2~3秒即可将此键设置为开关键,
设置后每次按键,继电器执行相应的开关动作,对电灯进行控制。中途可改变遥控器或选用另外按键来进行开关,只须按另外键2~3秒设置即可。
在使用不同的晶振时,延时不一样,此代码使用的是8M晶振。
*/

#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int
sbit hwx=P3^3;                      //中断1端口P3.3
sbit jdqkg=P3^6;                                                 //继电器控制端
uchar irdata[33],ircord[4],oldcord[4]={1,1,1,1};                  //irdata数组:地址码和指令码每位的存储数组,地址码16位,
                                                                                                  //指令码8位,指令码反码8位,共32位,引导码丢弃没用
                                                                                                //ircord数组:将地址码和指令码做转后存储为字节的数组,以便查询num数组里面的值
                                                                                                //oldcord数组:存入指定设置遥控器的地址码和遥控器上某一开关数据值
bit irok,reok;                                                 //irok将位数转为字节数后的标志位 ,reok是否有重复码产生而进行开关键重新设置标志位

void ex1ir() interrupt 2                  //中断1中断函数
{
        uchar i;
        uint tmp;
        PCON=0;                                                //有中断产生,中止节能模式,进入正常模式
        EX1=0;
        tmp=17;
        while(tmp) tmp--;                   //延时200微秒,消除干扰.使用8M晶振初值100延时1200微秒,初值17即可延时200微秒 。
                                                                // 此处只是相对uint数据类型,uchar类型计算出的延时初值会不一样。需在软件里面模拟测试
        if(hwx)                                           //判断是干扰还是数据,hwx为0表示数据,为1表示是干扰产生的中断
        {       
                EX1=1;
                return;
        }
        i=33;
        while(i)
        {       
                irdata[33-i]=0;
                while(!hwx)                  //低电平数据直接丢去,此处暂未加防干扰死循环
                {
                        ;
                }
               
                while(hwx)
                {
                        irdata[33-i]++;                               
                        tmp=5;
                        while(tmp) tmp--;                //加入延时初值5,否则数组值会被计满。延时60微秒 。更换晶振,此处做相应修改
                        if(irdata[33-i]==255) break;                //如果数组计满255,说明有干扰,退出死循环
                }
                i--;

        }
        while(!hwx);                   //丢弃有用数据之后的低电平
        i=0;
        while(hwx)                          //毛弃有用数据之后的高电平
        {
                tmp=50;
                while(tmp) tmp--;
                if(i>250) break;         //        防止死循环
                i++;
        }
        i=0;
        while(!hwx)                  //延时后看是否重复码产生
        {
                i++;
                tmp=9050;           //延时108.4毫秒初值9050  更换晶振,此处做相应修改
                while(tmp) tmp--;
                if(i>250) i=250;        //如果长时间按键不松,将变量值始终定为250,防止变量溢出
        }

        if((5<i)&&(i<50))
        {
                reok=1;                        //reok为是否有重复按键产生,当按键时间大于2~3秒后,程序会对所按的键设置为开关灯键
        }
        irok=1;
        EX1=1;

}


void irpro()
{
        uchar i,j,k,value;
        value=k=1;                          //此处需注意加赋值语句,不然第二次调用函数时,两个变量的初值有时不会是0,k=1数组从第二个开始,第一个为引导码,不用
        for(i=0;i<4;i++)          //共四个字节需要转
        {
                for(j=0;j<8;j++)   //每字节八位
                {
                        value=value>>1;
                         if(irdata[k]>10) value=value|0x80;        //更换晶振,此处比较值做相应修改       
                        k++;
                }
           ircord[i]=value;                 //将位转为字节后的数据存入ircord数组
           value=0;
        }
        if(reok)                                 //reok为1表示有重复码产生,要进行遥控器开关键设置
        {
                reok=0;
                for(i=0;i<4;i++)
                {
                        oldcord[i]=ircord[i]; //将新按键或遥控器值对oldcord进行更新,使新设置开关键生效
                }
        }
}

void main(void)
{
        EA=1;
        EX1=1;
        IT1=1;
        while(1)
        {
                if(irok)                //是否进行位数到字节的转换
                {
                        irok=0;
                        irpro();          
                }
                if(ircord[0]==oldcord[0])                        //地址码判断是否是同一遥控器的按键
                {
                        if(ircord[2]==oldcord[2])           //0、1元素为地址码,2元素为数据码,3元素为数据码反码        。此处判断是否是开关键被按下
                        {
                                ircord[2]=0;
                                jdqkg=~jdqkg;                         //取反,控制开和关
                        }
                }
                PCON=PCON|0x01;
        }
}

评分

参与人数 1下载分 +4 收起 理由
erwin + 4

查看全部评分

回复 支持 反对

使用道具 举报

17#
发表于 2013-11-10 20:59:36 | 只看该作者 来自: 四川 来自 四川
没想到贴子加精了,还送了好多下载分,早知道这样也可以送下载分,我就不拿RMB充值了。以后多发点,我还有好多原创的电路板和代码呢

回复 支持 反对

使用道具 举报

18#
发表于 2013-11-11 11:28:02 | 只看该作者 来自: 广东广州 来自 广东广州
看得出楼主花了很大的心思修这板,花了更大的心思发帖,值得鼓励!表扬!

回复 支持 反对

使用道具 举报

19#
发表于 2013-11-11 12:19:24 | 只看该作者 来自: 江苏苏州 来自 江苏苏州
单片机。。C   要很大毅力啊

回复 支持 反对

使用道具 举报

20#
发表于 2013-11-11 12:58:16 | 只看该作者 来自: 四川自贡 来自 四川自贡
主要还是要有兴趣。我是全凭兴趣才坚持了一年多,能做出板子出来写代码

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表
附近
店铺
微信扫码查看附近店铺
维修
报价
扫码查看手机版报价
信号元
件查询
点位图


芯片搜索

快速回复