打印

多功能定时电路

[复制链接]
3563|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gurong60|  楼主 | 2008-12-1 19:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
 经过是几星期的努力终于做好一款实用的电路 
      电路功能:2组闹钟,2组电脑自动开机,5组用电器定时(电饭锅,电风扇等) 
      用途介绍:闹钟就不用说 
                  电脑的自动开机就是在你设置的时间到时电路板上有个继电器来代替电脑的开机键,为什么要设置这个功能呢?(嗨,人懒了,开机键都懒得去按)特别是上班的人来说把电脑开机挡闹钟很不错,因为电脑开机时可以自启动播放软件,比如千千静听,就我自己来说我每天都是八点上班,设置开机时间在7:20,电脑自动开机后就播放音乐(忘记说了千千静听里有自动关机的设置,我设8:00)然后我去上班电脑就自动关闭,是不是很好(不过这样浪费电) 
                  定时用电器:之前我做过这样的定时,我在盐城上班时就用之前的那个,当时是用电饭锅煮早饭,那时7.30上班,等我早上起来时就闻到米香了而且吃的时候正好是不冷不热的(准备工作是要有的,晚上必须把米水放入锅里,并且设置好时间,要不然的话,等你上班了早饭还每好,那就不行了.)现在这个改进的好处是不用天天设置时间,还带一组50%占空比的定时(专门为了煮粥用的),不用的时间可以把电源拔了,下次再用就不再设置时间 
      主要元件:STC12C2052(单片机,由于芯片的程序存储容量问题就没有加红外线遥控电脑开关机),74HC164(移位寄存器),74HC138(3-8译器),MO3041(光电耦合可控硅),BTA08(双向可控硅8A),DS1302(时钟芯片) 

相关帖子

沙发
gurong60|  楼主 | 2008-12-1 19:43 | 只看该作者

源程序

#include"STC89C51RC_RD_PLUS.H"
#define uchar unsigned char
#define uint unsigned int
uchar code TAB[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar ucCurtime[7];
uchar hour[9],min[9]; 
uchar *pSecDa;
uint KeyValue,x=0,y,c,d,f;
uchar time1,time2,time3,a,b;
bit e,h=1;

/*********************************************************************
* 实时时钟模块 时钟芯片型号:DS1302 *
*********************************************************************/
sbit T_CLK = P3^4; /*实时时钟时钟线引脚 */
sbit T_IO = P3^3; /*实时时钟数据线引脚 */
sbit T_RST = P3^2; /*实时时钟复位线引脚 */
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit rxd=P3^0;
sbit txd=P3^1;
sbit s1=P1^0;
sbit s2=P1^1;
sbit s3=P1^2;
sbit s4=P1^3;
sbit s5=P1^4;
sbit s6=P1^5;
sbit s7=P1^6;
sbit s17=P1^7;
sbit s37=P3^7;
sbit s35=P3^5;

/******************************************************************** 
*
* 名称: v_RTInputByte
* 说明: 
* 功能: 往DS1302写入1Byte数据
* 调用:
* 输入: ucDa 写入的数据 
* 返回值: 无
***********************************************************************/
void v_RTInputByte(uchar ucDa) 

uchar i;
ACC = ucDa;


for(i=8; i>0; i--)
{

T_IO = ACC0; /*相当于汇编中的 RRC */
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1; 

}
/******************************************************************** 
*
* 名称: uchar uc_RTOutputByte
* 说明: 
* 功能: 从DS1302读取1Byte数据
* 调用: 
* 输入: 
* 返回值: ACC
***********************************************************************/
uchar uc_RTOutputByte(void) 

uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; /*相当于汇编中的 RRC */
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;

return(ACC); 
}
/******************************************************************** 
*
* 名称: v_W1302
* 说明: 先写地址,后写命令/数据
* 功能: 往DS1302写入数据
* 调用: v_RTInputByte() 
* 输入: ucAddr: DS1302地址, ucDa: 要写的数据
* 返回值: 无
***********************************************************************/
void v_W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); /* 地址,命令 */
v_RTInputByte(ucDa); /* 写1Byte数据*/
T_CLK = 1;
T_RST =0;

/******************************************************************** 
*
* 名称: uc_R1302
* 说明: 先写地址,后读命令/数据
* 功能: 读取DS1302某地址的数据
* 调用: v_RTInputByte() , uc_RTOutputByte()
* 输入: ucAddr: DS1302地址
* 返回值: ucDa :读取的数据
***********************************************************************/
uchar uc_R1302(uchar ucAddr)
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); /* 地址,命令 */
ucDa = uc_RTOutputByte(); /* 读1Byte数据 */
T_CLK = 1;
T_RST =0;
return(ucDa);
}

/******************************************************************** 
*
* 名称: v_Get1302
* 说明: 
* 功能: 读取DS1302当前时间
* 调用: uc_R1302() 
* 输入: ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年 
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值: 无
***********************************************************************/
void v_Get1302() 
{
uchar i;
uchar ucAddr = 0x81;
for (i=0;i<7;i++)
{
ucCurtime = uc_R1302(ucAddr);/*格式为: 秒 分 时 日 月 
星期 年 */
ucAddr += 2;
}
}

void delay(int a) //延时
{int i,j;
for(j=0;j<a;j++)
for(i=0;i<1;i++)v_Get1302();
}
void xianshi() //....数码管显示子程序....
{
if(x!=0&e==0)SBUF=0XFF;       
else SBUF=TAB[time1/16]; //
while(!TI) ;
TI=0;
s5=1;s6=0;s7=1;
delay(4);
if(x!=0&e==0)SBUF=0XFF;       
else SBUF=(TAB[time1%16])&0X7F; //
while(!TI) ;
TI=0;
s5=1;s6=0;s7=0;
delay(4); 
if(x!=0&e==0)SBUF=0XFF;       
else SBUF=TAB[time3/16];
while(!TI) ;
TI=0;
s5=0;s6=1;s7=1;
delay(4);
if(x!=0&e==0)SBUF=0XFF;       
else SBUF=(TAB[time3%16])&0X7F;
while(!TI) ;
TI=0;
s5=0;s6=1;s7=0;
delay(4); 
if(x!=0&e==0)SBUF=0XFF;       
else SBUF=TAB[time2/16]; //
while(!TI) ;
TI=0;
s5=0;s6=0;s7=1;
delay(4);
if(x!=0&e==0)SBUF=0XFF;       
else SBUF=TAB[time2%16];
while(!TI) ;
TI=0;
s5=0;s6=0;s7=0;
delay(4);
}
/****************以下为EPPROM读写相关函数*******************************/
/*以下为EPPROM保护,每次操作后更改指令值,使EPPROM免于被误操作*/
void EPPROM_Protect()
{
   ISP_CONTR=0x00;   //更改指令值,防止出现误操作
ISP_CMD=0x00;
ISP_TRIG=0x00;
ISP_ADDRH=0x00;
ISP_ADDRL=0x00;
}

/*以下为读入指令,入口参数为要读的地址(16位),返回内容(8位)*/
uchar EEPROM_Read(uint Addr)
{                 
ISP_ADDRH=Addr/0x100;   //送地址
ISP_ADDRL=Addr%0x100;
ISP_CONTR=0x83;   //控制字节
ISP_CMD=0x01;   //读命令
ISP_TRIG=0x46;   //触发
ISP_TRIG=0xB9;
EPPROM_Protect(); //更改相关数值,防止误操作 
return(ISP_DATA); //返回读出的值 
}

/*以下为扇区擦除指令,入口参数为扇区首地址 */
void EEPROM_Erase(uint Addr) 
{
ISP_ADDRH=Addr/0x100;   //待写入扇区首地址
ISP_ADDRL=0x00;
ISP_CONTR=0x83;
ISP_CMD=0x03;   //扇区擦除指令
ISP_TRIG=0x46;   //触发,将擦除整个扇区
ISP_TRIG=0xB9;
EPPROM_Protect(); //更改相关数值,防止误操作 
}

/*以下为写入指令,入口参数为写入的地址(16位)和内容(8位),每次要写入的位置*/
void EEPROM_Write(uint Addr,uchar Data)
{
ISP_DATA=Data; //待写入值
ISP_ADDRH=Addr/0x100;   //待写入扇区首地址
ISP_ADDRL=Addr%0x100;
ISP_CONTR=0x83;
ISP_CMD=0x02;   //写入指令
ISP_TRIG=0x46;   //触发,数据写入
ISP_TRIG=0xB9;
EPPROM_Protect(); //更改相关数值,防止误操作 
}

/**********************数据存储与读取******************************/
void DatSave()


    EEPROM_Erase(0x1000);
    EEPROM_Write(0x1000,hour[1]);   
    EEPROM_Write(0x1001,min[1]);
    EEPROM_Write(0x1002,hour[2]);   
    EEPROM_Write(0x1003,min[2]);
    EEPROM_Write(0x1004,hour[3]);   
    EEPROM_Write(0x1005,min[3]);
    EEPROM_Write(0x1006,hour[4]);   
    EEPROM_Write(0x1007,min[4]);
EEPROM_Write(0x1008,hour[5]);   
    EEPROM_Write(0x1009,min[5]);
EEPROM_Write(0x100a,hour[6]);   
    EEPROM_Write(0x100b,min[6]);
EEPROM_Write(0x100c,hour[7]);   
    EEPROM_Write(0x100d,min[7]);
EEPROM_Write(0x100e,hour[8]);   
    EEPROM_Write(0x100f,min[8]);
EEPROM_Write(0x1010,hour[9]);   
    EEPROM_Write(0x1011,min[9]); 

   

void DatLoad()
{


     hour[1]=EEPROM_Read(0x1000); 
     min[1]=EEPROM_Read(0x1001);
hour[2]=EEPROM_Read(0x1002); 
     min[2]=EEPROM_Read(0x1003);
hour[3]=EEPROM_Read(0x1004); 
     min[3]=EEPROM_Read(0x1005);
hour[4]=EEPROM_Read(0x1006); 
     min[4]=EEPROM_Read(0x1007);
hour[5]=EEPROM_Read(0x1008); 
     min[5]=EEPROM_Read(0x1009);
hour[6]=EEPROM_Read(0x100a); 
     min[6]=EEPROM_Read(0x100b);
hour[7]=EEPROM_Read(0x100c); 
     min[7]=EEPROM_Read(0x100d);
hour[8]=EEPROM_Read(0x100e); 
     min[8]=EEPROM_Read(0x100f);
hour[9]=EEPROM_Read(0x1010); 
     min[9]=EEPROM_Read(0x1011);
     

}
void anjiansm()
{
    if(s1&s2&s3&s4){ KeyValue=0;return;}
   delay(16);
     if(!s1)
     {
     while(!s1){xianshi();}; 
     KeyValue=1;
     return;
     }
   if(!s2)
     {
     while(!s2){xianshi();};
     KeyValue=2;
     return;
     }
   if(!s3)
     {
     while(!s3){xianshi();}; 
     KeyValue=3;
     return;
     }
   if(!s4)
     {
     while(!s4){xianshi();};
     KeyValue=4;
     return;
     }
}
void anjiancl()        //按键处理子程序
{
    switch (KeyValue)
   {
   case 1: x++;if(x==3){x=0;
              v_W1302(0x8e,0x00); //写入允许    
                    v_W1302(0x84,a);
           v_W1302(0x82,b);
        v_W1302(0x8a,f); 
         v_W1302(0x80,0x7f&ucCurtime[0]);
                          v_W1302(0x8e,0x80);
        c=1;
         } 
       if(x==2){a=ucCurtime[2] ;
            b=ucCurtime[1] ;
           f=ucCurtime[5] ; }  
    break;
   case 2:
         if(x==1){
                   hour[c]++; 
       if((hour[c]|0xf0)==0xfa)hour[c]=(hour[c]+0x10)&0xf0;
       if(hour[c]==0x24)hour[c]=0xff;
                  }
       if(x==2) {
                a++;
                if((a|0xf0)==0xfa)a=(a+0x10)&0xf0;
                if(a==0x24)a=0; 
                }        
    break;
   case 3: 
         if(x==1){
                   min[c]++;
       if((min[c]|0xf0)==0xfa)min[c]=(min[c]+0x10)&0xf0;
       if(min[c]==0x60)min[c]=0x00;
       }
         if(x==2){
               b++;
                        if((b|0xf0)==0xfa)b=(b+0x10)&0xf0;
               if(b==0x60)b=0; 
       v_W1302(0x8e,0x00);
       v_W1302(0x80,0x80);
                      v_W1302(0x8e,0x80);
       }
    
    break;
   case 4:if(x==0) h=~h;
         if(x==1){
                                
                              c++; if(c==10){c=1; DatSave();}
                              
       }
         if(x==2){ f++;if(f==8)f=1;}
    break;
   default:
   if(x==1){time3=hour[c];
         time1=c;
         time2=min[c];}
     if(x==0){ if(h==0){ 
                      time1=ucCurtime[5];
        time2=0;
        time3=0; 
                     }          
                       else{
             time1=ucCurtime[2] ;
                        time3=ucCurtime[1] ;
                        time2=ucCurtime[0] ;
                           }
     }
   if(x==2) {
          time1=a ;
                        time3=b ;
                        time2=f ;
            }
    break;
    }
}
void shaomiao()
{
for(c=2;c<10;c++)
   {
    if(hour[c]==ucCurtime[2]&&min[c]==ucCurtime[1]){y=c;return;}   
       }
c=1;
}
void dingshi()
{
    int z,l=1;
    switch (y)
{
   case 1:if(ucCurtime[0]%5==0){     //闹钟定时
         s17=0;
      for(z=0;z<25;z++)xianshi();
      s17=1;
      for(z=0;z<75;z++)xianshi();}
      break;
   case 2:if(ucCurtime[0]%5==0){    //闹钟定时
         s17=0;
      for(z=0;z<25;z++)xianshi();
      s37=1;
      for(z=0;z<75;z++)xianshi();}
      break;
   case 3:if(ucCurtime[0]==0x01)      //1路电脑开机定时处理
         {s37=0;
         for(z=0;z<25;z++)xianshi();
      s37=1;
      for(z=0;z<75;z++)xianshi();}
      y=0;
      break;
   case 4:if(ucCurtime[0]==0x01)    //2路电脑开机定时处理
         {s37=0;
         for(z=0;z<25;z++)xianshi();
      s37=1;
      for(z=0;z<75;z++)xianshi();}
      y=0;
      break;
   case 5:s35=0;        //用电器定时开
      break;
     case 6:if(ucCurtime[0]==0x00)s35=0;   //用电器定时开(一分钟内有30秒是开)
         if(ucCurtime[0]==0x30)s35=1;
      break;
   case 7:s35=1;        //定时关
         break;
   case 8:s35=0;        //用电器定时开
      break;
     case 9:s35=1;        //用电器定时关
      break;
   default:s35=1;s37=1;s17=1;
     break;
}
}

void Timer0() interrupt 1 //计时中断子函数,调节闪烁
{
    d++;      //中断一次加1
if(d>2)   
   {
   d=0;
   e=~e; 
   }
}
void main()

   

c=1;

    TH0=0x3c;          //设定中断初始值
TL0=0xb0;
TMOD=0x01;
EA=1;
TR0=1;
ET0=1;
    v_W1302(0x8e,0x00); //写入允许
v_W1302(0x90,0x05); //涓流充电
v_W1302(0x8e,0x80);
v_Get1302();     
    while(1)
{
     anjiansm();
     anjiancl(); 
     xianshi();
   if(x==0)     //在未设置完时不扫描定时设置
   {
      shaomiao();
      dingshi();
    DatLoad();
   }

}
}

使用特权

评论回复
板凳
ZGL3314| | 2011-1-24 16:48 | 只看该作者
顶一个

使用特权

评论回复
地板
jc981| | 2011-1-25 16:20 | 只看该作者
有空玩玩可以的,要是能把红外控制加上就更完美了。搞个智能控制器,专门控制家电设备,呵呵。

使用特权

评论回复
5
奇兵| | 2011-1-25 18:35 | 只看该作者
图呢!:dizzy:

使用特权

评论回复
6
VMP| | 2011-1-27 12:21 | 只看该作者
智能控制,不错的创意。
有没有做一些语音识别控制系统,比如:说电视开:那TV打开;电脑开:那PC打开;煮饭:电饭锅打开的呀,呵呵!!~~~

使用特权

评论回复
7
lifengjian0306| | 2011-2-24 21:21 | 只看该作者
我和楼主一样早就有这种想法了,就是差个时钟芯片

使用特权

评论回复
8
liuxiaofen1952| | 2011-4-17 19:37 | 只看该作者
可用浯言芯片控制

使用特权

评论回复
9
仙人球W| | 2014-11-1 17:16 | 只看该作者
我正好有一块无差别语音识别芯片  哈哈

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

179

主题

1307

帖子

4

粉丝