一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
楼主: 环牛
收起左侧

闲着没事,发个前两天做的个1602电子钟

  [复制链接]
发表于 2010-10-30 00:12 | 显示全部楼层
呵呵 有时间仿造一个
发表于 2010-12-12 12:11 | 显示全部楼层
感谢分享!!!!!!!!!!!!!
发表于 2010-12-12 16:35 | 显示全部楼层
有时间仿造一个
发表于 2010-12-18 01:54 | 显示全部楼层
这贴都成开源的了,建议不要用1602液晶屏,耗电太大,最好能做个普通LCD的,后面增加几个发光二极管用的时候按一下按键就亮个几秒,还有缩小体积,最好能用2个AAA电池供电,耗电要低,走时要准,可以放床头晚上方便看时间和当闹钟,再增加个倒计时功能,最好能有个迷你USB能和计算机通信用来输出闹钟或者倒计时完成的信号,貌似特种部队用的,汗一个,看看有没有高人能给整出来
发表于 2011-1-22 21:02 | 显示全部楼层
本帖最后由 LBQ691477940 于 2011-1-23 12:43 编辑

能否把这个的程序改成串行驱动1602不要并行的,谢谢!
已自行搞掂了四线驱动方法式
#include <reg52.h>
#include <intrins.h>
#define nop _nop_()
#define PtData P0  //定义连接口线
#define uint unsigned int
#define uchar unsigned char
/*
sbit rs=P0^0;
sbit rw=P0^1;
sbit en=P0^2;
*/
sbit rs=P3^5;
sbit rw=P3^6;
sbit en=P3^4;
sbit DQ=P2^2;
sbit spk=P2^3;
sbit a0=ACC^0;
sbit a1=ACC^1;
sbit a2=ACC^2;
sbit a3=ACC^3;
sbit a4=ACC^4;
sbit a5=ACC^5;
sbit a6=ACC^6;
sbit a7=ACC^7;
sbit k1=P1^7; //调整模式  
sbit k2=P1^6; //+按钮
sbit k3=P1^5; //-按钮
sbit k4=P1^4;
/*
sbit clock_clk =P2^2;// P3^2;//ds1302_clk(时钟线7)
sbit clock_dat =P2^1;// P2^4;//ds1302_dat(数据线6)
sbit clock_Rst =P2^0;// P3^3;//ds1302_Rst(复位线5)
*/
sbit clock_clk =P3^2;//ds1302_clk(时钟线7)
sbit clock_dat =P2^4;//ds1302_dat(数据线6)
sbit clock_Rst =P3^3;//ds1302_Rst(复位线5)
uint  idata tdat;  //温度值变量
char idata sett;  //模式计数变量
char tflag;   //温度正负标志
char idata disp_buf1[16];//1602显示缓冲区1(即上排16个字符)
char idata disp_buf2[16];//1602显示缓冲区2(即下排16个字符)
char idata timedata[7];//存放时间值变量
uchar code table[]="Temperature ok !";
char idata temdata[5]; //存放温度值变量
uchar i;
uchar code self_dat[]={      
    0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,        //一,代码 0x04
    0x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00,        //二,代码 0x05
    0x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00,        //三,代码 0x06
    0x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00,         //四,代码 0x07
    0x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00,        //五,代码 0x08
    0x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00,        //六,代码 0x09
    0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00};        //日,代码 0x0a};//自定义字符
//************LCD相关函数**********************************//
void delay(uint n)        //延时时间为n*1ms
{ uchar x=0;
for(;n>0;n--)
{
  for(;x<250;x++)
  {
   nop;
   nop;
   nop;
   nop;
  }
}
}
/*=====================================================================
void check_busy() //LCD忙检测函数
{
P0=0xff;
rs=0;
rw=1;
en=1;
while(P0&0x80);
en=0;
}
void lcd_wcom(uchar com)     //写命令
{ check_busy();
rw=0;
rs=0;
P0=com;
en=1;
en=0;
}
void lcd_wdat(uchar dat)    //写数据
{ check_busy();
rw=0;
rs=1;
P0=dat;
en=1;
en=0;
}
=======================================================================*/
void check_busy() //LCD忙检测函数
{
  /*uchar Temp,t;
  PtData=0xff;
  rw=1;
  rs=0;nop;
  en=0;nop;
  do
   {
    nop;
    en=1;nop;
    Temp=PtData;
    nop;nop;nop;
    en=0;nop;nop;
    en=1;nop;
    t=PtData;
    nop;nop;nop;
    en=0;nop;nop;
    Temp&=0x80;
   }
  while(Temp==0x80);*/
P0=0xff;
rs=0;
rw=1;
en=1;
while(P0&0x80);
en=0;
}
//----------------------------------------------------------------------
void lcd_wcom(uchar Temp)//---写指令
{
  check_busy();
  rs=0;
  rw=0;
  en=0;nop;
  en=1;nop;
  PtData=Temp;
  nop;
  en=0;nop;
  en=1;nop;
  PtData=(Temp<<4);//左移四位
  nop;
  en=0;nop;
}
//--------------------------------------------------------------------------
void lcd_wdat(uchar Temp)//---写数据
{
  check_busy();
  rs=1;
  rw=0;
  en=0;nop;
  en=1;nop;
  PtData=Temp;
  nop;
  en=0;nop;
  en=1;nop;
  PtData=(Temp<<4);
  nop;
  en=0;nop;
}
//
void self_data() //写入自定义字符
{
uchar i=0;
lcd_wcom(0x06); //设定地址指针加一
lcd_wcom(0x48); //装入自定义字符的起始地址(CGRAM)
for(;i<64;i++)  
  lcd_wdat(self_dat);
}
void lcd_init()     //初始化
{
lcd_wcom(0x28);  //8位,双列,5*7
//lcd_wcom(0x38);  //8位,双列,5*7
lcd_wcom(0x0c);  //开显示,关光标,光标所在字符不闪烁
lcd_wcom(0x06);  //显示地址递增
lcd_wcom(0x01);  //清屏,光标移到左上角
self_data();
}
/*------------------------------------------------------------------------
//---初始化
void lcd_init()
{
  Delay(600);//延时应大于15ms,不同的晶振使需要修改,本程序再6M下调试通过
  rs=0;
  rw=0;nop;
  en=0;nop;
  en=1;nop;
  PtData=0x20;//   
  nop;
  en=0;
  Delay(200);//延时应大于4.1ms
  en=1;nop;
  PtData=0x20;//   
  nop;
  en=0;
  Delay(5);//延时应大于100us
  en=1;nop;
  PtData=0x20;//  
  nop;
  en=0;//设置4位操作;
  WriteLcdInstr(0x01);//清屏
  WriteLcdInstr(0x28);//设置4位操作,1行显示,5x8
  WriteLcdInstr(0x02);//光标归位
  WriteLcdInstr(0x06);//AC自动加1,画面不动
  WriteLcdInstr(0x0f);//0x0f:光标闪烁开;  
}
------------------------------------------------------------------------------*/
//***********DS18B20相关函数*******************//
void delay_18b20(uint sum)
{
while(sum--);
}
void rst_18b20()                 //复位
{ //uchar flag;
DQ=1;
delay_18b20(8);
DQ=0;
delay_18b20(80);
DQ=1;
delay_18b20(13);
//flag=DQ;
//return(flag);
    delay_18b20(20);
}
void wr_18b20(uchar dat) //写一个字节的数据
{
uchar i=8;
for(;i>0;i--)
{
  DQ=0;
  DQ=dat&0x01;
  delay_18b20(5);
  DQ=1;
  dat>>=1;
}
}
uchar rd_18b20()  //读一个字节的数据
{
uchar dat=0,i=8;
for(;i>0;i--)
{
  DQ=0;
  dat>>=1;
  DQ=1;
  if(DQ)
  dat|=0x80;
  delay_18b20(4);
}
return(dat);
}
uint rd_temperature()  //读取温度值,返回值为uint型,占两个字节
{
uchar a=0,b=0;
uint t=0;
float tt=0;
rst_18b20();  //复位
wr_18b20(0xcc);  //跳过ROM
wr_18b20(0x44);  //启动温度转换
rst_18b20();  //再次对18B20操作时,需要重新复位一次
wr_18b20(0xcc);  //跳过ROM
wr_18b20(0xbe);  //读取内部RAM的内容
a=rd_18b20();  //读温度值低位(内部RAM的第0个字节)
b=rd_18b20();  //读温度值高位(内部RAM的第1个字节)
t=b;
t<<=8;    //温度值高位放在t的高8位
t=t|a;    //温度值低位放在t的低8位
if(t<0x0fff)  //判断温度值为正还是负
     tflag=0;  //tflag=0温度值为正
    else
   {
  t=~t+1;   //温度值为负,负值以补码存放,这里要将其还原为原码
  tflag=1;  //tflag=1温度值为负
   }
tt=t*0.0625;
t= tt*10;   //放大10倍精确到一位小数
return(t);
}
//***********************************************//
uchar disp_self(uchar i)         //判断自定义字符是第几个
{  
switch(i)
{
  case 1:i=1;break;
  case 2:i=2;break;
  case 3:i=3;break;
  case 4:i=4;break;
  case 5:i=5;break;
  case 6:i=6;break;
  case 7:i=7;break;
  default : break;
}
return(i);
}
void tem_conv()
   {  
    uchar flagdat ;//定义温度值符号
    if(tflag==0)
    temdata[4]=flagdat=0x20;//正温度不显示符号
       else
     temdata[4]=flagdat=0x2d;//负温度显示负号:-
     temdata[0]=tdat/1000+0x30;//温度百位值
        temdata[1]=tdat%1000/100+0x30;//温度十位值
        temdata[2]=tdat%100/10+0x30;//温度个位值
        temdata[3]=tdat%10+0x30;//温度小数位值
    if(temdata[0]==0x30)
        {temdata[0]=0x20;//如果百位为0,不显示
         if(temdata[1]==0x30)
         {
       temdata[1]=0x20;//如果百位为0,十位为0也不显示
         }
        }   
     }
void beeper(uchar i)  //蜂鸣器
{
uchar j;
for(j=i;j>0;j--)
{   
  spk=0;
  delay(200);
  spk=~spk;
  delay(200);  
}
}
void int_display()  //初始显示
{
uchar m=0;
lcd_init();
lcd_wcom(0x80);              //显示地址
for(m=0;m<16;m++)
  {
   lcd_wdat(table[m]); //将数组中字符显示出来
   delay(1000);         
  }  
  delay(10);
  beeper(2);
  lcd_wcom(0x01);
  
}
//********************************************//
void updata_disp()    //更新缓冲区数据程序
{
disp_buf1[0]='2';
disp_buf1[1]='0';
disp_buf1[2]=timedata[6]/16+0x30;
disp_buf1[3]=timedata[6]%16+0x30;
disp_buf1[4]='/';
disp_buf1[5]=timedata[4]/16+0x30;
disp_buf1[6]=timedata[4]%16+0x30;
disp_buf1[7]='/';
disp_buf1[8]=timedata[3]/16+0x30;
disp_buf1[9]=timedata[3]%16+0x30;
disp_buf1[10]=0x20;
disp_buf1[11]='[';
disp_buf1[12]=disp_self(timedata[5]%16);
disp_buf1[13]=']';
disp_buf1[14]=0x20;
disp_buf1[15]=0x20;
disp_buf2[0]=timedata[2]/16+0x30;
disp_buf2[1]=timedata[2]%16+0x30;
disp_buf2[2]=':';
disp_buf2[3]=timedata[1]/16+0x30;
disp_buf2[4]=timedata[1]%16+0x30;
disp_buf2[5]=':';
disp_buf2[6]=timedata[0]/16+0x30;
disp_buf2[7]=timedata[0]%16+0x30;
disp_buf2[8]=temdata[4];
disp_buf2[9]=temdata[0];
disp_buf2[10]=temdata[1];
disp_buf2[11]=temdata[2];
disp_buf2[12]='.';
disp_buf2[13]=temdata[3];
disp_buf2[14]=0xdf;
disp_buf2[15]='C';
}
void display()   //显示缓冲区数据函数
{
uchar i;
lcd_wcom(0x80);
for(i=0;i<16;i++)
lcd_wdat(disp_buf1);
lcd_wcom(0xc0);
for(i=0;i<16;i++)
lcd_wdat(disp_buf2);
}
//**************DS1302相关子函数**************//
//DS1302写入字节(底层协议)
uchar clock_in(){
clock_dat=1;
a0=clock_dat;
clock_clk=1; clock_clk=0; a1=clock_dat;
clock_clk=1; clock_clk=0; a2=clock_dat;
clock_clk=1; clock_clk=0; a3=clock_dat;
clock_clk=1; clock_clk=0; a4=clock_dat;
clock_clk=1; clock_clk=0; a5=clock_dat;
clock_clk=1; clock_clk=0; a6=clock_dat;
clock_clk=1; clock_clk=0; a7=clock_dat;
return(ACC);
}
//1302驱动程序(底层协议)
void clock_out(uchar dd){
ACC=dd;
clock_dat=a0; clock_clk=1; clock_clk=0;
clock_dat=a1; clock_clk=1; clock_clk=0;
clock_dat=a2; clock_clk=1; clock_clk=0;
clock_dat=a3; clock_clk=1; clock_clk=0;
clock_dat=a4; clock_clk=1; clock_clk=0;
clock_dat=a5; clock_clk=1; clock_clk=0;
clock_dat=a6; clock_clk=1; clock_clk=0;
clock_dat=a7; clock_clk=1; clock_clk=0;
}
//DS1302读数据(底层协议)
uchar read_clock(uchar ord){
uchar dd=0;
clock_clk=0;
clock_Rst=0;
clock_Rst=1;
clock_out(ord);
dd=clock_in();
clock_Rst=0;
clock_clk=1;
return(dd);
}
//DS1302写数据(底层协议)
void write_clock(uchar ord, uchar dd){
clock_clk=0;
clock_Rst=0;
clock_Rst=1;
clock_out(ord);
clock_out(dd);
clock_Rst=0;
clock_clk=1;
}
//设置1302的初始时间
void Init_1302(){//(2011年1月23日12时28分00秒星期日)
if(read_clock(0xc1) != 0xf0)
{
  write_clock(0x8e,0x00);//允许写操作
  write_clock(0x8c,0x11);//年
  write_clock(0x8a,0x07);//星期
  write_clock(0x88,0x01);//月
  write_clock(0x86,0x23);//日
  write_clock(0x84,0x12);//小时
  write_clock(0x82,0x28);//分钟
  write_clock(0x80,0x00);//秒
  write_clock(0x90,0xa5);//充电
  write_clock(0xc0,0xf0); //判断是否初始化一次标识写入
  write_clock(0x8e,0x80);//禁止写操作
}
}
//常用时钟数据读取
void read_clocks()
{
timedata[0] = read_clock(0x81);//读取秒数据
timedata[1] = read_clock(0x83);//读取分钟数据
timedata[2] = read_clock(0x85);//小时
timedata[3] = read_clock(0x87);//日
timedata[4] = read_clock(0x89);//月
timedata[5] = read_clock(0x8b);//星期
timedata[6] = read_clock(0x8d);//年
}
void set_display(uchar com, uchar dat)   //调整时间时显示函数
{
lcd_wcom(com);
lcd_wdat(dat/16+0x30);
lcd_wdat(dat%16+0x30);
}
set_selfdisplay(uchar com, uchar dat)    //调整星期时自定义字符显示函数
{
lcd_wcom(com);
lcd_wdat(dat);
}
void int_checkbutton()   //初始化按键
{
k1=1;
k2=1;
k3=1;
k4=1;
}
void int_t0() interrupt 1 using 1        //定时中断
{
TH0=0x3c;
TL0=0xb0;
i++;
if(i==10)
{
  i=0;
  display();//更新显示数据
}
}
//**************主程序************************//
void main()
{
TMOD=0x01;                //设置定时中断
TH0=0x3c;
TL0=0xb0;
EA=1;
ET0=1;
TR0=1;
int_display();  //初始化显示
int_checkbutton(); //按键初始化
Init_1302();  //1302初始化
while(1)
{      
   if(k1==0)     //调整模式键按下
   {
    delay(30);
    if(k1==0)
    {  
     while(!k1);   //确定按下
     sett++;
     TR0=0;
     beeper(1);
       if(sett==1) //按下的次数不同,光标移动到不同的调整位置处
      {
       lcd_wcom(0x0f);
       lcd_wcom(0x83);
      }
       if(sett==2)
      {
       lcd_wcom(0x86);
      }
       if(sett==3)
      {
       lcd_wcom(0x89);
      }
       if(sett==4)
      {
       lcd_wcom(0x8c);
      }
       if(sett==5)
      {
       lcd_wcom(0xc1);
      }
       if(sett==6)
      {
       lcd_wcom(0xc4);
      }
       if(sett==7)
      {
       lcd_wcom(0xc7);
      }
       if(sett==8)     //第八次按下模式键,退出调整,恢复走时显示
      {
       sett=0;
       lcd_wcom(0x0c);
       TR0=1;
      }
    }
   }if(sett!=0)
     {
      if(k2==0)  //增加键按下
      {
       delay(30); //延时消抖
        if(k2==0)
       {
        while(!k2);
        beeper(1); //按键放开之后蜂鸣器叫一下,表示确定
        if(sett==1) //根据按下的次数调整相应的项目
        { uchar item ;
         item=timedata[6];
         item=(item/16)*10+item%16;
         item++;   //年份加一
         if(item==100)item=0;
         item=(item/10)*16+item%10;
         set_display(0x82,item); //调整时显示
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x8c,item);
         lcd_wcom(0x83);
        }
        if(sett==2)
        { uchar item ;
         item=timedata[4];
         item=(item/16)*10+item%16;
         item++;   //月份加一
         if(item==13)item=0;
         item=(item/10)*16+item%10;
         set_display(0x85,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x88,item);
         lcd_wcom(0x86);
        }
        if(sett==3)
        { uchar item ;
         item=timedata[3];
         item=(item/16)*10+item%16;
         item++;   //日加一
         if(item==32)item=0;
         item=(item/10)*16+item%10;
         set_display(0x88,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x86,item);
         lcd_wcom(0x89);
        }
        if(sett==4)
        { uchar item ;
         item=timedata[5];
         item=(item/16)*10+item%16;
         item++;   //星期加一
         if(item==8)item=1;
         item=(item/10)*16+item%10;
         set_selfdisplay(0x8c,disp_self(item%16));
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x8a,item);
         lcd_wcom(0x8c);
        }
        if(sett==5)
        { uchar item ;
         item=timedata[2];
         item=(item/16)*10+item%16;
         item++;   //小时加一
         if(item==24)item=0;
         item=(item/10)*16+item%10;
         set_display(0xc0,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x84,item);
         lcd_wcom(0xc1);
        }
        if(sett==6)
        { uchar item ;
         item=timedata[1];
         item=(item/16)*10+item%16;
         item++;            //分加一
         if(item==60)item=0;
         item=(item/10)*16+item%10;
         set_display(0xc3,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x82,item);
         lcd_wcom(0xc4);
        }
        if(sett==7)
        { uchar item ;
         item=timedata[0];
         item=(item/16)*10+item%16;
         item++;   //秒加一
         if(item==60)item=0;
         item=(item/10)*16+item%10;
         set_display(0xc6,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x80,item);
         lcd_wcom(0xc7);
        }
       }
      }
      if(k3==0) //下面这段是减按钮的程序,和加按钮程序差不多
      {  //唯一不同就是++变成--,还有就是上限变成了下限
       delay(30);
        if(k3==0)
       {
        while(!k3);
        beeper(1);
        if(sett==1)
        { uchar item ;
         item=timedata[6];
         item=(item/16)*10+item%16;
         item--;     
         if(item==0)item=99;
         item=(item/10)*16+item%10;
         set_display(0x82,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x8c,item);
         lcd_wcom(0x83);
        }
        if(sett==2)
        { uchar item ;
         item=timedata[4];
         item=(item/16)*10+item%16;
         item--;
         if(item==-1)item=12;
         item=(item/10)*16+item%10;
         set_display(0x85,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x88,item);
         lcd_wcom(0x86);
        }
        if(sett==3)
        { uchar item ;
         item=timedata[3];
         item=(item/16)*10+item%16;
         item--;
         if(item==-1)item=31;
         item=(item/10)*16+item%10;
         set_display(0x88,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x86,item);
         lcd_wcom(0x89);
        }
        if(sett==4)
        { uchar item ;
         item=timedata[5];
         item=(item/16)*10+item%16;
         item--;
         if(item==0)item=7;
         item=(item/10)*16+item%10;
         set_selfdisplay(0x8c,disp_self(item%16));
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x8a,item);
         lcd_wcom(0x8c);
        }
        if(sett==5)
        { uchar item ;
         item=timedata[2];
         item=(item/16)*10+item%16;
         item--;
         if(item==-1)item=23;
         item=(item/10)*16+item%10;
         set_display(0xc0,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x84,item);
         lcd_wcom(0xc1);
        }
        if(sett==6)
        { uchar item ;
         item=timedata[1];
         item=(item/16)*10+item%16;
         item--;
         if(item==-1)item=59;
         item=(item/10)*16+item%10;
         set_display(0xc3,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x82,item);
         lcd_wcom(0xc4);
        }
        if(sett==7)
        { uchar item ;
         item=timedata[0];
         item=(item/16)*10+item%16;
         item--;
         if(item==-1)item=59;
         item=(item/10)*16+item%10;
         set_display(0xc6,item);
         write_clock(0x8e,0x00);//允许写操作
         write_clock(0x80,item);
         lcd_wcom(0xc7);
        }
       }
      }
     }   
tdat=rd_temperature();   //读温度值
tem_conv();    //转化温度
read_clocks();     //读时钟数据   
updata_disp();    //数据送入显示缓冲区
}
}
发表于 2011-1-26 13:13 | 显示全部楼层
洞洞板上有细铜丝走线吧
发表于 2011-1-29 08:19 | 显示全部楼层
回复 5# fangjun


    我做了一个,居然不行啊,无显示,线没连错,也没焊错,就是单片机用STC89C52的,什么问题啊?还有时钟芯片做好后插上就可以了吗?
发表于 2011-1-29 08:24 | 显示全部楼层
回复 77# 单片e家
这个……偶也不懂,你问问原作者,或者坛子里好多的单片机高手
发表于 2011-1-29 11:39 | 显示全部楼层
回复 1# 环牛


    我做了一个,居然不行啊,无显示,线没连错,也没焊错,就是单片机用STC89C52的,什么问题啊?还有时钟芯片做好后插上就可以了吗?
发表于 2011-2-3 22:44 | 显示全部楼层
做的不错,有时间准备仿制。

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-26 00:43 , Processed in 0.052460 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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