版本排序说明
Ver4.0
Ver3.0
Ver2.0
Ver1.0
2016.01.18 机顶盒死机解决方案,
版本Ver4.0
参数已经调整为线上模式:
1,死机检测主板:监测SDI盒子两个LED灯,180秒的熄灭状态,触发一个大约15秒的高电平输出然后拉低电平,推挽输出驱动能力20ma,机顶盒无条件关机15秒,然后开机
2,频道锁定:开机会有一个70秒的等待,然后进入频道设定的过程
3,发送短信:高阻模式下对应的引脚如果检测到有一个9秒的高电平输出,发出短信提示给两个管理员
详细功能,见程序注释
/* 项目名称:机顶盒死机发送短信程序 日期:2016年01月18日 20:10 版本:2.0 兼容死机监控端的3.0程序 作者:chunli 博客:http://990487026.blog.51cto.com/ 邮箱:[email protected] 编码环境:GBK2312简体中文 为了代码在各编辑器美观的兼容,没有使用tab键,全用空格隔开 μVision 版本:4.72.9.0 [如果没有License 编译此程序 会报错] 代码类型:C语言 更新说明: 1,增加了一个管理员手机号,发生重启事件,把事件发送给两个管理员的手机上 2,加入开启・关闭发送短信功能 3,去除��嗦注释 硬件兼容: 单片机型号:STC12C5A60S2 晶振频率:11.0592M 谐振电容:30PF SIM900A模块+无短信功能限制SIM卡一张 使用说明: 一、 发送短信模块只提供以下频道的监控,单片机引脚功能的定义请看程序首部 CCTV 5 --> 监控大板的上边左第1个模块,输出高电平长度大于crash_time数值,触发发送短信给Admin_phone_number CCTV 14 --> 监控大板的上边左第2个模块 湖南卫视 --> 监控大板的上边左第3个模块 CCTV13 --> 监控大板的上边左第4个模块 安徽卫视 --> 监控大板的上边左第5个模块 东方卫视 --> 监控大板的上边左第6个模块 黑龙江卫视 --> 监控大板的上边左第7个模块 备用频道 08 --> 监控大板的下边左第3个模块 备用频道 09 --> 监控大板的下边左第2个模块 备用频道 10 --> 监控大板的下边左第1个模块 二、 蜂鸣器一声响:提示正常,模块已经完成与SIM900A对话初始化 蜂鸣器二声响:提示已经发送短信给Admin_phone_number1 蜂鸣器三声响:提示已经发送短信给Admin_phone_number2 蜂鸣器六声响:提示已经打开 或者已经关闭 发送短信功能 蜂鸣器九声响:提示因关闭发送短信功能,发生了死机事件,无法发送短信 三、 Grant_message手机号,发送短信内容"开启发送短信功能"到SIM900A模块的号码,就会开启因宕机事件触发的发送短信功能,并返回一条"已开启发送短信功能"的短信 Grant_message手机号,发送短信内容"关闭发送短信功能"到SIM900A模块的号码,就会关闭因宕机事件触发的发送短信功能,并返回一条"已关闭发送短信功能"的短信 也可以测试单片机和Sim900A模块是否在正常工作。 测试环境crash_time的数值:2,便于测试功能 线上环境crash_time的数值:9,真实环境触发条件 【前提是死机监控端的延时要精准】,死机监控端高电平持续时间足够长,必须大于crash_time的数值 编译结果: Rebuild target 'Target 1' compiling 死机就发送短信.c... linking... Program Size: data=91.0 xdata=100 code=3470 creating hex file from "机顶盒"... "机顶盒" - 0 Error(s), 0 Warning(s). */ #include "STC12C5A60S2.H" #include "STRING.H" #define cache_max 200 //串口接收缓存长度,不能太短啊,要能存储一个简短的短信内容 #define crash_time 9 //定义死机超时,秒 //单片机引脚定义,低电平超时crash_time 触发 发送短信 sbit channel_01 = P0^0; unsigned char channel_01_timer_ms,channel_01_timer_sec; //CCTV 5 定义宕机毫秒 ,秒计时变量 sbit channel_02 = P0^1; unsigned char channel_02_timer_ms,channel_02_timer_sec; //CCTV 14 sbit channel_03 = P0^2; unsigned char channel_03_timer_ms,channel_03_timer_sec; //湖南卫视 sbit channel_04 = P0^3; unsigned char channel_04_timer_ms,channel_04_timer_sec; //CCTV 13 sbit channel_05 = P0^4; unsigned char channel_05_timer_ms,channel_05_timer_sec; //安徽卫视 sbit channel_06 = P0^5; unsigned char channel_06_timer_ms,channel_06_timer_sec; //东方卫视 sbit channel_07 = P0^6; unsigned char channel_07_timer_ms,channel_07_timer_sec; //黑龙江卫视 sbit channel_08 = P0^7; unsigned char channel_08_timer_ms,channel_08_timer_sec; //备用频道 08 sbit channel_09 = P2^7; unsigned char channel_09_timer_ms,channel_09_timer_sec; //备用频道 09 sbit channel_10 = P2^6; unsigned char channel_10_timer_ms,channel_10_timer_sec; //备用频道 10 sbit beep = P1^0; //单片机运行指示灯 sbit runing_led = P1^1; //蜂鸣器 //定义拥有开启,关闭发送短信功能的管理员手机号码+8134******** unsigned char code *Grant_message="0031003300340032003900360037003*003*003*003*"; //管理员1的手机号码 unsigned char code *Admin_phone_number1="AT+CMGS=\"003100330034003200390036003*0038003*003*003*\""; //管理员2的手机号码 unsigned char code *Admin_phone_number2="AT+CMGS=\"003100350030003800380036003*0039003*003*003*\""; //CCTV5频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_01="004300430054005600359891905300206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //CCTV14少儿频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_02="0043004300540056003100345C11513F9891905300206B63572891CD542FFF0C8BF700355206949F540E523765B098759762"; //湖南卫视频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_03="6E565357536B89C69891905300206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //CCTV13新闻频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_04="00430043005400560031003365B095FB9891905300206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //安徽卫视频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_05="5B895FBD536B89C69891905300206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //东方卫视频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_06="4E1C65B9536B89C69891905300206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //黑龙江卫视频道 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_07="9ED19F996C5F536B89C69891905300206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //备用频道08 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_08="59077528989190530030003800206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //备用频道09 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_09="59077528989190530030003900206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; //备用频道10 正在重启,请5分钟后刷新页面。 unsigned char code *message_content_10="59077528989190530031003000206B63572891CD542FFF0C8BF700355206949F540E523765B0987597623002"; unsigned char code *Open_message="5F00542F"; //开启 unsigned char code *Shut_message="517395ED"; //关闭 unsigned char code *Send_open_message="5DF25F00542F53D1900177ED4FE1529F80FD3002"; //已开启发送短信功能。 unsigned char code *Send_shut_message="5DF2517395ED53D1900177ED4FE1529F80FD3002"; //已开启发送短信功能。 //xdata 把变量存在flash中,而不存在RAM中 //code 定义的数据要放在ROM里面,写入后就不能再更改 //Timer_start =Flag^0 定时器标志位 bdata 把变量定义为可拆成8位寻址 xdata unsigned char uart_cache[cache_max]; bdata unsigned char Flag; sbit Timer_start =Flag^0; //计时器,功能开关 sbit Message_switch =Flag^1; //打开・关闭 ,发送短信的功能 unsigned char Times=0; //定时计数器 unsigned char First_Int = 0; //串口数组字符“指针” unsigned char delay=0; //中断定时器,实际延时delay*50次 void SendData(unsigned char dat){ //底层驱动,发一个英文8位数据到串口SBUF ES=0; SBUF=dat; while(TI!=1); TI=0; ES=1; } void SendString(unsigned char *s){ //底层驱动,发英文字符到串口SBUF while(*s){SendData(*s++);} } void SendLR(void) { // 发送回车换行 SendString("\r\n"); } void DELAY_MS (unsigned int a){ // 毫秒级延时・12M@1T单片机 unsigned int i; while ( --a != 0 ) for (i=0;i<=600;i++); } void Beep_Ring(unsigned char ring_times){ //蜂鸣器提示音 if(ring_times==1){beep=0;DELAY_MS(300); beep=1;DELAY_MS(100);} if(ring_times==2){beep=0;DELAY_MS(150); beep=1;DELAY_MS(100);beep=0;DELAY_MS(150); beep=1;DELAY_MS(100);} if(ring_times==3){beep=0;DELAY_MS(100); beep=1;DELAY_MS(100);beep=0;DELAY_MS(100); beep=1;DELAY_MS(100);beep=0;DELAY_MS(100); beep=1;DELAY_MS(100);} } void Uart1Init(void) { //定时器1,[email protected] PCON &= 0x7F; //波特率不倍速 SCON = 0x50; //8位数据,可变波特率 AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T AUXR &= 0xFE; //串口1选择定时器1为波特率发生器 TMOD &= 0x0F; //清除定时器1模式位 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFD; //设定定时初值 TH1 = 0xFD; //设定定时器重装值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 ES=1; //开串口中断 } void Timer0Init(void) { //20毫秒@11.0592MHz AUXR &= 0x7F; //定时器0时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式,16位定时器,非自动重载模式 TL0 = 0x00; //设置定时器初值 TH0 = 0xB8; //设置定时器初值 TF0 = 0; //清TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } void CLR_Buf1(void){ unsigned int k; for(k=0;k<cache_max;k++){uart_cache[k] = 0;} //将缓存内容清零 First_Int = 0; //接收字符串的起始存储位置 DELAY_MS(50); //摸索才发现的等待缓存串口清空生效・坑死我了,哈哈~ //如果没有这个 DELAY_MS(50);这个缓存赋值为0,数值并不会立即生效,搞不明白,最好还是加上 } void Send_Command(unsigned char *command,unsigned char *ack,unsigned char wait_time){ unsigned char *pointer; pointer = command; //保存字符串command的首地址到c CLR_Buf1(); //清除串口缓存 while(1) { if(!strstr(uart_cache,ack)) { //查找需要应答的字符 if(Timer_start == 0){ command = pointer; //将字符串地址给b for (command; *command!='\0';command++){SendData(*command);} SendLR(); Times = 0; delay = wait_time; Timer_start = 1; // 开启定时器 } }else{ Timer_start = 0; //关闭定时器 break; } } CLR_Buf1(); //如果找到了匹配的字符串,清除串口缓存,不要干扰后面的程序 } void Wait_Register(void) { //等待模块注册成功 unsigned char i,k; i = 1; //循环标志位,用来从内层循环直接跳出 CLR_Buf1(); //清空串口数组缓存,免得带来干扰 while(i) { CLR_Buf1(); SendString("AT+CREG?");//查询模块网络注册状态 SendLR(); DELAY_MS(1000); for(k=0;k<cache_max;k++) { if(uart_cache[k] == ':') { if((uart_cache[k+4] == '1')||(uart_cache[k+4] == '5')){//表明网络注册成功 i = 0; //循环标志位,用来从内层循环for直接跳出到while外 CLR_Buf1(); } } } } } void Send_Message(unsigned char channel_number){ if(!Message_switch){ //判断是否允许发送短信,如果不允许发送短信,9声急促提示音,结束函数 Beep_Ring(3); Beep_Ring(3); Beep_Ring(3); return; } //给管理员1发送重启事件提示短信 Send_Command("AT+CSMP=17,167,2,25","OK",3); //设置文本模式参数 Send_Command("AT+CSCS=\"UCS2\"","OK",3); //设置字符集 Send_Command(Admin_phone_number1,">",3); //手机号码 有回车符 switch (channel_number){ case 1: Send_Command(message_content_01,">",3); break; case 2: Send_Command(message_content_02,">",3); break; case 3: Send_Command(message_content_03,">",3); break; case 4: Send_Command(message_content_04,">",3); break; case 5: Send_Command(message_content_05,">",3); break; case 6: Send_Command(message_content_06,">",3); break; case 7: Send_Command(message_content_07,">",3); break; case 8: Send_Command(message_content_08,">",3); break; case 9: Send_Command(message_content_09,">",3); break; case 10: Send_Command(message_content_10,">",3); break; default: Beep_Ring(1);Beep_Ring(1); } //警告 连续两声长音 SendData(0x1a); // 开始发送 不跟回车符 DELAY_MS(2000); //等待SIM900A模块的响应 Beep_Ring(2); //给管理员2发送重启事件提示短信 Send_Command("AT+CSMP=17,167,2,25","OK",3); Send_Command("AT+CSCS=\"UCS2\"","OK",3); Send_Command(Admin_phone_number2,">",3); switch (channel_number){ case 1: Send_Command(message_content_01,">",3); break; case 2: Send_Command(message_content_02,">",3); break; case 3: Send_Command(message_content_03,">",3); break; case 4: Send_Command(message_content_04,">",3); break; case 5: Send_Command(message_content_05,">",3); break; case 6: Send_Command(message_content_06,">",3); break; case 7: Send_Command(message_content_07,">",3); break; case 8: Send_Command(message_content_08,">",3); break; case 9: Send_Command(message_content_09,">",3); break; case 10: Send_Command(message_content_10,">",3); break; default: Beep_Ring(3); } SendData(0x1a); DELAY_MS(2000); Beep_Ring(3); } void SIM900aInit(void){ Send_Command("AT","OK",3); //波特率同步 // Send_Command("AT+CLIP=1","OK",3); //开启来电显示 Send_Command("AT+CSCLK=0","OK",3); //关闭SIM900A睡眠 Send_Command("AT+CMGD=1,4","OK",3); //删除卡上所有短信 Send_Command("ATE0","OK",3); //取消回显 Send_Command("AT+CNMI=3,2,0,0,0","OK",3); //新短信直接输出 Send_Command("AT+CMGF=1","OK",3); //TEXT模式 Send_Command("AT+CPMS=\"SM\",\"SM\",\"SM\"","OK",3); //所有操作都在SIM卡中进行 Wait_Register(); //查询等待模块注册成功 Beep_Ring(1); //SIM900A初始化完成提示音,滴~ } void Check_status(void){ //被中断函数调用,每20毫秒执行一次该函数 if(channel_01){ //如果channel_01引脚是低电平,进入秒计时器 channel_01_timer_ms++; if(channel_01_timer_ms>50){ // [email protected] channel_01_timer_sec++; channel_01_timer_ms = 0; } }else{channel_01_timer_ms = 0;}//如果channel_01引脚不是低电平,清空毫秒计时器 if(channel_02){ channel_02_timer_ms++; if(channel_02_timer_ms>50){ channel_02_timer_sec++; channel_02_timer_ms = 0; } }else{channel_02_timer_ms = 0;} if(channel_03){ channel_03_timer_ms++; if(channel_03_timer_ms>50){ channel_03_timer_sec++; channel_03_timer_ms = 0; } }else{channel_03_timer_ms = 0;} if(channel_04){ channel_04_timer_ms++; if(channel_04_timer_ms>50){ channel_04_timer_sec++; channel_04_timer_ms = 0; } }else{channel_04_timer_ms = 0;} if(channel_05){ channel_05_timer_ms++; if(channel_05_timer_ms>50){ channel_05_timer_sec++; channel_05_timer_ms = 0; } }else{channel_05_timer_ms = 0;} if(channel_06){ channel_06_timer_ms++; if(channel_06_timer_ms>50){ channel_06_timer_sec++; channel_06_timer_ms = 0; } }else{channel_06_timer_ms = 0;} if(channel_07){ channel_07_timer_ms++; if(channel_07_timer_ms>50){ channel_07_timer_sec++; channel_07_timer_ms = 0; } }else{channel_07_timer_ms = 0;} if(channel_08){ channel_08_timer_ms++; if(channel_08_timer_ms>50){ channel_08_timer_sec++; channel_08_timer_ms = 0; } }else{channel_08_timer_ms = 0;} if(channel_09){ channel_09_timer_ms++; if(channel_09_timer_ms>50){ channel_09_timer_sec++; channel_09_timer_ms = 0; } }else{channel_09_timer_ms = 0;} if(channel_10){ channel_10_timer_ms++; if(channel_10_timer_ms>50){ channel_10_timer_sec++; channel_10_timer_ms = 0; } }else{channel_10_timer_ms = 0;} } void Check_Crash(void) { //轮询查看是否死机 ,高电平有效 if(channel_01_timer_sec > crash_time){ //检测1号频道 低电平时间 channel_01_timer_sec=0; //清空死机时间长度标记 Send_Message(1); //调用发送短信 } if(channel_02_timer_sec > crash_time){ channel_02_timer_sec=0; Send_Message(2); } if(channel_03_timer_sec > crash_time){ channel_03_timer_sec=0; Send_Message(3); } if(channel_04_timer_sec > crash_time){ channel_04_timer_sec=0; Send_Message(4); } if(channel_05_timer_sec > crash_time){ channel_05_timer_sec=0; Send_Message(5); } if(channel_05_timer_sec > crash_time){ channel_05_timer_sec=0; Send_Message(5); } if(channel_06_timer_sec > crash_time){ channel_06_timer_sec=0; Send_Message(6); } if(channel_07_timer_sec > crash_time){ channel_07_timer_sec=0; Send_Message(7); } if(channel_08_timer_sec > crash_time){ channel_08_timer_sec=0; Send_Message(8); } if(channel_09_timer_sec > crash_time){ channel_09_timer_sec=0; Send_Message(9); } if(channel_10_timer_sec > crash_time){ channel_10_timer_sec=0; Send_Message(10); } } void Check_New_Message(void) { if(strstr(uart_cache,Grant_message)) { //若缓存字符串中含有Grant_message就表示 超级管理员发短信来了 DELAY_MS(300); //等待数据全部接收完成,1T单片机执行速度太快 if(strstr(uart_cache,Open_message)) { //匹配开启发送短信内容 Message_switch=1; //允许发送重启事件短信 Send_Command("AT+CSMP=17,167,2,25","OK",3); //设置文本模式参数 Send_Command("AT+CSCS=\"UCS2\"","OK",3); //设置字符集 Send_Command(Admin_phone_number1,">",3); //给Admin_phone_number1发送通知 Send_Command(Send_open_message,">",3); //已开启发送短信功能。 SendData(0x1a); // 开始发送 返回OK DELAY_MS(3000); Beep_Ring(3);Beep_Ring(3); //短信发送提示音,滴~滴~滴・滴~滴~滴~ } if(strstr(uart_cache,Shut_message)) { Message_switch=0; //不允许发送重启事件短信 Send_Command("AT+CSMP=17,167,2,25","OK",3); Send_Command("AT+CSCS=\"UCS2\"","OK",3); Send_Command(Admin_phone_number1,">",3); Send_Command(Send_shut_message,">",3); SendData(0x1a); DELAY_MS(3000); Beep_Ring(3);Beep_Ring(3); } CLR_Buf1(); // 清空SBUF缓存 } } //主函数 void main(void){ P0M1=0xff; //设定P0口为高阻,用来检测高低,模拟电平 P0M0=0x00; //设定P0口为高阻,用来检测高低,模拟电平 P2M1=0xff; //设定P2口为高阻,用来检测高低,模拟电平 P2M1=0x00; //设定P3口为高阻,用来检测高低,模拟电平 Timer0Init(); //初始化定时器0 Uart1Init(); //初始化串口9600波特率 SIM900aInit(); //初始化SIM900A模块 Message_switch=1;//默认打开发送短信功能 while(1){ Check_Crash(); //查询各个频道的引脚状态,判断是否死机 Check_New_Message(); //查询新的短信 } } //4级串口中断函数 void Uart1() interrupt 4{ uart_cache[First_Int] = SBUF; //将接收到的单个字符存到缓存中 First_Int++; //缓存指针向后移动 if(First_Int > cache_max){First_Int = 0;} //如果缓存满,将缓存指针指向缓存的首地址 RI = 0; //清除RI位 } //1级最高级别,定时器中断函数 void Timer0() interrupt 1{ //最高级别中断服务程序 [email protected] static unsigned char Time_count=0; //定时器计数器 static全局生命周期 TR0=0; //关定时器 TL0 = 0x00; //重设定时器初值 TH0 = 0xB8; //重设定时器初值 Time_count++; //每隔20毫秒进入中断,Time_count无条件自加运算 if(Time_count>=50){ Time_count = 0; runing_led=~runing_led; //SIM900A运行指示灯,1秒闪烁一次 } if(Timer_start) Times++; //如果收到允许定时,开始计时 if(Times > (50*delay)){ //如果Times 到达设定时间,50*delay就是秒数 Timer_start = 0; //定时结束,定时功能标记Timer_start一定为0 Times = 0; //完成定时,清空计数器 } Check_status(); //轮询监督死机函数 TR0=1; //开启定时器 } ------------------------------------------------------ /* 项目名称:监控机顶盒 是否死机了 日期:2016年01月17日 版本:4.0 变更说明: 1,获取电平持续时间,判断死机状态更科学 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 编码环境:GBK2312简体中文 μVision 版本:4.72.9.0 单片机:STC15f104W STC15F104W ,晶振设定12M 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 STC15F104W I/O 口工作类型设定 P3M1[5:0] P3M0[5:0] I/O工作模式 0 0 准双向 下拉20ma,上拉270μa 0 1 推挽模式(上拉20ma) 1 0 仅为输入(高阻状态) 1 1 开漏模式,内部上拉电阻断开 P3M1=0x00; //设定P3.3为推挽 P3M0=0x0f; //设定P3.3为推挽 线上环境的数值if(Time_sec > 180 ) 3分钟的死机状态监测 */ #include "STC15F104E.H" #define watiting 15 //关机,输出高电平时间长度 秒 不是很精确 sbit led1 = P3^1; //LM393 A输出,低电平为正常,高电平为异常 ,HDMI convert SDI 1灯熄灭LM393 A会有高电平 sbit led2 = P3^2; //LM393 B输出,低电平为正常,高电平为异常 ,HDMI convert SDI 2灯熄灭LM393 B会有高电平 sbit control = P3^4; //输出高电平给机顶盒的EL817会控制重启 unsigned int Time_20ms; unsigned int Time_sec; void sleep_ms(unsigned int a) { // 毫秒级延时函数 @12M 1T单片机 unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void sleep_sec(unsigned char time){ // 延时函数,秒 unsigned char num; for(num=0;num<time;num++){ sleep_ms(1000); } } void restart(void){ //高电平 有效 control=1; //推挽输出高电平给机顶盒的 sleep_sec(watiting);//关机watiting秒 control=0; //结束高电平,机顶盒开机 sleep_sec(watiting); } void Timer0Init(void) { //20毫秒@11.0592MHz AUXR &= 0x7F; //定时器0时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式,16位定时器,非自动重载模式 TL0 = 0x00; //设置定时器初值 TH0 = 0xB8; //设置定时器初值 TF0 = 0; //清TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } void main(){ control = 0; //监控端开机关机瞬间,不应该影响到机顶盒 P3M1=0x00; //设定P3.4为推挽 00000(bin) P3M0=0x10; //设定P3.4为推挽 10000(bin) Timer0Init(); while(1){ if(Time_sec > 180 ){ //判断死机状态的持续时间长度,应大于电视盒子初始化时间 单位:秒 Time_sec=0; //清空计数器 restart(); //重启机顶盒 } } } //1级最高级别,定时器中断函数 void Timer0() interrupt 1{ //最高级别中断服务程序 TR0=0; //关定时器 TL0 = 0x00; //重设定时器初值 TH0 = 0xB8; //重设定时器初值 if(led1 && led2) Time_20ms ++; //只有当两个led都输出高电平,才计入死机持续时间计算 else { //如果中途led1或led2电平突变为低电平,清空计数器 ,复位死机时间计算 Time_20ms=0; Time_sec=0; } if(Time_20ms > 50){ Time_20ms=0; Time_sec++; } TR0=1; //开定时器 } ----------------------------------------------------- /* 项目名称:机顶盒开机后,单片机固定频道(仅限用于华数机顶盒) 功能:电视盒子开机,80秒后自动锁定频道,完成后,蜂鸣器嘀的一声 日期:2016年01月15日 版本:4.0 更新说明: 1,取消right按键 ,用OK键代替 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 编码环境:GBK2312简体中文 μVision 版本:4.72.9.0 单片机型号:STC15f104W 烧录晶振选择:12M 单片机引脚说明 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 STC15F104W I/O 口工作类型设定 P3M1[5:0] P3M0[5:0] I/O工作模式 0 0 准双向 下拉20ma,上拉270μa 0 1 推挽模式(上拉20ma) 1 0 仅为输入(高阻状态) 1 1 开漏模式,内部上拉电阻断开 P3M1=0x00; //设定P3.3为推挽 P3M0=0x08; //设定P3.3为推挽 */ #include "STC15F104E.H" #define waiting 2000 // 按键超时时间设定,单位 毫秒 sbit key_menu = P3^0; //机顶盒的menu按键,发出低电平有效 sbit key_down = P3^1; //机顶盒的down按键,发出低电平有效 sbit key_ok = P3^2; //机顶盒的ok按键,发出低电平有效 sbit beep = P3^3; //蜂鸣器,发出低电平有效 void delay (unsigned int a) { // 毫秒级延时函数 @12M晶振 1T单片机 unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void menu(void){ //按一下menu键的操作 函数 key_menu=0; delay(500); key_menu=1; delay(waiting); } void down(unsigned char down_number){ //按多次down键的操作 函数 unsigned char i; for(i=0;i<down_number;i++){ key_down=0; delay(500); key_down=1; delay(waiting); } } void ok(void){ key_ok=0; delay(500); key_ok=1; delay(waiting); } void change_channel(unsigned char page,unsigned char number){ // 选择频道的函数 //page 选择频道所在的 第几页 1到21页可选 //number 选择频道所属page的number 1到9可选 menu(); down(2); ok(); down(9*(page-1)+number-1); ok(); } void beep_ring(void){ beep=0; delay(500); beep=1; } void initial (void){ // 开机初始化 unsigned char i; for(;i<70;i++){ // 等待机顶盒开机初始化,70秒,菜单消失,黑屏提示 无信号(无信号源时)。 delay(1000); } change_channel(1,9); //浙江卫视, 在第1页,第9个 //change_channel(3,3); //CCTV5 体育,在第3页,第3个 //change_channel(9,6); //CCTV14少儿,在第9页,第6个 //change_channel(5,4); //湖南卫视, 在第5页,第4个 //change_channel(3,5); //CCTV13新闻,在第3页,第5个 //change_channel(7,1); //安徽卫视, 在第7页,第1个 //change_channel(4,7); //东方卫视, 在第4页,第7个 //change_channel(3,8); //黑龙江卫视,在第3页,第8个 } void main(){ //主函数 initial(); //锁定频道 beep_ring(); //蜂鸣器提示音 while(1){ } } -----------------------------------------------------------------
3.0版本程序
/* 项目名称:机顶盒开机后,单片机固定频道(仅限用于华数机顶盒) 功能:电视盒子开机,80秒后自动锁定频道,完成后,蜂鸣器嘀的一声 日期:2016年01月15日 版本:3.0 更新说明: 1,取消right按键 ,用OK键代替 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 编码环境:GBK2312简体中文 μVision 版本:4.72.9.0 单片机型号:STC15f104W 烧录晶振选择:12M 单片机引脚说明 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 STC15F104W I/O 口工作类型设定 P3M1[5:0] P3M0[5:0] I/O工作模式 0 0 准双向 下拉20ma,上拉270μa 0 1 推挽模式(上拉20ma) 1 0 仅为输入(高阻状态) 1 1 开漏模式,内部上拉电阻断开 P3M1=0x00; //设定P3.3为推挽 P3M0=0x08; //设定P3.3为推挽 */ #include "STC15F104E.H" #define waiting 2000 // 按键超时时间设定,单位 毫秒 sbit key_menu = P3^0; //机顶盒的menu按键,发出低电平有效 sbit key_down = P3^1; //机顶盒的down按键,发出低电平有效 sbit key_ok = P3^2; //机顶盒的ok按键,发出低电平有效 sbit beep = P3^3; //蜂鸣器,发出低电平有效 void delay (unsigned int a) { // 毫秒级延时函数 @12M晶振 1T单片机 unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void menu(void){ //按一下menu键的操作 函数 key_menu=0; delay(500); key_menu=1; delay(waiting); } void down(unsigned char down_number){ //按多次down键的操作 函数 unsigned char i; for(i=0;i<down_number;i++){ key_down=0; delay(500); key_down=1; delay(waiting); } } void ok(void){ key_ok=0; delay(500); key_ok=1; delay(waiting); } void change_channel(unsigned char page,unsigned char number){ // 选择频道的函数 //page 选择频道所在的 第几页 1到21页可选 //number 选择频道所属page的number 1到9可选 menu(); down(2); ok(); down(9*(page-1)+number-1); ok(); } void beep_ring(void){ beep=0; delay(500); beep=1; } void initial (void){ // 开机初始化 unsigned char i; for(;i<70;i++){ // 等待机顶盒开机初始化,70秒,菜单消失,黑屏提示 无信号(无信号源时)。 delay(1000); } change_channel(1,9); //浙江卫视, 在第1页,第9个 //change_channel(3,3); //CCTV5 体育,在第3页,第3个 //change_channel(9,6); //CCTV14少儿,在第9页,第6个 //change_channel(5,4); //湖南卫视, 在第5页,第4个 //change_channel(3,5); //CCTV13新闻,在第3页,第5个 //change_channel(7,1); //安徽卫视, 在第7页,第1个 //change_channel(4,7); //东方卫视, 在第4页,第7个 //change_channel(3,8); //黑龙江卫视,在第3页,第8个 } void main(){ //主函数 initial(); //锁定频道 beep_ring(); //蜂鸣器提示音 while(1){ } } 编译结果 Build target 'Target 1' compiling 死机监控.C... linking... Program Size: data=13.0 xdata=0 code=209 creating hex file from "机顶盒"... "机顶盒" - 0 Error(s), 0 Warning(s). /* 项目名称:监控机顶盒 是否死机了 日期:2016年01月15日 版本:3.0 变更说明: 1,获取电平持续时间,判断死机状态更科学 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 编码环境:GBK2312简体中文 μVision 版本:4.72.9.0 单片机:STC15f104W STC15F104W ,晶振设定12M 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 STC15F104W I/O 口工作类型设定 P3M1[5:0] P3M0[5:0] I/O工作模式 0 0 准双向 下拉20ma,上拉270μa 0 1 推挽模式(上拉20ma) 1 0 仅为输入(高阻状态) 1 1 开漏模式,内部上拉电阻断开 P3M1=0x00; //设定P3.3为推挽 P3M0=0x0f; //设定P3.3为推挽 */ #include "STC15F104E.H" #define watiting 3 //关机时间长度 sbit led1 = P3^1; //LM393 A输出,低电平为正常,高电平为异常 ,HDMI convert SDI 1灯熄灭LM393 A会有高电平 sbit led2 = P3^2; //LM393 B输出,低电平为正常,高电平为异常 ,HDMI convert SDI 2灯熄灭LM393 B会有高电平 sbit control = P3^4; //输出高电平给机顶盒的EL817会控制重启 unsigned int Time_20ms; unsigned int Time_sec; void sleep_ms(unsigned int a) { // 毫秒级延时函数 @12M 1T单片机 unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void sleep_sec(unsigned char time){ // 延时函数,秒 unsigned char num; for(num=0;num<time;num++){ sleep_ms(1000); } } void restart(void){ //高电平 有效 control=1; //推挽输出高电平给机顶盒的 sleep_sec(watiting);//关机watiting秒 control=0; //结束高电平,机顶盒开机 sleep_sec(watiting); } void Timer0Init(void) { //20毫秒@11.0592MHz AUXR &= 0x7F; //定时器0时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式,16位定时器,非自动重载模式 TL0 = 0x00; //设置定时器初值 TH0 = 0xB8; //设置定时器初值 TF0 = 0; //清TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } void main(){ control = 0; //监控端开机关机瞬间,不应该影响到机顶盒 P3M1=0x00; //设定P3.4为推挽 00000(bin) P3M0=0x10; //设定P3.4为推挽 10000(bin) Timer0Init(); while(1){ if(Time_sec > 3 ){ //获取高电平持续时间的长度 Time_sec=0; //清空计数器 restart(); //重启机顶盒 } } } //1级最高级别,定时器中断函数 void Timer0() interrupt 1{ //最高级别中断服务程序 TR0=0; //关定时器 TL0 = 0x00; //重设定时器初值 TH0 = 0xB8; //重设定时器初值 if(led1 && led2) Time_20ms ++; //只有当两个led都输出高电平,才计入死机持续时间计算 else { //如果中途led1或led2电平突变为低电平,清空计数器 ,复位死机时间计算 Time_20ms=0; Time_sec=0; } if(Time_20ms > 50){ Time_20ms=0; Time_sec++; } TR0=1; //开定时器 } 编译结果 Build target 'Target 1' compiling 死机监控.C... linking... Program Size: data=13.0 xdata=0 code=209 creating hex file from "机顶盒"... "机顶盒" - 0 Error(s), 0 Warning(s).
2.0版本程序
/* 项目名称:机顶盒开机后,单片机固定频道(仅限用于华数机顶盒) 功能:电视盒子开机,70秒后自动锁定频道,完成后,蜂鸣器嘀的一声 日期:2016年01月10日 版本:2.0 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 编码环境:GBK2312简体中文 μVision 版本:4.72.9.0 单片机:STC15f104W STC15F104W ,晶振设定12M 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 STC15F104W I/O 口工作类型设定 P3M1[5:0] P3M0[5:0] I/O工作模式 0 0 准双向 下拉20ma,上拉270μa 0 1 推挽模式(上拉20ma) 1 0 仅为输入(高阻状态) 1 1 开漏模式,内部上拉电阻断开 P3M1=0x00; //设定P3.3为推挽 P3M0=0x08; //设定P3.3为推挽 */ #include "reg51.h" #define waiting 2000 sbit key_menu = P3^0; //机顶盒的menu按键,发出低电平有效 sbit key_down = P3^1; //机顶盒的down按键,发出低电平有效 sbit key_right = P3^2; //机顶盒的right按键,发出低电平有效 sbit key_ok = P3^3; //机顶盒的ok按键,发出低电平有效 sbit beep = P3^4; //蜂鸣器,发出低电平有效 void delay (unsigned int a) { // 毫秒级延时函数 unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void menu(void){ //按一下menu键的操作 函数 key_menu=0; delay(500); key_menu=1; delay(waiting); } void down(unsigned char down_number){ //按一下down键的操作 函数 unsigned char i; for(i=0;i<down_number;i++){ key_down=0; delay(500); key_down=1; delay(waiting); } } void right(void){ //按一下rigth键的操作 函数 key_right=0; delay(500); key_right=1; delay(waiting); } void ok(void){ key_ok=0; delay(500); key_ok=1; delay(waiting); } void change_channel(unsigned char page,unsigned char number){ // 选择频道的函数 //page 选择频道所在的 第几页 1到21页可选 //number 选择频道所属page的number 1到9可选 menu(); down(2); right(); down(9*(page-1)+number-1); ok(); } void beep_ring(void){ beep=0; delay(1000); beep=1; } void initial (void){ // 开机初始化 unsigned char i; for(;i<70;i++){ // 等待机顶盒开机初始化,70秒,菜单消失,黑屏提示 无信号(无信号源时)。 delay(1000); } change_channel(1,9); //浙江卫视,在第1页,第9个 //change_channel(3,5); //中央新闻,在第3页,第5个 //change_channel(1,1); //华数剧场,在第1页,第1个 //change_channel(1,1); //华数剧场,在第1页,第1个 //change_channel(21,1); //求索旅行,在第21页,第2个 } void main(){ //主函数 initial(); beep_ring(); while(1){ } } /* 项目名称:监控机顶盒 是否死机了 日期:2016年01月10日 版本:2.0 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 编码环境:GBK2312简体中文 μVision 版本:4.72.9.0 单片机:STC15f104W STC15F104W ,晶振设定12M 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 STC15F104W I/O 口工作类型设定 P3M1[5:0] P3M0[5:0] I/O工作模式 0 0 准双向 下拉20ma,上拉270μa 0 1 推挽模式(上拉20ma) 1 0 仅为输入(高阻状态) 1 1 开漏模式,内部上拉电阻断开 P3M1=0x00; //设定P3.3为推挽 P3M0=0x08; //设定P3.3为推挽 */ #include "STC15F104E.H" sbit led1 = P3^5; //HDMI convert SDI 1号灯 sbit led2 = P3^4; //HDMI convert SDI 2号灯 sbit control = P3^3; //继电器上电,机顶盒重启 void sleep_ms(unsigned int a) { // 毫秒级延时函数 @12M unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void sleep_sec(unsigned char time){ // 延时函数,秒 unsigned char num; for(num=0;num<time;num++){ sleep_ms(1000); } } void restart(void){ //P沟道场效应管,G极高电平,再低电平 control=0; //P沟道场效应管,G极高电平,机顶盒断电 sleep_sec(10); //机顶盒断电10秒 control=1; //P沟道场效应管,G极低电平,机顶盒开机 } void main(){ while(1){ if(led1&&led2){ //如果HDMI convert SDI两个灯都熄灭,LM393输出高电平 sleep_sec(180); //3分钟再看看 if(led1&&led2){ //如果HDMI convert SDI两个灯还是熄灭状态,LM393输出高电平 restart(); //重启机顶盒 } } } }
1.0版本程序
/* 项目名称:机顶盒开机后,单片机固定频道(仅限用于华数机顶盒) 日期:2016年01月08日 版本:1.0 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 单片机:STC15f104W STC 15F104W ,晶振12M 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 */ #include "reg51.h" sbit key_menu = P3^0; //机顶盒的menu按键,发出低电平有效 sbit key_down = P3^1; //机顶盒的down按键,发出低电平有效 sbit key_right = P3^2; //机顶盒的right按键,发出低电平有效 sbit key_ok = P3^3; //机顶盒的ok按键,发出低电平有效 void delay (unsigned int a) { // 毫秒级延时函数 unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void menu(void){ //按一下menu键的操作 函数 key_menu=0; delay(500); key_menu=1; delay(500); } void down(unsigned char down_number){ //按一下down键的操作 函数 unsigned char i; for(i=0;i<down_number;i++){ key_down=0; delay(500); key_down=1; delay(500); } } void right(void){ //按一下rigth键的操作 函数 key_right=0; delay(500); key_right=1; delay(500); } void ok(void){ key_ok=0; delay(500); key_ok=1; delay(500); } void change_channel(unsigned char page,unsigned char number){ // 选择频道的函数 //page 选择频道所在的 第几页 1到21页可选 //number 选择频道所属page的number 1到9可选 menu(); down(2); right(); down(9*(page-1)+number-1); ok(); } void initial (void){ // 开机初始化 unsigned char i; for(;i<60;i++){ // 等待机顶盒开机初始化,70秒,菜单消失,黑屏提示 无信号(无信号源时)。 delay(1000); } change_channel(1,9); //浙江卫视,在第1页,第9个 //change_channel(3,5); //中央新闻,在第3页,第5个 //change_channel(1,1); //华数剧场,在第1页,第1个 //change_channel(1,1); //华数剧场,在第1页,第1个 //change_channel(21,1); //求索旅行,在第21页,第2个 } void main(){ //主函数 initial(); while(1){ } } /* 项目名称:监控机顶盒 是否死机了 日期:2016年01月08日 版本:1.0 作者:chunli 博客:990487026.blog.51cto.com 邮箱:[email protected] 单片机:STC15f104W STC 15F104W ,晶振12M 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 */ #include "reg51.h" sbit led1 = P3^0; //HDMI convert SDI 1号灯 sbit led2 = P3^1; //HDMI convert SDI 2号灯 sbit control = P3^2; //继电器上电,机顶盒重启 void delay (unsigned int a) { // 毫秒级延时函数 @12M unsigned int i; while ( --a != 0 ) { for (i=0;i<=600;i++); } } void sleep(unsigned char time){ // 延时函数,秒 unsigned char num; for(num=0;num<time;num++){ delay(1000); } } void restart(void){ //继电器断开,再上电 control=0; //继电器上电,继电器松开,机顶盒断电 sleep(10); //机顶盒断电10秒 control=1; //继电器断电,继电器吸合,机顶盒开机 } void main(){ while(1){ if((led1==0)&&(led2==0)){ //如果HDMI convert SDI两个灯都熄灭 sleep(120); //2分钟再看看 if((led1==0)&&(led2==0)){ //如果HDMI convert SDI两个灯还是熄灭状态 restart(); //重启机顶盒 } } } }
本文出自 “魂斗罗” 博客,谢绝转载!