微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 写代码累了DIY遥控时钟掉电可走两年1602+1302+C52

写代码累了DIY遥控时钟掉电可走两年1602+1302+C52

时间:10-02 整理:3721RD 点击:
经常写代码太累太没趣了,DIY遥控时钟玩玩,还别说一动起手来才知道模电没学好。在调试过程中还发现比遥控更牛B的功能,小手一模到屏的数据线还会调时。哈哈能到这就是传说中的触屏功能?可用在这里有点浪费啊,费了大半天原来是没上拉受干拢了。时钟掉电可走两年1602+1302+C52。用着自己造的东东就是爽啊,下次想DIY手机(呵呵技术难达到)           牛人多的是在这里本人只是想写点东东与大家交流下,分享DIY的乐趣,以及激励学习的热情。以下是时钟源程序(程序写的啰嗦别笑)

           #include<reg52.h>
//寄存器宏定义
#define W_SECOND    0x80
#define W_MINUTE    0x82
#define W_HOUR      0x84
#define R_SECOND    0x81
#define R_MINUTE    0x83
#define R_HOUR      0x85
#define W_PROTECT   0x8E
#define R_DAY       0x87
#define R_MONTH     0x89
#define R_YEAR      0x8D
#define W_YEAR      0x8C
#define W_MONTH     0x88
#define W_DAY       0x86
#define uchar unsigned char
#define uint  unsigned int
#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0替换
#define wei      P2
sbit RS=P2^6;
sbit RW=P2^5;
sbit PSB=P1^2;
sbit EN=P2^4;
//位寻址寄存器宏定义
sbit ACC_7=ACC^7;
sbit SCLK=P2^1;
sbit DIO=P2^2;
sbit CE=P2^3;
sbit IR=P3^2;  //红外接口标志
sbit BUZZ=P3^4;
//sbit SZEN=CH;
uchar GUBIAO,jishu,busy;
char dat1,flag,flag1,miao,fen,shi,r,yue,flag2,flag3,h;
uchar code addr_tab[]={
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,//第一行汉字位置
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,//第二行汉字位置
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,//第三行汉字位置
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,//第四行汉字位置
};
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
unsigned char IRcord[4];
unsigned char irdata[33];
/*------------------------------------------------
                  函数声明
------------------------------------------------*/
void lcd_wcmd(uchar cmd);
void lcd_wdat(uchar dat);
void  dipl(unsigned char a);
void W1302(unsigned char addr,dat) ;
void Ir_work(void);
void Ircordpro(void);
void Delay(unsigned int t);
void queding();
void lcd_rdat();
void delay(uchar z);
void gonnen();
void taojia();
void taojian();
unsigned char  R1302(unsigned char addr);
void delay_1ms(void);
/*------------------------------------------------
                全局变量声明
------------------------------------------------*/
unsigned char  irtime;//红外用全局变量
unsigned char  a,b,m,n;
bit irpro_ok,irok;
/*------------------------------------------------
                  定时器0中断处理
------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
  irtime++;  //用于计数2个下降沿之间的时间
}
/*------------------------------------------------
                  外部中断0中断处理
------------------------------------------------*/
void EX0_ISR (void) interrupt 0 //外部中断0服务函数
{
  static unsigned char  i;             //接收红外信号处理
  static bit startflag;                //是否开始处理标志位
if(startflag)                        
   {
    if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
                        i=0;
      irdata=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
      irtime=0;
      i++;
       if(i==33)
         {
       irok=1;
     i=0;
      }
          }
    else
  {
  irtime=0;
  startflag=1;
  }
}
/*------------------------------------------------
                定时器0初始化
------------------------------------------------*/
void TIM0init(void)//定时器0初始化
{
  TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
  TH0=0x00; //重载值
  TL0=0x00; //初始化值
  ET0=1;    //开中断
  TR0=1;   
}
/*------------------------------------------------
                  外部中断0初始化
------------------------------------------------*/
void EX0init(void)
{
IT0 = 1;   //指定外部中断0下降沿触发,INT0 (P3.2)
EX0 = 1;   //使能外部中断
EA = 1;    //开总中断
}
//*************************************************************
//*************************************************************
    //调时间功能选择
//*************************************************************
//*************************************************************
void gonnen()    //功能键函数
{
   unsigned char f,g;
   R1302(R_MINUTE);
   if(flag2==0)    //中断功能函数运行后读DS1302数标志
   {
   fen=dat1;
   R1302(R_HOUR);
   shi=dat1;
   R1302(R_DAY);
   r=dat1;
   R1302(R_MONTH);
   yue=dat1;
   flag2=1;
   }
   W1302(W_PROTECT,0X00); //
   W1302(W_SECOND,0X80);
   W1302(W_PROTECT,0X80);
   flag=1;   
   flag1=1;    //中断功能函数运行后调时间函数进入标志
   flag3=1;
   GUBIAO++;  //屏幕光标
  if(GUBIAO==1)   //光标位置选择
   {
   lcd_wcmd(0x80+0x4a);
   lcd_wcmd(0x0F);
   }
  if(GUBIAO==2)
   {
   lcd_wcmd(0x80+0x47);
   lcd_wcmd(0x0F);
   }
  if(GUBIAO==3)
   {
   lcd_wcmd(0x80+0x44);
   lcd_wcmd(0x0F);
   }
  if(GUBIAO==4)
   {
   lcd_wcmd(0x80+0x0b);
   lcd_wcmd(0x0F);
   }
  if(GUBIAO==5)
   {
   lcd_wcmd(0x80+0x08);
   lcd_wcmd(0x0F);
   }
  if(GUBIAO==6)  //功能键函数退出前处理各标志和对DS1302写入数据
   {
    GUBIAO=0;
flag=0;   //中断功能函数退出后主函数恢复运行标志
flag1=0;  //中断功能函数退出后调时间函数不能进入标志
flag2=0;
flag3=0;  
lcd_wcmd(0x0c);
    f=fen/10;  //十进制转十六进制准备给DS1302送数据
    g=fen%10;  //
    fen=f*16+g;  //
    f=shi/10;  //
    g=shi%10;  //
    shi=f*16+g;  //
    f=r/10;   //
    g=r%10;   //
    r=f*16+g;  //
    f=yue/10;  //
    g=yue%10;  //
    yue=f*16+g;    //
W1302(W_PROTECT,0X00);  //把转好的十六进制数送给DS1302
W1302(W_MINUTE,fen);
W1302(W_HOUR,shi);
W1302(W_DAY,r);
W1302(W_MONTH,yue);
W1302(W_SECOND,0X55);
    W1302(W_PROTECT,0X80);
   }
}
//*************************************************************
//*************************************************************
//                    调时间加加        
//*************************************************************
//*************************************************************
void taojia()   
{
   if(flag1==1)      
    {
  if(GUBIAO==2)     //分
   {
   fen++;
   if(fen>=60)
   fen=0;
   lcd_wcmd(0x80+0x47);
   dipl(fen);
   lcd_wcmd(0x80+0x47);
   
   }
  if(GUBIAO==3)    //时
   {
   shi++;
   if(shi>=24)
   shi=0;
   lcd_wcmd(0x80+0x44);
   dipl(shi);
   lcd_wcmd(0x80+0x44);
   
   }
  if(GUBIAO==4)    //日
   {
   r++;
   if(r>=32)
   r=1;
   lcd_wcmd(0x80+0x0b);
   dipl(r);
   lcd_wcmd(0x80+0x0b);
   
   }
  if(GUBIAO==5)    //月
   {
   yue++;
   if(yue>=13)
   yue=1;
   lcd_wcmd(0x80+0x08);
   dipl(yue);
   lcd_wcmd(0x80+0x08);
   }
}
}
//*************************************************************
//*************************************************************
//                    调时间减减        
//*************************************************************
//*************************************************************
void taojian()   
{
   if(flag3==1)      
    {
  if(GUBIAO==2)     //分
   {
   fen--;
   if(fen<0)
   fen=59;
   lcd_wcmd(0x80+0x47);
   dipl(fen);
   lcd_wcmd(0x80+0x47);
   
   }
  if(GUBIAO==3)    //时
   {
   shi--;
   if(shi<0)
   shi=23;
   lcd_wcmd(0x80+0x44);
   dipl(shi);
   lcd_wcmd(0x80+0x44);
   
   }
  if(GUBIAO==4)    //日
   {
   r--;
   if(r<1)
   r=31;
   lcd_wcmd(0x80+0x0b);
   dipl(r);
   lcd_wcmd(0x80+0x0b);
   
   }
  if(GUBIAO==5)    //月
   {
   yue--;
   if(yue<1)
   yue=12;
   lcd_wcmd(0x80+0x08);
   dipl(yue);
   lcd_wcmd(0x80+0x08);
   }
}
}
/*------------------------------------------------
                  键值处理
------------------------------------------------*/
void  zuanhuan(void)                 //a--b
{  
   switch(a)
   {
   case 0x45:gonnen();  break;
   case 0x46:taojia();  break;
   case 0x40:taojian();  break;
   default:break;
   }
}
//*************************************************************
//*************************************************************
     //红外键值散转
//*************************************************************
//*************************************************************
void Ir_work(void)
{
a=IRcord[2];
zuanhuan();
irpro_ok=0;//处理完成标志
}
/*------------------------------------------------
                红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
{
  unsigned char i, j, k;
  unsigned char cord,value;
  k=1;
  for(i=0;i<4;i++)      //处理4个字节
  {
   for(j=1;j<=8;j++) //处理1个字节8位
   {
   cord=irdata[k];
   if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
   value|=0x80;
   if(j<8)
   {
   value>>=1;
   }
   k++;
   }
  IRcord=value;
  value=0;     
  }
  irpro_ok=1;//处理完毕标志位置1
}
//*************************************************************
//*************************************************************
      //延时
//*************************************************************
//*************************************************************
void delay_1ms(void)    //延时程序
{
uchar K,L;
for(K=0;K<10;K++)
for(L=0;L<20;L++);
}
void delay(uchar z)
{
uchar i,j;
for(i=z;i>0;i--)
for(j=220;j>0;j--);
}
//*************************************************************
//*************************************************************
     //检测LCD忙
//*************************************************************
//*************************************************************
void busy_1602(void)    //查询忙碌标志信号程序
{
do
{
  EN=0;
  RW=1;
  RS=0;
  EN=1;
  busy=P0;
  EN=0;   
  delay_1ms();
} while(busy&&0x10==1);
}
//*************************************************************
//*************************************************************
      //LCD显汉字
//*************************************************************
//*************************************************************
void hanzi_Disp(uchar x,uchar y,uchar *pt)
{
  lcd_wcmd(addr_tab[8*x+y]); //写地址
  while(*pt>0)
  {
  lcd_wdat(*(pt++));    //写数据   
  }
}
//*************************************************************
//*************************************************************
       //LCD写指令
//*************************************************************
//*************************************************************
void lcd_wcmd(uchar cmd)
{    busy_1602();
       EN=0;
       RW=0;
       RS=0;
       EN=1;
       P0=cmd;
       EN=0;
}
//*************************************************************
//*************************************************************
     //LCD写数据
//*************************************************************
//*************************************************************
void lcd_wdat(uchar dat)
{    busy_1602();
       EN=0;
       RW=0;
       RS=1;
       EN=1;
       P0=dat;
       EN=0;
}
//*************************************************************
//*************************************************************
     //LCD读数据
//*************************************************************
//*************************************************************
/*void lcd_rdat()
{
        unsigned char lcddat;
        EN = 0;
  RS = 0;
  RW = 1;
  delay(4);
  EN = 1;
  lcddat = P0;      
  delay(4);
  EN = 0;
} */
//*************************************************************
//*************************************************************
      //LCD初始化
//*************************************************************
//*************************************************************
void lcd_init()//LCD初始化
{

       lcd_wcmd(0x38);
  lcd_wcmd(0x0c);
  lcd_wcmd(0x06);
}
//*****************************************************************
            //DS1302写地址,数据发送函数****************************      
//******************************************************************
void W1302(unsigned char addr,dat)      
{
  unsigned char i,temp;
  CE=0;
  SCLK=0;
  CE=1;
  //DS1302发地址
  for(i=8;i>0;i--)
     {
  SCLK=0;
  temp=addr;
  DIO=(bit)(temp&0x01);  //每次传输低字节
  addr>>=1;
  SCLK=1;
  }
  //DS1302发送数据
  for(i=8;i>0;i--)
     {
  SCLK=0;
  temp=dat;
  DIO=(bit)(temp&0x01);
  dat>>=1;
  SCLK=1;
  }
  CE=0;
}
//*************************************************************
//**************************************************************
               //DS1302数据读取函数
//*************************************************************
//*************************************************************
unsigned char  R1302(unsigned char addr)
{
  unsigned char i,temp,dat2;
  CE=0;
  SCLK=0;
  CE=1;
  //DS1302发送地址
  for(i=8;i>0;i--)
  {
  SCLK=0;
  temp=addr;
  DIO=(bit)(temp&0x01);  //每次传输低字节
  addr>>=1;
  SCLK=1;
  }
   //DS1302读取数据
   for(i=8;i>0;i--)
   {
   ACC_7=DIO;
   SCLK=1;
   ACC>>=1;
   SCLK=0;
   }
   CE=0;
   dat1=ACC;
   dat2=dat1/16;
   dat1=dat1%16;
   dat1=dat1+dat2*10;
   return(dat1);
}
//*************************************************************
//*************************************************************
                     //初始化DS1302
//*************************************************************
//*************************************************************
void Init(void)
{
  P2=0XFF;
  W1302(W_PROTECT,0X00);
// W1302(W_SECOND,0X00);
// W1302(W_MINUTE,0X10);
// W1302(W_HOUR,0X20);
  W1302(W_YEAR,0X12);
// W1302(W_MONTH,0X04);
// W1302(W_DAY,0X21);
  W1302(W_PROTECT,0X80);
}
//*************************************************************
//*************************************************************
     //转换显示时间
//*************************************************************
//*************************************************************
void  dipl(unsigned char a)   
{ unsigned char b,c,d;
  b=a/10;
  c=a%10;
  lcd_wdat(tab);
  lcd_wdat(tab[c]);
}
//*************************************************************
//*************************************************************
       //主函数
//*************************************************************
//*************************************************************
void main()     //主函数
{
  EX0init(); //初始化外部中断
  TIM0init();//初始化定时器
  lcd_init();
  Init();
   while(1)
  {
     while(flag==1)
  {
   if(irok)                        //如果接收好了进行红外处理
  {   
  Ircordpro();
   irok=0;
  }
     if(irpro_ok)                   //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
  {
  Ir_work();
    }
  }
     lcd_wcmd(0x80+0x4a);    //秒
     R1302(R_SECOND);
     dipl(dat1);


  lcd_wcmd(0x80+0x47);    //分
     R1302(R_MINUTE);
  dipl(dat1);
  
      
     lcd_wcmd(0x80+0x44);   //时
     R1302(R_HOUR);
  dipl(dat1);
  
  lcd_wcmd(0x80+0x05); //年
     R1302(R_YEAR);
  dipl(dat1);
  
  
  lcd_wcmd(0x80+0x08); //月
     R1302(R_MONTH);
  dipl(dat1);
  lcd_wcmd(0x80+0x0b); //日
     R1302(R_DAY);
  dipl(dat1);
  
  lcd_wcmd(0x80+0x07);
  lcd_wdat('-');
  lcd_wcmd(0x80+0x0a);
  lcd_wdat('-');
  lcd_wcmd(0x80+0x46);
  lcd_wdat(':');
  lcd_wcmd(0x80+0x49);
  lcd_wdat(':');
  lcd_wcmd(0x80+0x03);
  lcd_wdat('2');
  lcd_wcmd(0x80+0x04);
  lcd_wdat('0');
  
  if(irok)                        //如果接收好了进行红外处理
  {   
  Ircordpro();
   irok=0;
  }
     if(irpro_ok)                   //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
  {
  Ir_work();
    }
  }
}











不错,学习了。

不错,学习了。谢谢分享。

主要是不够精确,我做的几个电子钟从每天快一秒到十多秒的都有,那误差可大了、、、、、、
要写个程序,让电子钟在每天0点时自己减掉或加上误差秒数就好了,就像杜洋工作室里的那个FT4电子钟那样。

有什么好东东要分享哦

嗯确实不是很准

我正想做呢

好好加油

真不错

努力学习,以后多做点东西,累积经验,力求创新。

学习 学习 自己也做一个试试

很好的

呵呵!还不错哦!

好东西自然要收藏 好东西 与您共分享

好,希望能看到原理图

程序好像在keil里运行不了啊

杜洋工作室

遥控的!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top