久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5809|回復(fù): 1
收起左側(cè)

我的小制作基于51單片機的數(shù)字時鐘

[復(fù)制鏈接]
ID:72519 發(fā)表于 2015-1-21 17:44 | 顯示全部樓層 |閱讀模式
通過幾天的調(diào)試用,單片機AT89C52,LCD液晶屏LC1602,溫度采集模塊DS18B20,時鐘模塊DS1302,和三個按鍵,以及一些電子元件完成了數(shù)字時鐘系統(tǒng)的設(shè)計。在一塊液晶顯示屏上實現(xiàn)動態(tài),時、分、秒、年、月、日、星期、溫度數(shù)據(jù)的顯示, 通過三個按鍵,S1調(diào)時鍵、S2時間加鍵、S3時間減鍵、實現(xiàn)時鐘的年、月、日、星期、時、分、秒、的調(diào)整。本系統(tǒng)設(shè)計大部分功能有軟件來實現(xiàn),使電路簡單明了。由于以前從沒有過單片機相關(guān)產(chǎn)品的制作經(jīng)驗,所以這個設(shè)計共用了約30多個鐘。在做這設(shè)計之前軟件思路非常模糊代碼都是想到哪寫到哪,結(jié)果寫到最后調(diào)試時出現(xiàn)了大把錯誤,在調(diào)試程序中花了大把的時間,調(diào)程序真的是個考驗?zāi)托牡墓ぷ鞲愕奈以译娔X的想法都有了。因為是自己一個人制作的出現(xiàn)了錯誤只好在網(wǎng)上找資料,閱讀別人寫過的代碼,經(jīng)過長時間的修改終于完成了這次制作。設(shè)計因為是業(yè)余學(xué)習(xí)的單片機加上這斷時間工作比較忙,所以為了完成這個產(chǎn)品的制作可沒少睡過覺,幾乎每天都沒在2點鐘前睡過。附原代碼
  1. #include"reg52.h"

  2. #include"12864.h"

  3. #include"ds1302.h"

  4. #include"ds18b20.h"

  5. #include"intrins.h"//_nop_聲明



  6. #define uchar unsigned char

  7. #define uint unsigned int

  8. sbit DQ=P3^7;

  9. sbit rs=P3^0;

  10. sbit rw=P3^1;

  11. sbit en=P3^2;

  12. uchar tou;



  13. sbit io=P3^6;

  14. sbit rst=P3^4;      //定義各芯片跟單片機連接的定義

  15. sbit sck=P3^5;

  16. sbit s1=P1^0;      //定義各芯片跟單片機連接的定義

  17. sbit s2=P1^4;

  18. sbit s3=P1^7; //定義各芯片跟單片機的連接的定義

  19. uchar tung=0;  //定義

  20. uchar tab4[]={0x82,0x85,0x88,0x8f,0xc0,0xc3,0xc6};//用來存放年月日星期時分秒的地址

  21. char tab[]={13,5,4,5,00,59,33};//年 月 日 周 時 分 秒的初值

  22. uchar tab1[]; //

  23. uchar write_add[7]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80}; //寫寄存器地址

  24. uchar read_add[7]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81};//存放從1302中讀數(shù)寄存器地址

  25. void write_byte(uchar);            //寫數(shù)據(jù)函數(shù)

  26. uchar read_byte(void);          //讀數(shù)據(jù)函數(shù)

  27. uchar readtemperature(void);//一次性讀出溫度



  28. void write_ds1302_byte(uchar);    //單字節(jié)寫函數(shù)

  29. void write_ds1302(uchar add,uchar dat);//寫 /寫地址數(shù)據(jù)+寫數(shù)據(jù)函數(shù)

  30. uchar read_ds1302(uchar);//         單字節(jié)讀函數(shù)

  31. void flx(uchar j);           //

  32. void key(void);     //按鍵函數(shù)

  33. void write_ds1302_byte(uchar dat)

  34. {

  35.          uchar i;

  36.          for(i=0;i<8;i++)                      //單字節(jié)寫

  37.          {

  38.                    sck=0;

  39.                    io=dat&0x01;

  40.                    dat=dat>>1;

  41.                    sck=1;

  42.          }

  43.                   

  44. }

  45. void write_ds1302(uchar add,uchar dat)

  46. {

  47.         rst=0;

  48.          _nop_();

  49.          sck=0;

  50.          _nop_();

  51.          rst=1;                      //寫地址數(shù)據(jù)+寫數(shù)據(jù)函數(shù)

  52.          _nop_();

  53.          write_ds1302_byte(add);               //寫地址

  54.          write_ds1302_byte(dat);        //寫數(shù)據(jù)

  55.          rst=0;

  56.          _nop_();

  57.          io=1;

  58.          sck=1;



  59. }                                                                                             

  60. uchar read_ds1302(uchar add)

  61. {        uchar i,value;

  62.          rst=0;                      //

  63.          _nop_();

  64.          sck=0;

  65.          _nop_();     //單字節(jié)讀數(shù)據(jù)函數(shù)

  66.          rst=1;

  67.          _nop_();

  68.          write_ds1302_byte(add );

  69.          for(i=0;i<8;i++)

  70.          {

  71.                    value=value>>1;

  72.                    sck=0;

  73.                    if(io)                                         //因為是串口所以要分8次讀數(shù)據(jù)

  74.                    value=value|0x80;

  75.                    sck=1;

  76.          }

  77.          rst=0;

  78.          _nop_();

  79.          sck=0;

  80.          _nop_();

  81.          sck=1;

  82.          io=1;

  83.          return value;

  84.          }

  85. void read_ds1302_1(void)//一次讀出年月日 時分秒函數(shù)

  86. {

  87.          uchar i,shi,ge,tun;

  88.          write_ds1302(0x8e,0x00);//去除寫保護

  89.          for(i=0;i<7;i++)

  90.          {

  91.                    tun=read_ds1302(read_add[i]);     //一次將年月日從DS1302中讀出送到數(shù)組中

  92.                    ge=tun%16;

  93.                    shi=tun/16;                                                           //將BCD碼分成十位和個位

  94.                    tab[i]=shi*10+ge;                                     //再換成十進制存到數(shù)組tab中



  95.          }

  96.                    write_ds1302(0x8e,0x00);//加寫保護

  97. }

  98. void write_ds1302_1(void)

  99. {                                                                                              //將10進制數(shù)送到1602;

  100.        write_com(0x80+0x40+6);//秒的位置

  101.          write_dat(tab[6]/10+0x30);

  102.          write_dat(tab[6]%10+0x30);



  103.          write_com(0x80+0x40+3);//

  104.          write_dat(tab[5]/10+0x30);  //分的位置

  105.          write_dat(tab[5]%10+0x30);

  106.                               //將十進制的數(shù)據(jù)換成1602的顯示碼送到顯示屏

  107.          write_com(0x80+0x40+0);// //時的地址

  108.          write_dat(tab[4]/10+0x30);    //顯示屏的第二排要加0x80+40

  109.          write_dat(tab[4]%10+0x30);



  110.          write_com(0x80+2);//

  111.          write_dat(tab[0]/10+0x30);//年的地址

  112.          write_dat(tab[0]%10+0x30);



  113.          write_com(0x80+5);// 顯示屏 的第一排地址要加0x80;

  114.          write_dat(tab[1]/10+0x30);

  115.          write_dat(tab[1]%10+0x30);                   //月的地址

  116.                                                                                    

  117.          write_com(0x80+8);//   日的地址

  118.          write_dat(tab[2]/10+0x30);

  119.          write_dat(tab[2]%10+0x30);



  120.          write_com(0x80+15);                        //星期的地址

  121.          write_dat(tab[3]%10+0x30);









  122. }

  123. void set_rtc(void)         //一次設(shè)置初始時間年月日函數(shù)

  124. {

  125.          uchar i,j;

  126.         

  127.          for(i=0;i<7;i++)

  128.          {

  129.                  j=tab[i]/10;         //將設(shè)置的年月日時間2013—4-25 00-14-00中分解出十位放入J中

  130.                    tab1[i]=tab[i]%10; //將設(shè)置的年月日時間2013—4-25 00-14-00中分解出個位再放入time_data[]數(shù)組中

  131.                    tab1[i]=tab1[i]+j*16;//將十進制的個位和十位轉(zhuǎn)換為BCD碼



  132.          }

  133.          write_ds1302(0x8e,0x00);//去除寫保護

  134.          for(i=0;i<7;i++)

  135.          {

  136.          write_ds1302(write_add[i],tab1[i]); //寫要設(shè)置初始時間日期的操作寄存器的地址

  137.          }

  138.          write_ds1302(0x8e,0x00);//加寫保護

  139. }

  140.   

  141.   void ds1302_init(void)

  142.   {



  143.   



  144.         key();          //按鍵函數(shù)

  145.    read_ds1302_1();//一次讀出年月日 時分秒函數(shù)

  146.    write_ds1302_1(); //時間的顯示函數(shù)

  147.                   

  148. }      

  149. void key(void)

  150. {      

  151.                             //按鍵函數(shù)

  152.          if(s1==0)             //如果S1按下

  153.          {

  154.                    delay(3);    //延時去抖

  155.                   if(s1==0)                                                  

  156.                    {      

  157.                             while(!s1);   //

  158.                               tung=0;            //tung用來確定光標(biāo)的位置

  159.                                     

  160.                             while(tung<=6)            //循環(huán)7次   時分秒年月日星期

  161.                             {      

  162.                                                

  163.                              

  164.                                          if(s2==0)

  165.                                                {

  166.                                                         delay(3);

  167.                                                         if(s2==0)//去抖動延時

  168.                                                         {

  169.                                                                  while(!s2);    // 檢測按鍵是否放開

  170.                                                                  tab[tung]++; //如果+鍵按下加1

  171.                                                         }

  172.                     }

  173.                                                if(s3==0)

  174.                                                {

  175.                                                         delay(3);    // 檢測按鍵是否放開

  176.                                                         if(s3==0)

  177.                                                         {

  178.                                                                  while(!s3); //按鍵是否松手

  179.                                                                  tab[tung]--;        //如果—鍵按下減1

  180.                                                         }

  181.                                                }

  182.                                       

  183.                                         switch(tung)

  184.                                         {                                                 //通過tung的值確定光標(biāo)的位置

  185.                                         case 0:

  186.                                                           if(tab[tung]<3)         //如果tung=0;則表示正在調(diào)年讓年在2004到2098這個范圍內(nèi)

  187.                                                           tab[tung]=98;

  188.                                                           if(tab[tung]>98)

  189.                                                           tab[tung]=4;

  190.                                                           break;

  191.                                                          

  192.                                        case 1:

  193.                                                        if(tab[tung]<1)

  194.                                                                tab[tung]=12;

  195.                                                           if(tab[tung]>12)       //如果tung=1;則表示正在調(diào)月讓月在1到12這個范圍內(nèi)

  196.                                                             tab[tung]=1;

  197.                                                            break;

  198.                                        case 2:

  199.                                                        if(tab[tung]==0)

  200.                                                                tab[tung]=31;

  201.                                                           if(tab[tung]==32)       //如果tung=2;則表示正在調(diào)日讓在1到31這個范圍內(nèi)

  202.                                                                tab[tung]=1;

  203.                                                           break;

  204.                                        case 3:

  205.                                                       if(tab[tung]<1)

  206.                                                           tab[tung]=7;

  207.                                                          if(tab[tung]>7)   //如果tung =3則表示下在調(diào)星期讓在1到7這個范圍內(nèi)

  208.                                                           tab[tung]=1;

  209.                                                           break;

  210.                                    case 4:

  211.                                                       if(tab[tung]<0)

  212.                                                 tab[tung]=23;

  213.                                                          if(tab[tung]>23)         //如果tung=4則表示在調(diào)時讓時在1到23這個范圍內(nèi)

  214.                                                                 tab[tung]=0;

  215.                                                            break;

  216.                                       case 5:

  217.                                                       if(tab[tung]<0)

  218.                                                                 tab[tung]=59;

  219.                                                          if(tab[tung]>59)           //如果tung=5;則表示正在調(diào)分讓分在1到59這個范圍內(nèi)

  220.                                                                 tab[tung]=0;

  221.                                                            break;

  222.                                       default:

  223.                                                       if(tab[tung]<0)

  224.                                                                 tab[tung]=59;

  225.                                                          if(tab[tung]>59)           //如果tung=6;則表示正在調(diào)秒讓秒在1到59這個范圍內(nèi)

  226.                                                                 tab[tung]=0;

  227.                                                         break;

  228.                                         }

  229.                                        write_com(tab4[tung]);    //顯示正在調(diào)的位置         

  230.                                        flx(tab[tung]);    //將數(shù)據(jù)分離成1602的顯示碼并送到1602顯示屏

  231.                                          

  232.                                     

  233.                             if(s1==0)

  234.                                       {

  235.                                                 while(!s1);  //判斷是否調(diào)好了時間如果好了則跳出key

  236.                                               tung++;    //每按一下S1調(diào)式模式鍵則加一次如果到了7次跳出KEY函數(shù)

  237.                                       }                                 

  238.                                              

  239.                             }

  240.                            

  241.                    }

  242.                    write_com(0x0c);//調(diào)完了時間關(guān)閉光標(biāo)      

  243.                    set_rtc(); //把調(diào)好的時間數(shù)據(jù)送到DS1302芯片中

  244.          }

  245. }

  246. void flx(uchar j)

  247. {

  248.          uchar k,a;

  249.           write_com(0x0f);       //開光標(biāo)顯示指令

  250.           k=j/10;                 //分離十位跟個位

  251.           a=j%10;

  252.           if(tung!=3)        //年月日時分秒分離

  253.           {

  254.         

  255.                write_dat(k+0x30);    //將分離的十位跟個位換成LC1602能顯示的碼

  256.                     write_com(0x0c);//關(guān)光標(biāo)指令   

  257.                write_dat(a+0x30);



  258.          }

  259.          else

  260.         

  261.                    write_dat(a+0x30);      //星期分離

  262.                     

  263. }



  264. void delay1(uchar i)

  265. {

  266. while(i--);

  267. }

  268. void init_ds18b20(void)

  269. {

  270.   uchar n;

  271.   DQ=1;

  272.   delay1(8);

  273.   DQ=0;

  274.   delay1(80);                 //初始化函數(shù)

  275.   DQ=1;

  276.   delay1(8);

  277.   n=DQ;

  278.   delay(25);

  279. }

  280. void write_byte(uchar dat)

  281. {

  282.          uchar i;

  283.          for(i=0;i<8;i++)

  284.          {

  285.                    DQ=0;                              //寫函數(shù)

  286.                    DQ=dat&0x01;

  287.                    delay(4);

  288.                    DQ=1;

  289.                    dat>>=1;               //移一位

  290.         

  291.          }

  292.                    delay(4);

  293. }

  294. uchar read_byte(void)

  295. {

  296.          uchar i,value;

  297.          for(i=0;i<8;i++)

  298.          {

  299.                    DQ=0;                                     //讀數(shù)據(jù)函數(shù)

  300.                    value>>=1;                       //移1位

  301.                    DQ=1;

  302.                    if(DQ)

  303.                    value|=0x80;

  304.                    delay(4);

  305.          }

  306.          return value;

  307. }

  308. uchar readtemperature(void)//一次性讀出溫度

  309. {

  310.          uchar a,b;

  311.          init_ds18b20();

  312.          write_byte(0xcc);//跳過ROM

  313.          write_byte(0x44);//啟動溫度測量

  314.          delay1(300);

  315.          init_ds18b20();               //初始化



  316.          write_byte(0xcc);

  317.          write_byte(0xbe);//讀取溫度

  318.          a=read_byte();//高8位

  319.          b=read_byte();//

  320.         

  321.          b<<=4;                             //因不用小數(shù)部分所以移4位

  322.          b+=(a&0xf0)>>4;          //將存放低8位的個位和高8位的十位合到一塊

  323.        return b;

  324. }

  325. void xianshi(void)

  326. {

  327.          uchar temp,k,f;

  328.          temp=readtemperature();//將溫度保存到temp中

  329.          f=temp/10;                            //分離出十位跟個位

  330.          k=temp%10;

  331. write_com(0x80+0x40+10);//溫度顯示的位置                     

  332. write_dat(f+0x30);          //

  333. write_dat(k+0x30);





  334. }

  335. uchar tab1[]="20  -  -   week  ";  //屏上要固定顯示的字符

  336. uchar tab2[]="  :  :  ";

  337. void delay(uint x)

  338. {

  339.          uint a,b;

  340.          for(a=x;a--;a>0)                     //延時函數(shù)

  341.                    for(b=110;b>0;b--);

  342. }

  343. void write_com(uchar com)

  344. {

  345.          rs=0;

  346.          rw=0;                                                  //寫數(shù)據(jù)指令函數(shù)

  347.          P2=com;

  348.          delay(4);

  349.          en=1;

  350.          delay(4);

  351.          en=0;

  352. }

  353. void write_dat(uchar dat)

  354. {

  355.          rs=1;

  356.          rw=0;

  357.     P2=dat;

  358.          delay(4);                                  //寫數(shù)據(jù)函數(shù)

  359.          en=1;

  360.          delay(4);

  361.          en=0;



  362. }

  363. void init(void)

  364. {

  365.     write_com(0x38);

  366.          write_com(0x0c);//     //1602初始化函數(shù)

  367.          write_com(0x06);

  368.          write_com(0x01);

  369.          write_com(0x80);

  370. write_com(0x80);                           //第一行顯示的位置地址

  371. for(tou=0;tou<16;tou++)

  372.          {

  373.                    write_dat(tab1[tou]);  //顯示固定字符

  374.          }

  375. write_com(0x80+0x40);        //第二行顯示的位置地址

  376. for(tou=0;tou<8;tou++)

  377. {

  378.          write_dat(tab2[tou]);

  379.         

  380. }

  381. write_com(0x80+0x40+12);  

  382. write_dat(0xdf);//顯示溫度的小圓圈符號,0xdf是液晶屏字符庫的該符號地址碼

  383. write_dat(0x43); //顯示"C"符號,0x43是液晶屏字符庫里大寫C的地址碼   

  384. }

  385. main()

  386. {

  387.          init();//初始化顯示屏

  388.          set_rtc();       //設(shè)置ds1302時鐘芯片時間

  389. while(1)



  390.              ds1302_init();//初始化ds1302時鐘芯片

  391.                    xianshi();      //溫度顯示函數(shù)

  392.                   

  393. }

  394.         



  395. }

  396. 通過這次的制作讓我全面的了解單片機相關(guān)產(chǎn)品的開發(fā)流程,及一些常用芯片驅(qū)動程序的編寫。始我在單片機上的學(xué)習(xí)更上一層樓!
復(fù)制代碼




回復(fù)

使用道具 舉報

ID:260199 發(fā)表于 2017-12-11 15:58 | 顯示全部樓層
666,有沒有整點提醒功能
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: a在线视频| 中文字幕视频在线看5 | 成人一区在线观看 | xxxxx黄色片 欧美一区免费 | 欧美簧片 | 国产a爽一区二区久久久 | 中文字幕久久久 | 中文字幕视频三区 | 亚洲夜射 | 亚洲高清在线 | 超碰免费在线 | 九九综合 | 精品无码久久久久久国产 | 久久久黑人 | 欧美精品久久久久久久久久 | 日韩av在线中文字幕 | 在线视频一区二区 | 久久99精品久久久久婷婷 | 99视频精品| 美女黄视频网站 | 视频在线观看亚洲 | 中文一区二区 | 国产精品一区二区精品 | 国产十日韩十欧美 | 国产69精品久久99不卡免费版 | 久久精品亚洲 | 人人草天天草 | 成人欧美一区二区三区1314 | 亚洲视频在线播放 | 久久精品久久精品 | 国产精品国产精品国产专区不片 | 大学生a级毛片免费视频 | 久久精品国产免费一区二区三区 | 99久久精品免费看国产四区 | 国产精品久久久久久 | 亚洲精品自在在线观看 | 成人一区二 | 国产欧美精品一区二区色综合朱莉 | 国产毛片av| 国产91在线 | 亚洲 | 国产高清免费 |