数码之家

 找回密码
 立即注册
搜索
查看: 5066|回复: 15

[C51] 基于STC15W单片机的电视机与有线机顶盒联动控制器【红外接收&红外发射】

[复制链接]
发表于 2019-12-1 10:24:35 | 显示全部楼层 |阅读模式
本帖最后由 慕名而来 于 2019-12-10 11:27 编辑

注:本贴文字、图片较多,请通过电脑阅读!
一.源起(啰嗦)  
因为女儿给我的居室里换了一台乐视40SAIR-小时代版的网络电视,连接有线电视机顶盒使用时,出现了问题,其一:启动时电视机对机顶盒的视频信号时常无法识别、看过网络电影后重新接收有线信号时将电视切换到AV状态后已有的视频型号仍然无法识别,上述过程中电视机会停留在AV插头连接的动图状态,此时需要将机顶盒关闭而后再重新启动才能完成信号输送。其二:机顶盒的音频信号与乐视电视机的电平不匹配,正常的连接方式,电视机端音量微小,需要将机顶盒的音量开到满格、电视机的音量开到40以上才能正常收听伴音(与年龄、听觉有关),替代的方法是用电脑小音箱接收机顶盒音频收听伴音,但此时的问题是关闭了电视机后如果不关闭机顶盒就一直听伴音,而一般家庭老年人的使用习惯都是不关闭机顶盒只关闭电视机的。其三:综上所述,换了电视机后老伴不会用了,而我却暗暗窃喜,因为我看到了“玩”机,终于有东西可以编程控制了*****(这里删掉了6个哈)
二.方案(简述)
简述方案之前需要先说说电视机、机顶盒的启动特征;此型乐视电视机经遥控器启动后经过开机广告、系统确认等等步骤,需要大约56S后到达视频信号确认时段,广电机顶盒经上电启动或遥控启动后需要大约42S后开始播放电视节目信号。根据上述两个实测的时间,控制顺序为启动电视机后等待12S启动机顶盒,再等待40秒后为电视机发送“视频”遥控信号、而后再为机顶盒发送“确认”(全屏)的遥控信号至此就完成了联机启动过程,而关闭过程为:发送关机信号后首先发送机顶盒关机信号等待17S后关闭电视机、机顶盒电源。
善意提示:本系统仅适合有兴趣且会玩单片机的小伙伴折腾,不适合商用所以不要商用否则会害人的,原因是网络电视系统时常升级、机顶盒播放系统也时常升级,每次升级都会改变开机时间而产生失控,此时需要小伙伴们通过升级本系统的控制程序来适应。
三.本案(分享)
分享前需要申明的是,本帖代码范本全部源自本坛的坛友之热心开源与分享,在此诚心感谢那些热心分享乐于助人的坛友!!
提示:本贴代码范本提供于此不另行粘贴,只需要将代码中的端口设置按照自己的设置修改好就可以了,而后分别测试、实验直到各个功能部分都可以完全按照自己的想法工作了就新建两个文本文档将代码做成.c和.h文件就可以将他们组合到一起了,关于模块化编程方法请百度解决,如果代码组合时有问题可跟帖探讨!
1.红外接收代码在老站这个帖子:
=== 求  STC  1T单片机红外解码程序 ===|http://bbs.mydigit.cn/read.php?tid=235104
上述帖子的第6楼坛友autopccopy  分享的:
此链接的STC官网代码只要端口设置正确则不用任何改动就直接可以使用了。
2.红外发射代码在老站的这个帖子:
STC15W20x 模拟真38Khz载波红外发射 |http://bbs.mydigit.cn/read.php?tid=2296784
此代码本人参照简易逻辑分析仪实测波形进行了校正及少量改动

改动后的代码如下:
//////////////////////////
IR_out.c
/////////////////////////
#include "IR_out.h"
bit CEND;  //定时器T2中断标志
//============================
void Delay8us()  [url=]//@12.000MHz[/url]
{
unsigned char i;
_nop_();
_nop_();
i = 21;
while (--i);
}
//--------------------------
void Delay18us()  [url=]//@12.000MHz[/url]
{
unsigned char i;
_nop_();
_nop_();
i = 51;
while (--i);
}
//====定时器T2启动函数===============================
void T2_START(uint T_MS)
{
T2L=T_MS;
T2H=T_MS>>8;   
AUXR|=0x10;
IE2|=0x04;
}
//=====高电平输出函数============================
void Wait_High(uint tm)//IR_LED发射
{
CEND = 0;
T2_START(tm);
while(!CEND)//输出38KHz载波
{
IR_IO=0; //开启红外端口8us
Delay8us();
IR_IO=1; //关闭红外端口18us
Delay18us();
}
IR_IO = 1; //关闭红外端口
}
//====低电平输出函数============================
void Wait_Low(uint tn)//IR_LED熄灭
{
IR_IO = 1;
CEND = 0;
T2_START(tn);
while(!CEND)
{
//等待延时结束
}
}
//====数据输出函数==============================
//输出高电平时经红外接收头得到低电平信号
void Send_DATA(uint date)
{
uchar j;
for(j=0;j<8;j++)
{
Wait_High(T0_56MS);//高电平560us起始
if(date&0x01)//从最低位开始发送
  {
  Wait_Low(T1_69MS);// 低电平1.6ms
  }
else
  {
  Wait_Low(T0_56MS);// 低电平560us
  }
date=date>>1;   
}
}
//====机顶盒红外遥控器键值输出函数=========================
void out_IR(bit e,uint key)
{
uchar i,DIL,DIH;
if(e==1)   //机顶盒遥控
{
DIL=0x01;
DIH=0xFD;
}
else if(e==0) //电视机遥控
{
DIL=0x4C;
DIH=0x65;
}
Wait_High(T9MS);//高9ms
Wait_Low(T4_5MS);//低4.5ms
Send_DATA(DIL); //发送用户识别码低8位
Send_DATA(DIH); //发送用户识别码高8位
Send_DATA(key); //发送键值
Send_DATA(~key); //发送键值反码
Wait_High(T0_56MS);//高电平560us 结束位      
Wait_Low(T20MS);
Wait_Low(T20MS);//两次完成40ms延时
CEND = 0;
//4次重复码
for(i=0;i<4;i++)
{
Wait_High(T9MS);//9ms亮
Wait_Low(T2_5MS);//2.5ms灭
Wait_High(T0_56MS);//0.56ms高电平
Wait_Low(T20MS);
Wait_Low(T20MS);
Wait_Low(T20MS);
Wait_Low(T20MS);
Wait_Low(T20MS);//5次完成约100ms延时(波形标值为96.628ms)
}
}

控制过程是:本装置的操控方法很简单,两建启动、一键关闭,启动时按一次机顶盒遥控器的兰键使系统进入待机状态,再按一次机顶盒遥控器的红键(已经学习成电视机遥控器的“待机/启动”键)启动电视机,接下来就放下遥控器等待观看即可。
本装置长期通电值守,在电视机、机顶盒无供电状态下,按下机顶盒遥控器的兰键后系统响应控制J1吸合为电视机上电,此后等待电视机启动,当机顶盒遥控器红键按下时电视机启动,LOGO灯由低亮度变成高亮被本系统光敏电阻检测到,本系统经单片机的ADC转换后得到电视机已经开机的信号,进而操作开机过程(过程详见代码注释)。
以下主函数是我自己写的,这个只能自己写否则就没得玩了哈,代码如下:

#include <STC15W.h>
#include "IR_in.h"
#include "IR_out.h"
#include "stc15w_ADC.h"
#define uchar unsigned char
#define uint  unsigned int
sbit JK1=P1^3; //电视机电源开关(继电器1)
sbit JK2=P1^2; //机顶盒电源开关(继电器2)
sbit led=P1^4; //待机指示灯LED
uchar flag;
bit flag0;
uint temp=0; //ADC转换用数据缓存变量
//================================================
uchar TV_ON()//单片机片内ADC检测函数
{
temp=AD_work(1);
if(temp>980)  //(电视机待机状态)低光照1000
flag0=1;
else
if(temp<960)  //(电视机启动执行状态)高光照940
flag0=0;
return flag0;
}
//以上ADC检测值是通过另外搭电路用4位数码管模块实际测试的、数据仅用于判断所以保留原状态即可不必做真实值的转换

//感兴趣的话可以参照本人另贴:基于单片机ADC采样水位控制的净水机废水回收控制程序https://www.mydigit.cn/forum.php?mod=viewthread&tid=15103(出处: 数码之家)

程序中那些被封闭的定义、函数就是用于测量的,、而相关STC15W单片机片内ADC的代码(本例的stc15w_ADC.c内容)也都在那个帖子里。
//=====主函数 ====================================
void main(void)
{
uchar adc;
uint i;
InitTimer(); //初始化定时器T0
InitADC();//ADC初始化  //设置P1.1--ADC1通道测量光敏电阻电位(端口不用再行sbit定义)
P1M1&=0xff;//ADC检查端口初始化为高阻态
P1M0&=0xfd;
IR_IO=1;   //红外输出端口初始化
P_IR_RX=1;  //红外输入端口初始化
JK1=1;   //释放电视机电源继电器
JK2=1;   //释放机顶盒电源继电器
led=1;   //关闭指示灯
flag=1;   //初始化开机标志、上电或待机时标志置1
flag0=1;   //电视启动上电标志计数变量
while(1)
{
led=0;  //指示灯点亮本系统进入待机状态
//按机顶盒遥控器蓝色待机按键、按键有效时为电视机上电---电视机进入待机状态但不启动电视机
//B_IrUserErr=0时用户码为正确的默认值
if((B_IR_Press)&&(B_IrUserErr==1)&&(IR_code==0xdc))//默认为电视机遥控器用户码0x654C、此处为机顶盒机顶盒待机键查询
{
if(flag==1)
  {
  flag=2;    //标志置位为开机标志
  JK1=0;    //电视机上电
  B_IR_Press = 0; //清除键按下标志
  }
}
//此后电视机上电进入待机状态
//以下是启动电视机时控制机顶盒开机的过程
adc=TV_ON(); //采集电视机logo灯亮度
if(adc==0)  //如果电视机已经启动
{
if(flag==2)     //如果标志为开机值
{
led=1;     //指示灯熄灭
for(i=0;i<280;i++)  //14S延时
  {
  T2_START(T50MS); //启动20ms定时
  CEND=0;    //定时器中断产生后清除中断标志(stc15w的T2没有中断标志)
  led=~led;   //运行开机程序时指示灯闪灯
  while(CEND==0);  //等待新的中断到来
  }
  JK2=0;    //延时结束后机顶盒上电     
  for(i=0;i<800;i++) //40S延时
  {
  T2_START(T50MS);     
  CEND=0;
  led=~led;  
  while(CEND==0);
  }
out_IR(0,0x47);  //延时结束后遥控发送电视机视频切换信号、使电视机进入信号源播放状态   
//out_IR(0,0x47);  //信号发3次避免错失
//out_IR(0,0x47);
  for(i=0;i<40;i++) //2S延时
  {
  T2_START(T50MS);     
  CEND=0;
  led=~led;  //指示灯闪灯
  while(CEND==0);
  }
out_IR(1,0xce);  //2S后发送遥控机顶盒信号使画面全屏显示  
//out_IR(1,0xce);  //信号发3次避免错失
//out_IR(1,0xce);
flag=3;    //标志置位为关机标志
}
}
//以下是电视机、机顶盒关机控制过程
if((B_IR_Press)&&(B_IrUserErr==0)&&(IR_code==0x0a))//如果电视机遥控器有键按下&用户码正确&待机键值正确
{
if(flag==3)     //如果标志为关机值
{
out_IR(0,0x0a);//发送遥控电视机关机信号
out_IR(0,0x0a);
out_IR(0,0x0a);
for(i=0;i<150;i++) //延时5秒
  {
  T2_START(T50MS);
  CEND=0;
  led=~led;   
  while(CEND==0);
  }
out_IR(1,0xdc);   //5S后发送信号遥控关闭机顶盒
out_IR(1,0xdc);
out_IR(1,0xdc);
for(i=0;i<200;i++) //延时10秒
  {
  T2_START(T50MS);
  CEND=0;
  led=~led;   
  while(CEND==0);
  }//10S后
JK1=1;     //关闭电视机电源
JK2=1;     //关闭机顶盒电源
flag=1;     //标志重新初始化   
}
B_IR_Press = 0;   //清除IR键按下标志
}
}
}
//====定时器T0中断函数===========
void timer0 (void) interrupt 1
{
IR_RX_HT6121();
}
//====定时器T2中断函数===========
void Int1(void) interrupt 12
{
IE2 &= ~0x04;
IE2 |= 0x04;
CEND = 1;
IE2&=~0x04;//关中断
AUXR&=~0x10;//关定时器
}


电路原理图:


实物图:
图中的组件2就是2根线连接了一个红外发射二极管。

图中的组件1实物如下图:



主机制作完成后的图片:



接线完成后的图片:
图片中的白钢带为自制的配件用于适应其他电视挂架,黄/黑线经线槽输送给机顶盒电源插座。


全部完工后的效果图片:
电视机下方外观上仅多出了一个一元硬币大的小盒挡住了两个LOGO发光字符。


居室角落里的机顶盒及音箱:



代码分享:https://www.mydigit.cn/forum.php?mod=viewthread&tid=105571

本帖子中包含更多资源

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

x

打赏

参与人数 4家元 +108 收起 理由
xiaoqi233 + 8 謝謝分享,就是图片太小了
家睦 + 60
jf201006 + 20 謝謝分享
cushion + 20 原創內容

查看全部打赏

发表于 2019-12-1 10:32:51 | 显示全部楼层
真能折腾,赞 楼主
回复 支持 反对

使用道具 举报

发表于 2019-12-1 11:01:45 | 显示全部楼层
为了看个电视折腾得好辛苦
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-1 12:19:44 | 显示全部楼层
维超 发表于 2019-12-1 10:32
真能折腾,赞 楼主

已经很久没弄东西了,也借此消消手痒。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-1 12:20:35 | 显示全部楼层
lcy960 发表于 2019-12-1 11:01
为了看个电视折腾得好辛苦

有的玩就好
回复 支持 反对

使用道具 举报

发表于 2019-12-1 20:26:34 来自手机浏览器 | 显示全部楼层
乐视的电视跟手机都是广告机啊…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-2 09:50:32 | 显示全部楼层
触景情伤 发表于 2019-12-1 20:26
乐视的电视跟手机都是广告机啊…

多谢过来临帖,真的不喜欢这种网络电视,原本用创维的,感觉那才是真正的电视机,家里的小棉袄的孝心难拒,关闭了网络后不再更新暂时稳定了,另外用音箱听伴音不但音质好、最大的好处是可以关闭电视机的音响省的广告声音大吵人,一番折腾后一切又归于平静,开关看电视的操作又回到了以往的状态,挺爽的。
回复 支持 反对

使用道具 举报

发表于 2019-12-2 10:41:16 来自手机浏览器 | 显示全部楼层
慕名而来 发表于 2019-12-2 09:50
多谢过来临帖,真的不喜欢这种网络电视,原本用创维的,感觉那才是真正的电视机,家里的小棉袄的孝心难拒 ...

平平凡凡才是真…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-3 09:51:35 | 显示全部楼层

现在很多产品为了增加加价的噱头,功能弄的花里胡哨的,而基本功能却不咋地,使用者只能随遇而安吧。
回复 支持 反对

使用道具 举报

发表于 2019-12-9 22:02:38 | 显示全部楼层
谢谢楼主分享,我们就是乐视的电视,不过前一段时间小孩升级,卡logo了,没办法,网上淘了一块主板换上,又可以用了。
回复 支持 反对

使用道具 举报

发表于 2019-12-10 09:25:27 | 显示全部楼层
好资料,感谢共享
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-10 11:21:26 | 显示全部楼层
shyboy133 发表于 2019-12-9 22:02
谢谢楼主分享,我们就是乐视的电视,不过前一段时间小孩升级,卡logo了,没办法,网上淘了一块主板换上,又 ...

如果有兴趣做一个这东西真的很实用,如果没有这个装置,开机时要么是一只手一个遥控器,即使通过遥控器按键学习用一个遥控器也要分别操作,最讨厌的是这款乐视电视机经常的不能确认已有的有线电视信号,原本运行中的机顶盒还要再次关机再启动才能正常播放,正常播放后还要按确认键才能使电视画面全屏显示,真的太讨厌了,现在是遥控器两个按键按完后放下遥控器等待就好了,上述那些操作全部都自动完成了。晚间在床上看电视关机的时候电视机的logo灯、机顶盒的显示屏、音箱的指示灯弄的卧室里各种颜色的光亮,每次都要下地关电源,有时关了电源再上床时睡意就散了,现在好了,遥控器放在手边,一键关机直接睡了。
回复 支持 反对

使用道具 举报

发表于 2019-12-10 19:24:28 | 显示全部楼层

好资料,感谢共享:lol::lol::lol:
回复 支持 反对

使用道具 举报

发表于 2022-1-29 15:23:18 | 显示全部楼层
指示用的LED是不是画反了?

打赏

参与人数 1家元 +10 收起 理由
慕名而来 + 10 精彩回帖

查看全部打赏

回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-30 14:56:43 | 显示全部楼层
kindzhon 发表于 2022-1-29 15:23
指示用的LED是不是画反了?

多谢指正,确实画反了,我习惯用单片机低电平使能LED,这个真的画反了!
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-10 19:35 , Processed in 0.748801 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表