找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1919|回复: 1
打印 上一主题 下一主题
收起左侧

1602电子时钟带温度显示单片机源码

[复制链接]
跳转到指定楼层
楼主
ID:152303 发表于 2016-12-5 14:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include  <reg51.h>
  2. #include  <intrins.h>

  3. #define  uchar  unsigned  char
  4. #define  uint   unsigned  int

  5. void delay(unsigned int x)//延时公用程序
  6. {
  7. unsigned char i;
  8. while(x--)
  9.     {
  10.     for(i=0;i<125;i++);
  11.     }
  12. }

  13. /********************DS1302部分程序*************************/
  14. sbit sclk=P3^1;
  15. sbit rst=P3^0;
  16. sbit io=P3^2;  //DS1302三个管脚定义
  17. unsigned char time[7]={16,2,12,5,14,28,00};//年周月日时分秒 有符号

  18. uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//DS1302写时间寄存器地址
  19. uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//读
  20. void write_ds1302_byte(uchar dat) //DS1302写字节函数
  21. {
  22.         uchar i;
  23.         for(i=0;i<8;i++)
  24.         {
  25.                 sclk=0;                           //下降沿数据有效
  26.                 io=dat&0x01;
  27.                 dat=dat>>1;
  28.                 sclk=1;
  29.         }
  30. }
  31. void write_ds1302(uchar add,uchar dat)
  32. {
  33.         rst=0;
  34.         _nop_();
  35.         sclk=0;
  36.         _nop_();
  37.         rst=1;
  38.         _nop_();
  39.         write_ds1302_byte(add);
  40.         write_ds1302_byte(dat);        //发送地址后立即发送数据,没有停顿
  41.         rst=0;
  42.         _nop_();
  43.         sclk=1;
  44.         io=1;
  45. }
  46. uchar read_ds1302(uchar add)
  47. {
  48.         uchar i,dat=0;
  49.         rst=0;
  50.         _nop_();
  51.         sclk=0;
  52.         _nop_();
  53.         rst=1;
  54.         _nop_();
  55.         write_ds1302_byte(add);        //发送地址后DS1302立即送出数据
  56.         for(i=0;i<8;i++)
  57.         {
  58.                 dat=dat>>1;
  59.                 sclk=0;
  60.                 if(io)
  61.                         dat=dat|0x80;
  62.                 sclk=1;
  63.         }
  64.         rst=0;
  65.         _nop_();
  66.         sclk=0;
  67.         _nop_();
  68.         sclk=1;
  69.         io=1;

  70.         return dat;
  71. }
  72. void ds1302_init()
  73. {
  74.         uchar i,j;
  75.         for(i=0;i<7;i++)
  76.         {
  77.                 j=time[i]/10;
  78.                 time[i]=time[i]%10;
  79.                 time[i]=time[i]+j*16;          //转换为BCD码
  80.         }
  81.         write_ds1302(0x8e,0x00);//去除写保护
  82.         for(i=0;i<7;i++)
  83.         {
  84.                 write_ds1302(write_add[i],time[i]);
  85.         }
  86.     write_ds1302(0x8e,0x80);//加写保护
  87. }
  88. void ds1302_set_time(uchar add,uchar dat) //设置DS1302时间
  89. {
  90.         uchar i;
  91.         i=dat/10;
  92.         dat%=10;
  93.         dat=dat+i*16;           //转换十进制为BCD码
  94.         write_ds1302(0x8e,0x00);
  95.         write_ds1302(add,dat);
  96.     write_ds1302(0x8e,0x80);
  97. }
  98. void read_time()        //读时间
  99. {
  100.         uchar i;
  101.         for(i=0;i<8;i++)
  102.         {
  103.                 time[i]=read_ds1302(read_add[i]);
  104.                 time[i]=time[i]/16*10+time[i]%16;//转换BCD码为十进制
  105.         }
  106. }

  107. /***********************DS18B20程序********************************/
  108. sbit DQ=P3^6;  //DS18B20数据端
  109. unsigned int temperature=0;//温度
  110. unsigned char fuhao=0;//温度的正负符号

  111. void delay_18B20(unsigned int i)
  112. {
  113. while(i--);
  114. }
  115. /**********ds18b20初始化函数**********************/
  116. void Init_DS18B20(void)
  117. {
  118. unsigned char x=0;
  119. DQ = 1;          //DQ复位
  120. delay_18B20(2); //稍做延时
  121. DQ = 0;          //单片机将DQ拉低
  122. delay_18B20(60); //精确延时 大于 480us
  123. DQ = 1;          //拉高总线
  124. delay_18B20(2);
  125. x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  126. delay_18B20(15);
  127. }
  128. /***********ds18b20读一个字节**************/
  129. unsigned char ReadOneChar(void)
  130. {
  131. unsigned char i=0;
  132. unsigned char dat = 0;
  133. for (i=8;i>0;i--)
  134. {
  135.     DQ = 0; // 给脉冲信号
  136.     dat>>=1;
  137.     DQ = 1; // 给脉冲信号
  138.     if(DQ)
  139.     dat |=0x80;
  140.     delay_18B20(4);
  141. }
  142.    return(dat);
  143. }
  144. /*************ds18b20写一个字节****************/
  145. void WriteOneChar(unsigned char dat)
  146. {
  147.    unsigned char i=0;
  148.    for (i=8; i>0; i--)
  149.    {
  150.     DQ = 0;
  151.     DQ = dat&0x01;
  152.     delay_18B20(2);
  153.     DQ = 1;
  154.     dat>>=1;
  155.   }
  156. }

  157. void ReadTemperature(void)
  158. {unsigned char readdata[2]={0,0};
  159. fuhao=0;
  160. temperature=0;
  161. delay_18B20(40);       // this message is very important
  162. Init_DS18B20();
  163. WriteOneChar(0xCC);    // 跳过读序号列号的操作
  164. WriteOneChar(0x44); // 启动温度转换
  165. delay_18B20(40);       // this message is wery important
  166. Init_DS18B20();
  167. WriteOneChar(0xCC); //跳过读序号列号的操作
  168. WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  169. delay_18B20(40);
  170. readdata[0]=ReadOneChar();    //读取温度值低位
  171. readdata[1]=ReadOneChar();      //读取温度值高位

  172. if (readdata[1]>127)
  173.        {readdata[0]^=0xff;//求补码
  174.         readdata[1]^=0xff;
  175.         fuhao=1;//符号为“-”
  176.        }

  177. temperature =readdata[1]*256+readdata[0] ;
  178. temperature =temperature*0.625+0.5 ;//放大了10倍
  179. }

  180. /**********************LCD程序******************************/
  181. #define LCD_DATA P1
  182. sbit LCD_RS = P0^0;
  183. sbit LCD_RW = P0^1;
  184. sbit LCD_EN = P0^2;
  185. unsigned char disbuff0[16]={'D',':',' ',
  186. ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',};//LCD第一行显示日期
  187. unsigned char disbuff1[16]={'T',':',' ',
  188. ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',};//LCD第二行显示温度

  189. void    Delay20ms() ;
  190. void         LCD_WriteDat(unsigned char lcd_dat);
  191. void         LCD_WriteCmd(unsigned char lcd_cmd);
  192. unsigned char         LCD_ReadStatus(void);
  193. void         LCD_Goto(unsigned char x,unsigned char y);
  194. void    LCD_Display(unsigned char row,unsigned char *str);

  195. void Delay20ms()   //粗略延时;
  196. {
  197.   unsigned int tmp = 50000;
  198.   while(tmp--);
  199.   }        

  200. void         LCD_Init(void)
  201. {
  202.         Delay20ms();
  203.         /*************************************************
  204.          功能设置:        DB5=1;DB6...=0;
  205.                                                          DB4=1:8位接口; 0:4位接口;
  206.                                                          DB3=1:双行显示;0:单行显示;
  207.                                                          DB3=1:5×10点阵;0:5×7点阵;               
  208.         *************************************************/
  209.   LCD_WriteCmd(0x38);        //8位机接口、双行显示、5×7字符点阵;
  210.         /*************************************************
  211.           显示控制:DB3=1;DB4...=0;
  212.                                                   DB2=1:开启显示;0:关闭LCD显示;
  213.                                                   DB1=1:显示光标;0:光标隐藏;
  214.                                                   DB0=1:光标闪烁;0:光标闪烁关闭;
  215.         *************************************************/
  216.         LCD_WriteCmd(0x0c);        //显示开启、光标不显示也不闪烁;
  217.         /*************************************************
  218.           清屏指令:DB0=1;DB1...=0;
  219.         *************************************************/
  220.         LCD_WriteCmd(0x01);        //清屏;
  221.         /****************************************************************
  222.           访问模式:DB2=1;DB3...=0;
  223.                                                   DB1=1:对内部Ram读写后AC自增,否则自减;
  224.                                                   DB0=1:与DB1设置有关,对DD RAM写时同时整屏移动1位;
  225.         *****************************************************************/
  226.         LCD_WriteCmd(0x06);        //光标右移一位、整屏不移动;

  227.   LCD_Goto(0,0);
  228.         }
  229. void         LCD_WriteDat(unsigned char lcd_dat)
  230. {
  231.         unsigned char tmp;
  232.         tmp = LCD_ReadStatus();                //读状态;
  233.         while((tmp & 0x80))                        //是否忙 ?
  234.                 {
  235.                         tmp = LCD_ReadStatus();
  236.                         }
  237.         
  238.         LCD_RS = 1;
  239.         LCD_RW = 0;
  240.         LCD_DATA = lcd_dat;
  241.         _nop_();
  242.         LCD_EN = 0;
  243.         _nop_();
  244.         _nop_();
  245.         LCD_EN = 1;
  246.         
  247.         }
  248. void         LCD_WriteCmd(unsigned char lcd_cmd)
  249. {
  250.         unsigned char tmp;
  251.         tmp = LCD_ReadStatus();
  252.         while((tmp & 0x80))
  253.         {
  254.                 tmp = LCD_ReadStatus();
  255.                 }
  256.         
  257.         LCD_RS = 0;
  258.         LCD_RW = 0;
  259.         LCD_DATA = lcd_cmd;
  260.         _nop_();
  261.         LCD_EN = 0;
  262.         _nop_();
  263.         _nop_();
  264.         LCD_EN = 1;
  265.         }
  266. unsigned char         LCD_ReadStatus(void)
  267. {
  268.         unsigned char tmp;
  269.         #if 0
  270.         LCD_RS = 0;
  271.         LCD_RW = 1;
  272.         LCD_EN = 1;
  273.         tmp = LCD_DATA;
  274.         LCD_EN = 0;
  275.         #endif
  276.         LCD_DATA = 0xff;
  277.         LCD_RS = 0;
  278.         LCD_RW = 1;
  279.         LCD_EN = 0;
  280.         _nop_();
  281.         _nop_();
  282.         LCD_EN = 1;
  283.         tmp = LCD_DATA;
  284.         return tmp;
  285.         }
  286. void         LCD_Goto(unsigned char x,unsigned char y)
  287. {
  288.         unsigned char tmp;
  289.         if(y)                                //若是第二行;
  290.                 {
  291.                         tmp = 0xc0 + x;
  292.                         LCD_WriteCmd(tmp);
  293.                         }
  294.         else
  295.                 {
  296.                         tmp = 0x80 + x;
  297.                         LCD_WriteCmd(tmp);
  298.                         }               
  299.         }
  300.         
  301. void LCD_Display(unsigned char row,unsigned char *str)
  302. {
  303.         if(row)
  304.                 {
  305.                         LCD_Goto(0,1);
  306.                         }
  307.   else
  308.           {
  309.                   LCD_Goto(0,0);
  310.                   }
  311.   while(*str != '\0')
  312.   {
  313.           LCD_WriteDat(*str++);
  314.           }
  315.         }
  316. /*************************按键处理程序********************************/
  317. uchar hour=0;uchar minute=0;uchar year=0;uchar month=0;uchar date=0;//时间设定
  318. uchar alarm_hour=0;uchar alarm_minute=0;//闹钟设定时间
  319. bit   at_flag;//闹钟开关标志
  320. void key()
  321. {uchar key1=0;uchar key2=0;
  322. key1=P0;key1=key1>>3;
  323. delay(75);
  324. key2=P0;key2=key2>>3;
  325. if (key1==key2 && key1!=0x1f)
  326.     {switch (key1)
  327.             {case 0x1e://闹钟分设置键
  328.                        {while(1)
  329.                              {disbuff0[11]='_';disbuff0[12]='_';//显示时
  330.                              delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
  331.                              disbuff0[11]=alarm_hour/10+'0';disbuff0[12]=alarm_hour%10+'0';//显示时
  332.                                   delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
  333.                              key1=0;key1=P0;key1=key1>>3;
  334.                              if (key1==0x1b)//加
  335.                                  {if (alarm_hour<23)
  336.                                    {alarm_hour++;}
  337.                                     else
  338.                                        {alarm_hour=0;}
  339.                                 }
  340.                              if (key1==0x17)//确定
  341.                                 {break;}
  342.                              }
  343.                        }
  344.              case 0x1d://闹钟分设置键
  345.                          {while(1)        
  346.                                             {disbuff0[14]='_';disbuff0[15]='_';//显示时
  347.                                              delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
  348.                                              disbuff0[14]=alarm_minute/10+'0';disbuff0[15]=alarm_minute%10+'0';//显示时
  349.                                              delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
  350.                                              key1=0;key1=P0;key1=key1>>3;
  351.                                              if (key1==0x1b)//加
  352.                                                 {if (alarm_minute<59)
  353.                                                     {alarm_minute++;}
  354.                                                     else
  355.                                                         {alarm_minute=0;}
  356.                                                 }
  357.                                              if (key1==0x17)//确定
  358.                                                 {break;}
  359.                                              }
  360.                          }
  361.              case 0x0f://闹钟开关键
  362.                        {at_flag=!at_flag;
  363.                        }
  364.              default : break;
  365.             }
  366.      }


  367. }

  368. /****************蜂鸣器程序**********************/
  369. sbit speaker=P3^7;
  370. void timer0() interrupt 1 //这里输出波形
  371. {TH0=254;//频率为1600hz时计时器初值
  372. TL0=200;
  373. speaker=!speaker;
  374. }

  375. /********************主程序********************/
  376. void main()
  377. {
  378. ds1302_init();//初始化1302
  379. LCD_Init();//初始化LCD
  380. /*计时器0设置*/
  381. TMOD=0x11;//定时器1、2工作于方式1
  382. TH0=254;//频率为1600hz时计时器初值
  383. TL0=200;
  384. ET0=1;  
  385. EA=0;//关闭总中断
  386. speaker=0;
  387. //显示welcome to BJTU
  388. disbuff0[0]=' ';disbuff0[1]=' ';disbuff0[2]='W';disbuff0[3]='e';disbuff0[4]='l';disbuff0[5]='c';disbuff0[6]='o';disbuff0[7]='m';
  389. disbuff0[8]='e';disbuff0[9]=' ';disbuff0[10]=' ';disbuff0[11]='t';disbuff0[12]='o';disbuff0[13]=' ';disbuff0[14]=' ';disbuff0[15]=' ';
  390. disbuff1[0]=' ';disbuff1[1]=' ';disbuff1[6]='Y';disbuff1[7]='O';disbuff1[8]='N';disbuff1[9]='K';disbuff1[10]='0';
  391. LCD_Display(0,disbuff0);//LCD第一行显示
  392. LCD_Display(1,disbuff1);//LCD第二行显示
  393. delay(5000);
  394. disbuff0[0]='D';disbuff0[1]=':';disbuff0[2]=' ';disbuff0[3]=' ';disbuff0[4]=' ';disbuff0[5]=' ';disbuff0[6]=' ';disbuff0[7]=' ';
  395. disbuff0[8]=' ';disbuff0[11]=' ';disbuff0[12]=' ';
  396. disbuff1[0]='T';disbuff1[1]=':';disbuff1[7]=' ';disbuff1[8]=' ';disbuff1[9]=' ';disbuff1[10]=' ';
  397. while(1)
  398.      {read_time();//获取时间
  399.       year=time[0];//计算年
  400.       month=time[2];//计算月
  401.       date=time[3];//计算日
  402.       hour=time[4];//计算时
  403.       minute=time[5];//计算分

  404.       disbuff0[2]=year/10+'0';disbuff0[3]=year%10+'0';//显示年
  405.       disbuff0[4]='-';disbuff0[5]= month/10+'0';disbuff0[6]= month%10+'0';//显示月
  406.       disbuff0[7]='-';disbuff0[8]= date/10+'0';disbuff0[9]= date%10+'0';//显示日
  407.       disbuff0[10]=' ';disbuff0[11]=hour/10+'0';disbuff0[12]=hour%10+'0';//显示时
  408.       disbuff0[13]=':';disbuff0[14]=minute/10+'0';disbuff0[15]=minute%10+'0';//显示分
  409.       ReadTemperature();//获取温度
  410.       if (fuhao)
  411.           {disbuff1[2]='-';}
  412.           else
  413.              {disbuff1[2]='+';}
  414.       disbuff1[3]=((temperature/1000)%10)+'0';disbuff1[4]=((temperature/100)%10)+'0';disbuff1[5]=((temperature/10)%10)+'0';
  415.       disbuff1[6]='.';disbuff1[7]=((temperature)%10)+'0';disbuff1[8]='C';
  416.       if (at_flag)//显示闹钟开关
  417.                             {disbuff1[10]='A';disbuff1[11]='_';disbuff1[12]='O';disbuff1[13]='N';disbuff1[14]=' ';}
  418.                             else
  419.                                {disbuff1[10]='A';disbuff1[11]='_';disbuff1[12]='O';disbuff1[13]='F';disbuff1[14]='F';}
  420.       key();//按键处理程序
  421.       if (alarm_minute==minute && alarm_hour==hour && at_flag)
  422.           {EA=1;TR0=1;}
  423.          else
  424.             {EA=0;TR0=0;speaker=0;}
  425.       LCD_Display(0,disbuff0);//LCD第一行显示
  426.       LCD_Display(1,disbuff1);//LCD第二行显示
  427.      }
  428. }

复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:388679 发表于 2018-8-21 21:47 | 只看该作者
我改了接口在学习板上做了 时间光标不闪 按键我看不懂接哪几个管脚
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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