找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机51单片机时钟可调程序+电路图

[复制链接]
跳转到指定楼层
楼主
如图是电路原理图如下:

单片机源程序如下:
  1. /*********************************************************************************
  2. * 【外部晶振】: 11.0592mhz       
  3. * 【主控芯片】: STC89C52
  4. * 【编译环境】: Keil μVisio3       
  5. * 【程序功能】: LCD1602显示DS1302时钟 ,按键可以调                                                                                           
  6. * 【使用说明】: 液晶1脚接1602黑色排母的1脚  如果是无背光的液晶只有14个脚 排母右边空2个位   
  7.                  请把液晶对比度电位器顺时针调制10点钟方向,请勿多调超出极限位置会损坏电位器!

  8.                                  使用前是用杜邦线分别把DS1302旁边3个脚的排针与P1口的0~2接相接
  9. 接线方式是 请看开饭背面有丝印
  10.                                         TSCLK  -  P10
  11.                                         TIO    -  P11
  12.                                         TRST   -  P12
  13. -------------------------------调节时钟--------------------------------------------
  14. 按下S2依次选择秒分时、星期日月年,S3 加,S4减

  15. *  说明:免费开源,不提供源代码分析.
  16. **********************************************************************************/
  17. #include<reg52.h>
  18. #define uint unsigned int
  19. #define uchar unsigned char
  20. uchar a,miao,shi,fen,ri,yue,nian,week,flag,temp,key1n;
  21. uchar ge,shi,bai,qian;
  22. #define yh 0x80  //第一行的初始位置
  23. #define er 0x80+0x40 //第二行初始位置
  24. #define keyport P2
  25. //sbit dula=P2^6;
  26. //sbit wela=P2^7;

  27. bit f_systick_1ms=0;
  28. bit f_systick_2ms=0;
  29. uchar cnt_systick_2ms=0;
  30. bit f_systick_4ms=0;
  31. uchar cnt_systick_4ms=0;
  32. bit f_systick_10ms=0;
  33. uchar cnt_systick_10ms=0;
  34. uchar cnt_systick_101ms=0;
  35. bit f_systick_505ms=0;
  36. uchar cnt_systick_505ms=0;
  37. bit f_systick_1s=0;
  38. uchar cnt_systick_1s=0;
  39. uchar data  current_Event = 0;
  40. bit flag_Alarm_blink;
  41. bit   swatch_Start_Flag = 0;                                                     //秒表计时开始标致位


  42. sbit wr=P1^1;
  43. sbit rs=P1^0;
  44. sbit en=P1^2;
  45. sbit SCLK=P3^5;
  46. sbit IO=P3^6;   
  47. sbit RST=P3^7;   
  48. sbit ACC0=ACC^0;
  49. sbit ACC7=ACC^7;
  50. sbit key=P2^0;
  51. sbit key1=P2^1;
  52. sbit key2=P2^2;
  53. sbit key3=P2^3;
  54. uchar keyvalue=0;
  55. uchar code tab1[]={"    -  -      "};
  56. uchar code tab2[]={"  :  :  "};
  57. uchar code tab3[]={"SWITCH"};
  58. void delay(uint xms)//延时函数
  59. {
  60.         uint x,y;
  61.         for(x=xms;x>0;x--)
  62.          for(y=110;y>0;y--);
  63. }
  64. /*************定时器T0的初始化********************/
  65. void Timer1_Init(void)
  66. {
  67.         TMOD=0x11;                                                          //T1定时器工作方式1
  68.         TH1=0xfc;                                                           //1ms初值
  69.         TL1=0x18;                               
  70.         ET1=1;                                                              //开定时器T0中断
  71.         EA=1;                                                               //开总中断               
  72. //        TR1=1;                                                              //启动定时器T0
  73. }
  74. /****************T0定时器中断*********************/
  75. void ISR_T1(void) interrupt        3                                                      //1ms中断
  76. {
  77.         TH1=0xfc;                       
  78.         TL1=0x18;                                                                               //重装1ms中断
  79.         f_systick_1ms=1;                                                    //1ms时基标志位
  80. }
  81. /*****************时基处理函数**********************/
  82. void SysTick_intgnd(void)
  83. {
  84.         if(f_systick_1ms==1)
  85.         {
  86.                 f_systick_1ms=0;
  87.                 cnt_systick_2ms++;                  
  88.                 if(cnt_systick_2ms==2)
  89.                 {
  90.                         cnt_systick_2ms=0;
  91.                         f_systick_2ms=1;                                                    //按键扫描标志位
  92.                 }
  93.                 cnt_systick_4ms++;                  
  94.                 if(cnt_systick_4ms==4)
  95.                 {
  96.                         cnt_systick_4ms=0;
  97.                         f_systick_4ms=1;                                                    //数码管扫描标志位
  98.                 }
  99.                 cnt_systick_10ms++;
  100.                 if(cnt_systick_10ms==10)
  101.                 {
  102.                         cnt_systick_10ms=0;
  103.                         f_systick_10ms=1;
  104.                         cnt_systick_1s++;
  105.                         if(cnt_systick_1s==100)  
  106.                         {
  107.                                 cnt_systick_1s=0;
  108.                                 f_systick_1s=1;                                                   //时钟1s更新一次标志位
  109.                         }
  110.                 }
  111.                 cnt_systick_101ms++;
  112.                 if(cnt_systick_101ms==101)
  113.                 {
  114.                         cnt_systick_101ms=0;
  115.                         flag_Alarm_blink = ~ flag_Alarm_blink;                             //闹钟报警标志位
  116.                         cnt_systick_505ms++;
  117.                         if(cnt_systick_505ms==5)  
  118.                         {
  119.                                 cnt_systick_505ms=0;
  120.                                 f_systick_505ms=1;

  121.                         }       
  122.                 }                                                            
  123.         }
  124. }
  125.                                                   
  126. /******************液晶写入************************/
  127. write_1602com(uchar com)//液晶写入指令函数
  128. {
  129.         rs=0;//置为写入命令
  130.         P0=com;//送入数据
  131.         delay(1);
  132.         en=1;//拉高使能端
  133.         delay(1);
  134.         en=0;//完成高脉冲
  135. }
  136. write_1602dat(uchar dat)
  137. {
  138.         rs=1;//置为写入数据
  139.         P0=dat;//送入数据
  140.         delay(1);
  141.         en=1;
  142.         delay(1);
  143.         en=0;
  144. }
  145. /*********************over***********************/
  146. /********************ds1302****************************/
  147. void write_byte(uchar dat)
  148. {
  149.         ACC=dat;
  150.         RST=1;
  151.         for(a=8;a>0;a--)
  152.         {
  153.                 IO=ACC0;
  154.                 SCLK=0;
  155.                 SCLK=1;
  156.                 ACC=ACC>>1;
  157.         }
  158. }
  159. uchar read_byte()
  160. {
  161.         RST=1;
  162.         for(a=8;a>0;a--)
  163.         {
  164.                 ACC7=IO;
  165.                 SCLK=1;
  166.                 SCLK=0;
  167.                 ACC=ACC>>1;

  168.         }
  169.         return (ACC);
  170. }
  171. void write_1302(uchar add,uchar dat)
  172. {

  173.         RST=0;
  174.         SCLK=0;
  175.         RST=1;
  176.         write_byte(add);
  177.         write_byte(dat);
  178.         SCLK=1;
  179.         RST=0;
  180. }
  181. uchar read_1302(uchar add)
  182. {
  183.         uchar temp;
  184.         RST=0;
  185.         SCLK=0;
  186.         RST=1;
  187.         write_byte(add);
  188.         temp=read_byte();
  189.         SCLK=1;
  190.         RST=0;
  191.         return(temp);
  192. }
  193. uchar BCD_Decimal(uchar bcd)
  194. {
  195. uchar Decimal;
  196. Decimal=bcd>>4;
  197. return(Decimal=Decimal*10+(bcd&=0x0F));
  198. }
  199. void ds1302_init()
  200. {
  201. RST=0;
  202. SCLK=0;
  203. write_1302(0x80,miao|0x00);//允许写
  204. }


  205.        

  206. void write_sfm(uchar add,uchar dat)//写时分秒
  207. {
  208.         uchar gw,sw;
  209.         gw=dat%10;
  210.         sw=dat/10;
  211.         write_1602com(er+add);
  212.         write_1602dat(0x30+sw);
  213.         write_1602dat(0x30+gw);
  214.                

  215. }
  216. void write_nyr(uchar add,uchar dat)                //写年月日
  217. {
  218.         uchar gw,sw;
  219.         gw=dat%10;
  220.         sw=dat/10;
  221.         write_1602com(yh+add);
  222.         write_1602dat(0x30+sw);
  223.         write_1602dat(0x30+gw);
  224.         write_1602com(yh+6);

  225. }
  226. void write_week(uchar week)//写星期函数
  227. {
  228.         write_1602com(yh+0x0d);
  229.         switch(week)
  230.         {                                             
  231.                 case 1:write_1602dat('M');//delay(5);
  232.                            write_1602dat('O');//delay(5);
  233.                            write_1602dat('N');
  234.                            break;
  235.           
  236.                 case 2:write_1602dat('T');//delay(5);
  237.                            write_1602dat('U');//delay(5);
  238.                            write_1602dat('E');
  239.                            break;
  240.                
  241.                 case 3:write_1602dat('W');//delay(5);
  242.                            write_1602dat('E');//delay(5);
  243.                            write_1602dat('D');
  244.                            break;
  245.                
  246.                 case 4:write_1602dat('T');//delay(5);
  247.                            write_1602dat('H');//delay(5);
  248.                            write_1602dat('U');
  249.                            break;
  250.                
  251.                 case 5:write_1602dat('F');//delay(5);
  252.                            write_1602dat('R');//delay(5);
  253.                            write_1602dat('I');
  254.                            break;
  255.                
  256.                 case 6:write_1602dat('S');//delay(5);
  257.                            write_1602dat('T');//delay(5);
  258.                            write_1602dat('A');
  259.                            break;
  260.                
  261.                 case 7:write_1602dat('S');//delay(5);
  262.                            write_1602dat('U');//delay(5);
  263.                            write_1602dat('N');
  264.                            break;


  265. }



  266. }
  267. lcd_init()//液晶初始化函数
  268. {      wr=0;
  269.         write_1602com(0x38);//设置液晶工作模式
  270.         write_1602com(0x0c);//开显示不显示光标
  271.         write_1602com(0x06);//整屏不移动,指针加一
  272.         write_1602com(0x01);
  273.         delay(10);
  274. //        write_1602com(yh+2);//字符写入的位置
  275. //        for(a=0;a<14;a++)
  276. //        {
  277. //        write_1602dat(tab1[a]);
  278. //        //delay(3);
  279. //        }
  280. //        write_1602com(er+4);
  281. //        for(a=0;a<8;a++)
  282. //        {
  283. //        write_1602dat(tab2[a]);
  284. //        //delay(3);
  285. //        }

  286. }
  287. void keyscan()
  288. {
  289.    //key=0;
  290.    if(key==0)
  291.    {
  292.                    delay(5);
  293.                 if(key==0)
  294.                 {
  295.                         TR0=0;
  296.                         TR1=0;
  297.                         write_1602com(0x01);
  298.                         delay(1);
  299.                        
  300.                          if(keyvalue==2)
  301.                                 keyvalue=0;
  302.                          keyvalue++;         //设置菜单界面
  303.                 }
  304.                   
  305.    }
  306.    
  307.    switch(keyvalue)
  308.    {
  309.               case        0:
  310.            case 1:                //钟表
  311.            {
  312.                 TR0=1;TR1=0;
  313.                 if(key1==0)//key1为功能键
  314.                 {
  315.                 delay(5);
  316.                
  317.                 if(key1==0)
  318.                 {
  319.                 TR0=0;
  320.                 TR1=0;
  321.                  while(!key1);
  322.                 key1n++;
  323.                 if(key1n==9)
  324.                         key1n=1;
  325.                 }
  326.                 }       
  327.                 switch(key1n)
  328.                 {
  329.                          
  330.                         case 1:
  331.                         {
  332.                         TR0=0; //关闭定时器
  333.                         TR1=0;
  334.                         write_1602com(er+0x0b);//写入光标位置
  335.                         delay(5);
  336.                            write_1602com(0x0f);//设置光标为闪烁
  337.                         delay(5);
  338.                            temp=(miao)/10*16+(miao)%10;
  339.                            write_1302(0x8e,0x00);
  340.                            write_1302(0x80,0x80|temp);//miao
  341.                            write_1302(0x8e,0x80);
  342.                          }
  343.                            break;
  344.                         case 2:
  345.                         TR0=0; //关闭定时器
  346.                         TR1=0;
  347.                           write_1602com(er+8);//fen
  348.                        
  349.                      //write_1602com(0x0f);
  350.                         break;
  351.                         case 3:
  352.                         TR0=0; //关闭定时器
  353.                         TR1=0;
  354.                          write_1602com(er+5);//shi
  355.                      //write_1602com(0x0f);
  356.                         break;
  357.                         case 4:
  358.                         TR0=0; //关闭定时器
  359.                         TR1=0;
  360.                          write_1602com(yh+0x0f);//week
  361.                      //write_1602com(0x0f);
  362.                         break;
  363.                         case 5:
  364.                         TR0=0; //关闭定时器
  365.                         TR1=0;
  366.                          write_1602com(yh+0x0b);//ri
  367.                      //write_1602com(0x0f);
  368.                         break;
  369.                         case 6:
  370.                         TR0=0; //关闭定时器
  371.                         TR1=0;
  372.                          write_1602com(yh+0x08);//yue
  373.                      //write_1602com(0x0f);
  374.                         break;
  375.                         case 7:
  376.                         TR0=0; //关闭定时器
  377.                         TR1=0;
  378.                          write_1602com(yh+0x05);//nian
  379.                      //write_1602com(0x0f);
  380.                         break;
  381.                         case 8:
  382.                         write_1602com(0x0c);//设置光标不闪烁
  383.                         TR0=1;//打开定时器
  384.                         temp=(miao)/10*16+(miao)%10;
  385.                            write_1302(0x8e,0x00);
  386.                            write_1302(0x80,0x00|temp);//miao
  387.                            write_1302(0x8e,0x80);
  388.             break;
  389.                                        
  390.        
  391.                                                                                                                
  392.                                
  393.                 }
  394.        

  395.                 if(key1n!=0)//当key1按下以下。再按以下键才有效
  396.                 {
  397.                
  398.                 if(key2==0)  //上调键
  399.                 {
  400.                 delay(5);
  401.                 if(key2==0)
  402.                 {
  403.                 while(!key2);
  404.                 switch(key1n)
  405.                 {
  406.                 case 1:miao++;
  407.                                 if(miao==60)
  408.                                         miao=0;
  409.                                 write_sfm(0x0a,miao);//写入新的秒数
  410.                                 temp=(miao)/10*16+(miao)%10;
  411.                                    write_1302(0x8e,0x00);
  412.                                    write_1302(0x80,0x80|temp);
  413.                                    write_1302(0x8e,0x80);
  414.                                 write_1602com(er+0x0b);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
  415.                                 //write_1602com(0x0b);
  416.                                 break;
  417.                 case 2:fen++;
  418.                                 if(fen==60)
  419.                                         fen=0;
  420.                                 write_sfm(0x07,fen);
  421.                                 temp=(fen)/10*16+(fen)%10;
  422.                                    write_1302(0x8e,0x00);
  423.                                    write_1302(0x82,temp);
  424.                                    write_1302(0x8e,0x80);
  425.                                 write_1602com(er+8);
  426.                                 break;
  427.                 case 3:shi++;
  428.                                 if(shi==24)
  429.                                         shi=0;
  430.                                 write_sfm(4,shi);
  431.                                 temp=(shi)/10*16+(shi)%10;
  432.                                    write_1302(0x8e,0x00);
  433.                                    write_1302(0x84,temp);
  434.                                    write_1302(0x8e,0x80);
  435.                                 write_1602com(er+5);
  436.                                 break;
  437.                 case 4:week++;
  438.                                 if(week==8)
  439.                                         week=0;
  440.                                         write_week(week);
  441.                                
  442.                                 write_1602com(yh+0x0f);
  443.                                 break;
  444.                 case 5:ri++;
  445.                                 if(ri==31)
  446.                                         ri=0;
  447.                                 write_nyr(10,ri);
  448.                                 temp=(ri)/10*16+(ri)%10;
  449.                                    write_1302(0x8e,0x00);
  450.                                    write_1302(0x86,temp);
  451.                                    write_1302(0x8e,0x80);
  452.                                 write_1602com(yh+11);
  453.                                 break;
  454.                 case 6:yue++;
  455.                                 if(yue==13)
  456.                                         yue=0;
  457.                                 write_nyr(7,yue);
  458.                                 temp=(yue)/10*16+(yue)%10;
  459.                                    write_1302(0x8e,0x00);
  460.                                    write_1302(0x88,temp);
  461.                                    write_1302(0x8e,0x80);
  462.                                 write_1602com(yh+8);
  463.                                 break;
  464.                 case 7:nian++;
  465.                          if(nian==100)
  466.                                 nian=0;
  467.                                 write_nyr(4,nian);
  468.                                 write_1602com(yh+5);
  469.                                 break;
  470.                                
  471.        
  472.                 } //switchkeyln
  473.        
  474.                  }//key2
  475.        
  476.                 }
  477.                 if(key3==0)
  478.                 {
  479.                 delay(5);
  480.                 if(key3==0)
  481.                 {
  482.                 while(!key3);
  483.                 switch(key1n)
  484.                 {
  485.                         case 1:miao--;
  486.                                         if(miao==-1)
  487.                                                 miao=59;
  488.                                 write_sfm(0x0a,miao);//写入新的秒数
  489.                                 write_1602com(er+0x0b);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
  490.                                 //write_1602com(0x0b);
  491.                                 break;
  492.                         case 2:fen--;
  493.                                         if(fen==-1)
  494.                                                 fen=59;
  495.                                 write_sfm(7,fen);
  496.                                 temp=(fen)/10*16+(fen)%10;
  497.                                    write_1302(0x8e,0x00);
  498.                                    write_1302(0x82,temp);
  499.                                    write_1302(0x8e,0x80);
  500.                                 write_1602com(er+8);
  501.                                 break;
  502.        
  503.                         case 3:shi--;
  504.                                    if(shi==-1)
  505.                                                 shi=23;
  506.                                 write_sfm(4,shi);
  507.                                 temp=(shi)/10*16+(shi)%10;
  508.                                    write_1302(0x8e,0x00);
  509.                                    write_1302(0x84,temp);
  510.                                    write_1302(0x8e,0x80);
  511.                                 write_1602com(er+5);
  512.                                 break;
  513.                         case 4:week--;
  514.                                         if(week==-1)
  515.                                                 week=7;
  516.                                 write_week(week);
  517.                                 write_1602com(yh+0x0f);
  518.                                 break;
  519.                         case 5:ri--;
  520.                                         if(ri==-1)
  521.                                                 ri=30;
  522.                                 write_nyr(10,ri);
  523.                                 temp=(ri)/10*16+(ri)%10;
  524.                                    write_1302(0x8e,0x00);
  525.                                    write_1302(0x86,temp);
  526.                                    write_1302(0x8e,0x80);
  527.                                 write_1602com(yh+11);
  528.                                 break;
  529.                         case 6:yue--;
  530.                                         if(yue==-1)
  531.                                                 yue=12;
  532.                                 write_nyr(7,yue);
  533.                                 temp=(yue)/10*16+(yue)%10;
  534.                                    write_1302(0x8e,0x00);
  535.                                    write_1302(0x88,temp);
  536.                                    write_1302(0x8e,0x80);
  537.                                 write_1602com(yh+8);
  538.                                 break;       
  539.                         case 7:nian--;
  540.                          if(nian==-1)
  541.                                 nian=99;
  542.                                 write_nyr(4,nian);
  543.                                 write_1602com(yh+5);
  544.                                 break;
  545.                                
  546.                                        
  547.                 } //switchkeyln
  548.        
  549.                 }
  550.        
  551.                 }        //key3
  552.        
  553.                 }
  554.            }//case1 菜单
  555.            break;
  556.            case 2:
  557.            {
  558.                           
  559.                            static uint data count;
  560.                         TR0=0;TR1=1;
  561.                        
  562.                         SysTick_intgnd();
  563.                         if(key1==0)//秒表计时开始
  564.                         {
  565.                         delay(5);
  566.                         if(key1==0)
  567.                                 {
  568.                                 write_1602com(0x01);
  569.                                 delay(1);
  570.                                 swatch_Start_Flag =1;
  571.                                 }
  572.                         }
  573.                         if(key2==0)//秒表计时结束
  574.                         {
  575.                         delay(5);
  576.                         if(key2==0)
  577.                                 swatch_Start_Flag =0;
  578.                         }
  579.                         if(key3==0)//复位
  580.                         {
  581.                         delay(5);
  582.                         if(key3==0)
  583.                                 swatch_Start_Flag =0;
  584.                                 count=0;
  585.                         }                
  586.                         if(swatch_Start_Flag ==1)
  587.                         {
  588.                                 if(f_systick_10ms == 1)                                         //产生跑秒
  589.                                 {       
  590.                                         f_systick_10ms = 0;               
  591.                                   count++;
  592.                                         if(count==9999)        count = 0;
  593.                                 }
  594.                         }
  595.                         ge=count%10;
  596.                         shi=count/10%10;
  597.                         bai=count/100%10;
  598.                         qian=count/1000;
  599.                 //        lcd_init();
  600.                         write_1602com(yh+3);
  601.                         write_1602dat(ge+0x30);
  602.                         write_1602com(yh+2);
  603.                         write_1602dat(shi+0x30);
  604.                         write_1602com(yh+1);
  605.                         write_1602dat(bai+0x30);
  606.                         write_1602com(yh+0);
  607.                         write_1602dat(qian+0x30);

  608.            }
  609.            break;
  610.    
  611.    }

  612. }
  613. void init()
  614. {
  615.         TMOD=0x11;
  616.         TH0=0;
  617.         TL0=0;
  618.         EA=1;
  619.         ET0=1;
  620.         //TR0=1;



  621. }

  622. //void cmg(void)//数码管锁存函数
  623. //{
  624. //dula=1;
  625. //P0=0x00;
  626. //dula=0;
  627. //wela=1;
  628. //P0=0x00;
  629. //wela=0;
  630. //}
  631. void timer0() interrupt 1
  632. {
  633. miao = BCD_Decimal(read_1302(0x81));
  634.         fen = BCD_Decimal(read_1302(0x83));
  635.         shi  = BCD_Decimal(read_1302(0x85));
  636.         ri  = BCD_Decimal(read_1302(0x87));
  637.         yue = BCD_Decimal(read_1302(0x89));
  638.         nian=BCD_Decimal(read_1302(0x8d));
  639.         week=BCD_Decimal(read_1302(0x8b));
  640.         //keyscan();       
  641.                 write_sfm(10,miao);
  642.         write_1602com(er+0x09);
  643.         write_1602dat(':');
  644.         write_sfm(7,fen);
  645.         write_1602com(er+0x06);
  646.         write_1602dat(':');
  647.         write_sfm(4,shi);
  648.        
  649.         write_nyr(4,nian);
  650.         write_1602com(yh+0x06);
  651.         write_1602dat('-');
  652.         write_nyr(10,ri);
  653.     write_nyr(7,yue);
  654.         write_1602com(yh+0x09);
  655.         write_1602dat('-');
  656.         write_week(week);
  657. }
  658. void main()
  659. {

  660.   // cmg();//数码管锁存
  661.         lcd_init();
  662.         ds1302_init();
  663.         init();
  664.         Timer1_Init();
  665.         SysTick_intgnd();
  666.         while(1)
  667.         {
  668.                 //TH0=(65536-60000)/256;
  669.         //TL0=(65536-60000)%256;
  670. //         if(f_systick_1ms==1)
  671. //         timer0();


  672. keyscan();
  673.        

  674.     }
  675. }
复制代码

所有资料51hei提供下载:
【实验104】DS1302时钟显示.rar (294.79 KB, 下载次数: 17)



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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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