程序版本排序说明
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/
邮箱:linux_lcl@163.com
编码环境: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,9600bps@11.0592MHz
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){ // 20MS@11.0592
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{ //最高级别中断服务程序 20MS@11.0592
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
邮箱:linux_lcl@163.com
编码环境: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
邮箱:linux_lcl@163.com
编码环境: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
邮箱:linux_lcl@163.com
编码环境: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
邮箱:linux_lcl@163.com
编码环境: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
邮箱:linux_lcl@163.com
编码环境: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
邮箱:linux_lcl@163.com
编码环境: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
邮箱:linux_lcl@163.com
单片机: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
邮箱:linux_lcl@163.com
单片机: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(); //重启机顶盒
}
}
}
}