找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4451|回复: 2
收起左侧

基于51单片机系列89C52单片机的设计

[复制链接]
ID:71870 发表于 2015-1-17 11:05 | 显示全部楼层 |阅读模式
  1. //************1602液晶显示程序************

  2. #include<reg52.h>

  3. #include <intrins.h>


  4. #define uchar unsigned char

  5. #define  uint unsigned  int


  6. uchara,miao,shi,fen,ri,yue,nian,week,flag1,key1n,temp;

  7. #define yh 0x80                              

  8. #define er 0x80+0x40


  9. //DS1302时钟芯片与C51之间的引脚连接定义

  10. sbit IO=P1^1;

  11. sbit SCLK=P1^0;

  12. sbit RST=P1^2;


  13. sbit ACC0=ACC^0;

  14. sbit ACC7=ACC^7;


  15. //校时按键与C51的引脚连接定义

  16. sbit key1=P1^5;                             //设置键

  17. sbit key2=P1^6;                             //加键

  18. sbit key3=P1^7;                             //减键

  19. //sbit buzzer=P1^3;                            //蜂鸣器,通过三极管9012驱动,端口低电平响                        


  20. typedef unsigned char BYTE;

  21. typedef unsigned int WORD;

  22. typedef bit BOOL ;

  23. extern GetTemp(void);

  24. extern unsigned int  idata Temperature;

  25. extern Init18b20 ();


  26. //unsigned char  a,b,c;


  27. sbit   lcden=P2^7;      //液晶使能位

  28. sbit   lcdrw=P2^5;     //液晶读写位

  29. sbit   lcdrs=P2^6;      //数据命令选择位

  30.   uchar code tab1[]={"2011-07-12 "};             //年显示的固定字符

  31.   uchar code tab2[]={"19:50:00"};                //时间显示的固定字符

  32.   

  33. void w_cmd(uint date);

  34. void w_data(uint date);


  35. /************定时器1子函数***********/

  36. void system_Ini()

  37. {

  38.    TMOD|= 0x11;

  39.    TH1=0x8e; //11.0592M

  40.    TL1=0x33;     

  41.        IE= 0x8A;     

  42.    TR1  = 1;


  43. }


  44. /************延时子函数***********/

  45. void delay(uchar x)

  46. {

  47. uchar y,z;

  48.    for(y=x;y>0;y--)

  49.          for(z=110;z>0;z--);

  50. }


  51. /*************** 液晶初始化和写命令及数据命令********************/

  52. void lcd_init()                                    

  53. {

  54.    lcden=0;               //初始使能端

  55.    lcdrw=0;                 // 写数据选择

  56.        w_cmd(0x38);                      //设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据

  57.        w_cmd(0x01);                      //清显示

  58.    w_cmd(0x0c);                     //开显示不显示光标

  59.        w_cmd(0x06);                      //整屏不移动,光标自动右移


  60.        w_cmd(yh+1);                      //日历显示固定符号从第一行第1个位置之后开始显示

  61.        for(a=0;a<14;a++)

  62.        {

  63.        w_data(tab1[a]);                      //向液晶屏写日历显示的固定符号部分

  64.        delay(3);

  65.        }

  66.        w_cmd(er+2);                       //时间显示固定符号写入位置,从第2个位置后开始显示

  67.        for(a=0;a<8;a++)

  68.        {

  69.        w_data(tab2[a]);                      //写显示时间固定符号,两个冒号

  70.        delay(3);

  71.        }


  72. }



  73. void w_cmd(uint date)     //“写”命令子程序

  74. {

  75.        lcdrs=0;

  76.        P0=date;

  77.        delay(5);

  78.        lcden=1;

  79.        delay(5);

  80.        lcden=0;

  81. }


  82. void w_data(uint date) //”写“数据子程序

  83. {

  84.    lcdrs=1;

  85.        P0=date;

  86.        delay(3);

  87.        lcden=1;

  88.        delay(5);

  89.        lcden=0;

  90. }


  91. /***************DS1302有关子函数********************/


  92. void write_byte(uchar dat)//写一个字节

  93. {

  94.        ACC=dat;

  95.        RST=1;

  96.        for(a=8;a>0;a--)

  97.        {

  98.               IO=ACC0;

  99.               SCLK=0;

  100.               SCLK=1;

  101.               ACC=ACC>>1;

  102.        }

  103. }

  104. uchar read_byte()                                   //读一个字节

  105. {

  106.        RST=1;

  107.        for(a=8;a>0;a--)

  108.        {

  109.               ACC7=IO;

  110.               SCLK=1;

  111.               SCLK=0;

  112.               ACC=ACC>>1;


  113.        }

  114.        return(ACC);

  115. }

  116. //----------------------------------------

  117. void write_1302(uchar add,uchar dat)                   //向1302芯片写函数,指定写入地址,数据

  118. {


  119.        RST=0;

  120.        SCLK=0;

  121.        RST=1;

  122.        write_byte(add);

  123.        write_byte(dat);

  124.        SCLK=1;

  125.        RST=0;

  126. }

  127. uchar read_1302(uchar add)                          //从1302读数据函数,指定读取数据来源地址

  128. {

  129.        uchartemp;

  130.        RST=0;

  131.        SCLK=0;

  132.        RST=1;

  133.        write_byte(add);

  134.        temp=read_byte();

  135.        SCLK=1;

  136.        RST=0;

  137.        return(temp);

  138. }

  139. uchar BCD_Decimal(uchar bcd)                //BCD码转十进制函数,输入BCD,返回十进制

  140. {

  141. uchar Decimal;

  142. Decimal=bcd>>4;

  143. return(Decimal=Decimal*10+(bcd&=0x0F));

  144. }

  145. //--------------------------------------

  146. void ds1302_init()                           //1302芯片初始化子函数(2010-01-07,12:00:00,week4)

  147. {

  148. RST=0;

  149. SCLK=0;


  150. write_1302(0x8e,0x00);                      //允许写,禁止写保护

  151. write_1302(0x80,0x00);                     //向DS1302内写秒寄存器80H写入初始秒数据00

  152. write_1302(0x82,0x53);                     //向DS1302内写分寄存器82H写入初始分数据00

  153. write_1302(0x84,0x19);                     //向DS1302内写小时寄存器84H写入初始小时数据12

  154. write_1302(0x8a,0x02);                     //向DS1302内写周寄存器8aH写入初始周数据4

  155. write_1302(0x86,0x12);                     //向DS1302内写日期寄存器86H写入初始日期数据07

  156. write_1302(0x88,0x07);                     //向DS1302内写月份寄存器88H写入初始月份数据01

  157. write_1302(0x8c,0x11);                     //向DS1302内写年份寄存器8cH写入初始年份数据10

  158. write_1302(0x8e,0x80);                      //打开写保护


  159. }


  160. /********温度显示子函数*********/

  161. void write_temp(uchar add,uchar dat)            //向LCD写温度数据,并指定显示位置

  162. {

  163.        uchargw,sw;

  164.        gw=dat%10;                            //取得个位数字

  165.        sw=dat/10;                             //取得十位数字

  166.        w_cmd(er+add);                  //er是头文件规定的值0x80+0x40

  167.        w_data(0x30+sw);                 //数字+30得到该数字的LCD1602显示码

  168.        w_data(0x30+gw);                 //数字+30得到该数字的LCD1602显示码

  169.    w_data(0xdf);                     //显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码

  170.       w_data(0x43);                   //显示"C"符号,0x43是液晶屏字符库里大写C的地址码         

  171. }            

  172. /******** 时间显示子函数*********/

  173. void write_sfm(uchar add,uchar dat)           //向LCD写时分秒,有显示位置加、现示数据,两个参数

  174. {

  175.        uchargw,sw;

  176.        gw=dat%10;                          //取得个位数字

  177.        sw=dat/10;                           //取得十位数字

  178.        w_cmd(er+add);                //er是头文件规定的值0x80+0x40

  179.        w_data(0x30+sw);               //数字+30得到该数字的LCD1602显示码

  180.        w_data(0x30+gw);               //数字+30得到该数字的LCD1602显示码

  181.                            

  182. }


  183. /********年、月、日显示子函数*********/

  184. void write_nyr(uchar add,uchar dat)           //向LCD写年月日,有显示位置加数、显示数据,两个参数

  185. {

  186.        uchargw,sw;

  187.        gw=dat%10;                         //取得个位数字

  188.        sw=dat/10;                          //取得十位数字

  189.        w_cmd(yh+add);               //设定显示位置为第一个位置+add

  190.        w_data(0x30+sw);               //数字+30得到该数字的LCD1602显示码

  191.        w_data(0x30+gw);               //数字+30得到该数字的LCD1602显示码

  192.       

  193. }

  194. /*******写星期子函数*********/

  195. void write_week(uchar week)                //写星期函数

  196. {

  197.        w_cmd(yh+0x0c);              //星期字符的显示位置

  198.        switch(week)

  199.        {

  200.               case 1:w_data('M');          //星期数为1时,显示

  201.                         w_data('O');

  202.                         w_data('N');

  203.                         break;

  204.          

  205.               case 2:w_data('T');           //星期数据为2时显示

  206.                         w_data('U');

  207.                         w_data('E');

  208.                         break;

  209.               

  210.               case 3:w_data('W');           //星期数据为3时显示

  211.                         w_data('E');

  212.                         w_data('D');

  213.                         break;

  214.               

  215.               case 4:w_data('T');            //星期数据为4是显示

  216.                         w_data('H');

  217.                         w_data('U');

  218.                         break;

  219.               

  220.               case 5:w_data('F');            //星期数据为5时显示

  221.                         w_data('R');

  222.                         w_data('I');

  223.                         break;

  224.               

  225.               case 6:w_data('S');            //星期数据为6时显示

  226.                         w_data('T');

  227.                         w_data('A');

  228.                         break;

  229.               

  230.               case 7:w_data('S');            //星期数据为7时显示

  231.                         w_data('U');

  232.                         w_data('N');

  233.                         break;


  234. }


  235. }

  236.                

  237.                /*******键盘扫描有关函数*********/

  238. void keyscan()

  239. {

  240.        if(key1==0)                          //key1为功能键(设置键)

  241.        {

  242.        delay(9);                            //延时,用于消抖动

  243.        if(key1==0)                          //延时后再次确认按键按下

  244.        {

  245. //  buzzer=0;                          //蜂鸣器短响一次

  246. //  delay(20);

  247. //  buzzer=1;

  248.        while(!key1);

  249.        key1n++;

  250.        if(key1n==9)

  251.               key1n=1;                      //设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环

  252.        switch(key1n)

  253.        {

  254.       

  255.        case1: TR0=0;                          //关闭定时器

  256.                      //TR1=0;

  257.                      w_cmd(er+0x09);         //设置按键按动一次,秒位置显示光标

  258.                    w_cmd(0x0f);            //设置光标为闪烁

  259.                    temp=(miao)/10*16+(miao)%10;    //秒数据写入DS1302

  260.                    write_1302(0x8e,0x00);

  261.                    write_1302(0x80,0x80|temp);//miao

  262.                  write_1302(0x8e,0x80);

  263.                    break;

  264.        case2:  w_cmd(er+6);             //按2次fen位置显示光标

  265.                      

  266.                   //write_1602com(0x0f);

  267.                      break;

  268.        case3: w_cmd(er+3);               //按动3次,shi

  269.                   //write_1602com(0x0f);

  270.                      break;

  271.        case4: w_cmd(yh+0x0e);           //按动4次,week

  272.                   //write_1602com(0x0f);

  273.                      break;

  274.        case5: w_cmd(yh+0x0a);           //按动5次,ri

  275.                   //write_1602com(0x0f);

  276.                      break;

  277.        case6: w_cmd(yh+0x07);           //按动6次,yue

  278.                   //write_1602com(0x0f);

  279.                      break;

  280.        case7: w_cmd(yh+0x04);           //按动7次,nian

  281.                   //write_1602com(0x0f);

  282.                      break;

  283.        case8:

  284.                      w_cmd(0x0c);             //按动到第8次,设置光标不闪烁

  285.                      TR0=1;//打开定时器

  286.         temp=(miao)/10*16+(miao)%10;

  287.                 write_1302(0x8e,0x00);

  288.                 write_1302(0x80,0x00|temp);//miao数据写入DS1302

  289.                 write_1302(0x8e,0x80);

  290.            break;                                                                                                      

  291.                      

  292.        }


  293.        }


  294.        }

  295. //------------------------------加键key2----------------------------         

  296.        if(key1n!=0)                     //当key1按下以下。再按以下键才有效(按键次数不等于零)

  297.        {


  298.        if(key2==0)                     //上调键

  299.        {

  300.        delay(10);

  301.        if(key2==0)

  302.        {

  303. //  buzzer=0;                      //蜂鸣器短响一次

  304. //  delay(20);

  305. //  buzzer=1;

  306.        while(!key2);

  307.        switch(key1n)

  308.        {

  309.        case1:miao++;                  //设置键按动1次,调秒

  310.               if(miao==60)

  311.                      miao=0;           

  312.                      write_sfm(0x08,miao);   

  313.                      temp=(miao)/10*16+(miao)%10;

  314.                    write_1302(0x8e,0x00);

  315.                    write_1302(0x80,temp);   

  316.                    write_1302(0x8e,0x80);

  317.                      w_cmd(er+0x09);

  318.                      //write_1602com(0x0b);

  319.                      break;

  320.        case2:fen++;

  321.               if(fen==60)

  322.                      fen=0;

  323.                      write_sfm(0x05,fen);         

  324.                      temp=(fen)/10*16+(fen)%10;  

  325.                    write_1302(0x8e,0x00);      

  326.                    write_1302(0x82,temp);      

  327.                    write_1302(0x8e,0x80);      

  328.                      w_cmd(er+6);     

  329.                      break;

  330.        case3:shi++;

  331.               if(shi==24)

  332.                      shi=0;

  333.                      write_sfm(2,shi);            

  334.                      temp=(shi)/10*16+(shi)%10;   

  335.                    write_1302(0x8e,0x00);      

  336.                    write_1302(0x84,temp);     

  337.                    write_1302(0x8e,0x80);      

  338.                      w_cmd(er+3);      

  339.                      break;

  340.        case4:week++;

  341.               if(week==8)

  342.                      week=1;

  343.            w_cmd(yh+0x0C) ;   

  344.                      write_week(week);      

  345.            temp=(week)/10*16+(week)%10;

  346.                    write_1302(0x8e,0x00);      

  347.                    write_1302(0x8a,temp);      

  348.                    write_1302(0x8e,0x80);      

  349.                      w_cmd(yh+0x0e);

  350.                      break;

  351.        case5:ri++;

  352.               if(ri==32)

  353.                      ri=1;

  354.                      write_nyr(9,ri);            

  355.                      temp=(ri)/10*16+(ri)%10;   

  356.                    write_1302(0x8e,0x00);     

  357.                    write_1302(0x86,temp);      

  358.                    write_1302(0x8e,0x80);      

  359.                      w_cmd(yh+10);      

  360.                      break;

  361.        case6:yue++;

  362.               if(yue==13)

  363.                      yue=1;

  364.                      write_nyr(6,yue);            

  365.                      temp=(yue)/10*16+(yue)%10;  

  366.                    write_1302(0x8e,0x00);      

  367.                    write_1302(0x88,temp);      

  368.                    write_1302(0x8e,0x80);      

  369.                      w_cmd(yh+7);      

  370.                      break;

  371.        case7:nian++;

  372.                if(nian==100)

  373.                      nian=0;

  374.                      write_nyr(3,nian);            

  375.            temp=(nian)/10*16+(nian)%10;  

  376.                    write_1302(0x8e,0x00);      

  377.                    write_1302(0x8c,temp);

  378.                    write_1302(0x8e,0x80);      

  379.                      w_cmd(yh+4);      

  380.                      break;

  381.                      


  382.        }


  383.        }


  384.        }

  385.        //------------------减键key3,各句功能参照'加键'注释---------------

  386.        if(key3==0)

  387.        {

  388.        delay(10);                        //调延时,消抖动

  389.        if(key3==0)

  390.        {

  391. //   buzzer=0;                       //蜂鸣器短响一次

  392. //   delay(20);

  393. //   buzzer=1;

  394.        while(!key3);

  395.        switch(key1n)

  396.        {

  397.               case 1:miao--;

  398.                  if(miao==-1)

  399.                          miao=59;

  400.                          write_sfm(0x08,miao);

  401.                 temp=(miao)/10*16+(miao)%10;

  402.                        write_1302(0x8e,0x00);     

  403.                        write_1302(0x80,temp);   

  404.                        write_1302(0x8e,0x80);   

  405.                          w_cmd(er+0x09);   

  406.                          //write_1602com(0x0b);

  407.                          break;

  408.               case 2:fen--;

  409.                      if(fen==-1)

  410.                             fen=59;

  411.                          write_sfm(5,fen);

  412.                          temp=(fen)/10*16+(fen)%10;

  413.                        write_1302(0x8e,0x00);

  414.                        write_1302(0x82,temp);

  415.                         write_1302(0x8e,0x80);

  416.                          w_cmd(er+6);

  417.                          break;

  418.               case 3:shi--;

  419.                       if(shi==-1)

  420.                             shi=23;

  421.                      write_sfm(2,shi);

  422.                      temp=(shi)/10*16+(shi)%10;

  423.                    write_1302(0x8e,0x00);

  424.                    write_1302(0x84,temp);

  425.                    write_1302(0x8e,0x80);

  426.                      w_cmd(er+3);

  427.                      break;

  428.               case 4:week--;

  429.                             if(week==0)

  430.                                    week=7;

  431.            w_cmd(yh+0x0C);

  432.                  write_week(week);

  433.                      temp=(week)/10*16+(week)%10;

  434.                    write_1302(0x8e,0x00);

  435.                    write_1302(0x8a,temp);

  436.                    write_1302(0x8e,0x80);

  437.                      w_cmd(yh+0x0e);

  438.                      break;

  439.               case 5:ri--;

  440.                             if(ri==0)

  441.                                    ri=31;

  442.                      write_nyr(9,ri);

  443.                      temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码

  444.                    write_1302(0x8e,0x00);//允许写,禁止写保护

  445.                    write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码

  446.                    write_1302(0x8e,0x80);//打开写保护

  447.                      w_cmd(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

  448.                      break;

  449.               case 6:yue--;

  450.                             if(yue==0)

  451.                                    yue=12;

  452.                      write_nyr(6,yue);

  453.                      temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码

  454.                    write_1302(0x8e,0x00);//允许写,禁止写保护

  455.                    write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码

  456.                    write_1302(0x8e,0x80);//打开写保护

  457.                      w_cmd(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

  458.                      break;     

  459.               case 7:nian--;

  460.                if(nian==-1)

  461.                      nian=99;

  462.                      write_nyr(3,nian);

  463.         temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码

  464.                    write_1302(0x8e,0x00);//允许写,禁止写保护

  465.                    write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码

  466.                    write_1302(0x8e,0x80);//打开写保护

  467.                      w_cmd(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

  468.                      break;

  469.                      

  470.                            

  471.        }


  472.        }


  473.        }


  474.        }


  475. }

  476. /***************"TO中断"初始********************/

  477. void intrupt()                  //"TO中断"初始

  478. {

  479. TMOD=0x01;                             //选择16位定时器0x01

  480. EA=1;                                        //开总中断

  481. ET0=1;                                      //开“T0”中断允许位

  482. TH0=(65536-50000)/256;

  483. TL0=(65536-50000)%256;           //定时器装初值

  484. TR0=1;

  485. }

  486. /*void init()                             //定时器、计数器设置函数

  487. {

  488.        TMOD=0x11;                      //指定定时/计数器的工作方式为3

  489.        TH0=0;                           //定时器T0的高四位=0

  490.        TL0=0;                           //定时器T0的低四位=0

  491.        EA=1;                            //系统允许有开放的中断

  492.        ET0=1;                           //允许T0中断

  493.        TR0=1;                           //开启中断,启动定时器


  494. }*/

  495. /***************主函数********************/

  496. void main()

  497. {

  498.        lcd_init();                          //调用液晶屏初始化子函数

  499.        ds1302_init();                      //调用DS1302时钟的初始化子函数

  500.        intrupt();

  501. //   system_Ini();

  502. //     led=0;                            //打开LCD的背光电源

  503. //   buzzer=0;                        //蜂鸣器长响一次

  504. //    delay(80);

  505. //   buzzer=1;

  506.        while(1)                          //无限循环下面的语句:

  507.        {

  508.                      

  509.    keyscan();                        //调用键盘扫描子函数

  510.       

  511.     }

  512. }


  513. void timer0() interrupt 1                 //取得并显示日历和时间

  514. {

  515.       

  516.   Init18b20();

  517.   system_Ini();

  518.   GetTemp();           //温度传感器DS18b2初始化子函数,在头文件中

  519.   flag1=Temperature;

  520. //  flag=ReadTemperature();      //将18b2头文件运行返回的函数结果送到变量flag中,用于显示

  521.   //读取秒时分周日月年七个数据(DS1302的读寄存器与写寄存器不一样):

  522.    miao = BCD_Decimal(read_1302(0x81));

  523.        fen= BCD_Decimal(read_1302(0x83));

  524.        shi  = BCD_Decimal(read_1302(0x85));

  525.        ri  = BCD_Decimal(read_1302(0x87));

  526.        yue= BCD_Decimal(read_1302(0x89));

  527.        nian=BCD_Decimal(read_1302(0x8d));

  528.        week=BCD_Decimal(read_1302(0x8b));


  529.        //显示温度、秒、时、分数据:

  530.    

  531.   write_temp(12,flag1);//显示温度,从第二行第12个字符后开始显示

  532.   write_sfm(8,miao);//秒,从第二行第8个字后开始显示(调用时分秒显示子函数)

  533.        write_sfm(5,fen);//分,从第二行第5个字符后开始显示

  534.        write_sfm(2,shi);//小时,从第二行第2个字符后开始显示

  535.       

  536.        //显示日、月、年数据:

  537.        write_nyr(9,ri);//日期,从第二行第9个字符后开始显示

  538.   write_nyr(6,yue);//月份,从第二行第6个字符后开始显示

  539.        write_nyr(3,nian);//年,从第二行第3个字符后开始显示

  540.        write_week(week);


  541. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的积分奖励!

查看全部评分

回复

使用道具 举报

ID:1 发表于 2015-1-17 13:20 来自手机 | 显示全部楼层
谢谢分享,这是一个用1602号液晶屏显示的,1302时钟程序吧
回复

使用道具 举报

ID:71870 发表于 2015-1-17 18:43 | 显示全部楼层
admin 发表于 2015-1-17 13:20
谢谢分享,这是一个用1602号液晶屏显示的,1302时钟程序吧

似的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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