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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4349|回復: 3
打印 上一主題 下一主題
收起左側

單片機+LCD1602實物顯示不正常,但是Proteus仿真成功

[復制鏈接]
跳轉到指定樓層
樓主
LCD1602程序仿真正常,實物上顯示不正常,程序在附件里面


單片機源程序如下:
  1. #include <reg51.h>                            //調用含有51專用寄存器的頭文件
  2. #include<intrins.h>
  3. #define uchar unsigned char            //用uchar代替unsigned char
  4. #define uint unsigned int                //用uint代替unsigned int

  5. #define yh 0x80       //LCD第一行的初始位置,因為LCD1602字符地址首位D7恒定為1(100000000=80)
  6. #define er 0x80+0x40 //LCD第二行初始位置(因為第二行第一個字符位置地址是0x40)

  7. char a,sec,min,hour,day,mouth,temp,n;                 //定義變量


  8. sbit rs=P3^0;                 //液晶指令/數據輸入控制
  9. sbit en=P3^2;                 //液晶使能端

  10. sbit Data=P3^6;   //定義數據線
  11. uchar rec_dat[14];   //用于顯示的接收數據數組

  12. sbit IO=P3^5;             //數據線
  13. sbit SCLK=P3^4;             //時鐘線
  14. sbit RST=P3^3;             //使能

  15. sbit mode=P1^0;      //設置鍵
  16. sbit s1  =P1^1;      //加鍵
  17. sbit s2  =P1^2;      //減鍵
  18. sbit yes =P1^3;             //調整確認鍵

  19. sbit ACC0=ACC^0;         //累加器A低位
  20. sbit ACC7=ACC^7;         //累加器A高位

  21. uchar code tab1[]={"Tem:   Hum:  %"};       //時間顯示的固定字符
  22. uchar code tab2[]={"  -     :  :  "};       //時間顯示的固定字符

  23. /***********************延時子程序********************/
  24. void delay(uint xms)
  25. {
  26.         uint x,y;
  27.         for(x=xms;x>0;x--)
  28.          for(y=110;y>0;y--);
  29. }

  30. /****************液晶寫入指令函數*******************/
  31. void write_1602com(uchar com)
  32. {
  33.         rs=0;                //數據/指令選擇置為指令
  34.         P2=com;              //送入數據
  35.         delay(1);            //看時序圖,可以得出,寫程序需要時間
  36.         en=1;                //拉高使能端,為制造有效的下降沿做準備
  37.         delay(1);
  38.         en=0;                //en由高變低,產生下降沿,液晶執行命令
  39. }

  40. /********************液晶寫入數據函數***************/
  41. void write_1602dat(uchar dat)
  42. {
  43.         rs=1;               //數據/指令選擇置為數據
  44.         P2=dat;             //送入數據
  45.         delay(1);
  46.         en=1;               //en置高電平,為制造下降沿做準備
  47.         delay(1);
  48.         en=0;               //en由高變低,產生下降沿,液晶執行命令
  49. }

  50. /**************液晶初始化函數**********************/
  51. void lcd_init()
  52. {
  53.         write_1602com(0x38);         //設置液晶工作模式,
  54.         write_1602com(0x0c);         //開顯示不顯示光標
  55.         write_1602com(0x06);         //整屏不移動,光標自動右移
  56.         write_1602com(0x01);         //清顯示

  57.         write_1602com(yh+1);         //日歷顯示固定符號從第一行第1個位置之后開始顯示
  58.         for(a=0;a<14;a++)
  59.         {
  60.         write_1602dat(tab1[a]);      //向液晶屏寫日歷顯示的固定符號部分
  61.         }
  62.         write_1602com(er+1);         //時間顯示固定符號寫入位置,從第2個位置后開始顯示
  63.         for(a=0;a<14;a++)
  64.         {
  65.         write_1602dat(tab2[a]);      //寫顯示時間固定符號,兩個冒號
  66.         }

  67. }

  68. /***************寫數據********************/
  69. void write_byte(uchar dat)
  70. {
  71.         ACC=dat;
  72.         RST=1;
  73.         for(a=8;a>0;a--)
  74.         {
  75.          IO=ACC0;
  76.          SCLK=0;
  77.          SCLK=1;
  78.          ACC=ACC>>1;
  79.         }
  80. }

  81. /******************讀數據********************/
  82. uchar read_byte()
  83. {
  84.         RST=1;
  85.         for(a=8;a>0;a--)
  86.         {
  87.          ACC7=IO;
  88.          SCLK=1;
  89.          SCLK=0;
  90.          ACC=ACC>>1;
  91.         }
  92.         return (ACC);
  93. }

  94. /*********向1302芯片寫函數,指定寫入地址,數據*********/
  95. void write_1302(uchar add,uchar dat)
  96. {
  97.         RST=0;
  98.         SCLK=0;
  99.         RST=1;
  100.         write_byte(add);
  101.         write_byte(dat);
  102.         SCLK=1;
  103.         RST=0;
  104. }

  105. /*********從1302讀數據函數,指定讀取數據來源地址*******/
  106. uchar read_1302(uchar add)
  107. {
  108.         uchar temp;
  109.         RST=0;
  110.         SCLK=0;
  111.         RST=1;
  112.         write_byte(add);
  113.         temp=read_byte();
  114.         SCLK=1;
  115.         RST=0;
  116.         return(temp);
  117. }

  118. /****************BCD碼轉十進制函數,輸入BCD,返回十進制*******/
  119. uchar BCD(uchar m)
  120. {
  121. uchar x;
  122. x=m>>4;
  123. return(x=x*10+(m&=0x0f));
  124. }

  125. /********1302芯片初始化子函數(2019-05-19,16:36:00,week7)********/
  126. void ds1302_init()
  127. {
  128. RST=0;
  129. SCLK=0;
  130. write_1302(0x8e,0x00); //允許寫,禁止寫保護


  131. write_1302(0x8e,0x80); //打開寫保護
  132. }

  133. /*****************************月日時分秒顯示子函數*******************************/
  134. void write_time(uchar add,uchar dat)//向LCD寫時分秒,有顯示位置加、現示數據,兩個參數
  135. {
  136.         uchar gw,sw;
  137.         gw=dat%10;                   //取得個位數字
  138.         sw=dat/10;                   //取得十位數字
  139.         write_1602com(er+add);       //er是頭文件寫的值0x80+0x40
  140.         write_1602dat(0x30+sw);      //數字+30得到該數字的LCD1602顯示碼
  141.         write_1602dat(0x30+gw);      //數字+30得到該數字的LCD1602顯示碼                               
  142. }






  143. /***********************按鍵處理函數**********************/
  144. void key()                             
  145. {
  146. if(mode==0)                           //第一次判斷"模式"按鍵按下
  147. {
  148.   delay(5);                            //延時消抖
  149.   if(mode==0){TR0=0;n++;}while(!mode);}                                                          
  150.   if(n>5) {TR0=1;n=0;}                           //如果第四次按下mode鍵則繼續計時,并且重新記錄按下的按鍵次數

  151. /**********************調整+********************************/                
  152.   if(n!=0)                             //當mode按下以后。再按以下鍵才有效(按鍵次數不等于零)
  153. {
  154.   if(s1==0)                            //調整+鍵
  155. {
  156.         delay(30);
  157. if(s1==0)
  158. {
  159.   TR0=0;
  160.    switch(n)
  161. {
  162.         case 1:sec++;                          //設置鍵按動1次,調秒
  163.                    if(sec==60)        sec=0;                   //秒超過59,再加1,就歸零               
  164.                     write_time(13,sec);           //令LCD在正確位置顯示"加"設定好的秒數
  165.                    temp=(sec)/10*16+(sec)%10;      //十進制轉換成DS1302要求的DCB碼
  166.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  167.                    write_1302(0x80,temp);          //向DS1302內寫秒寄存器80H寫入調整后的秒數據BCD碼
  168.                    write_1302(0x8e,0x80);          //打開寫保護
  169.                    write_1602com(er+14);         //因為設置液晶的模式是寫入數據后,指針自動+1,需要光標回位
  170.                    break;
  171.         case 2:min++;                                                   //設置鍵按動2次,調分
  172.                    if(min==60)        min=0;                           //分數據加到60時自動變成0
  173.                    write_time(10,min);           //令LCD在正確位置顯示"加"設定好的分數據
  174.                    temp=(min)/10*16+(min)%10;      //十進制轉換成DS1302要求的DCB碼
  175.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  176.                    write_1302(0x82,temp);          //向DS1302內寫分寄存器82H寫入調整后的分數據BCD碼
  177.                    write_1302(0x8e,0x80);          //打開寫保護
  178.                    write_1602com(er+11);
  179.                    break;
  180.         case 3:hour++;
  181.                    if(hour==24) hour=0;                           //時數據加到24時自動變成0
  182.                    write_time(7,hour);             //令LCD在正確的位置顯示"加"設定好的小時數據
  183.                    temp=(hour)/10*16+(hour)%10;    //十進制轉換成DS1302要求的DCB碼
  184.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  185.                    write_1302(0x84,temp);          //向DS1302內寫小時寄存器84H寫入調整后的小時數據BCD碼
  186.                    write_1302(0x8e,0x80);          //打開寫保護
  187.                write_1602com(er+8);
  188.                       break;

  189.         case 4:day++;                                                   //設置鍵按動5次,調天
  190.                    if(day==32)        day=1;                           //天數據加到32時自動變成1
  191.                      write_time(4,day);             //令LCD在正確的位置顯示"加"設定好的日期數據
  192.                    temp=(day)/10*16+(day)%10;      //十進制轉換成DS1302要求的DCB碼
  193.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  194.                    write_1302(0x86,temp);          //向DS1302內寫日期寄存器86H寫入調整后的日期數據BCD碼
  195.                    write_1302(0x8e,0x80);          //打開寫保護
  196.                    write_1602com(er+5);
  197.                         break;
  198.         case 5:mouth++;                                                   //設置鍵按動6次,調月
  199.                    if(mouth>=13)        mouth=1;           //月數據加到12時自動變成1
  200.                    write_time(1,mouth);           //令LCD在正確的位置顯示"加"設定好的月份數據
  201.                    temp=(mouth)/10*16+(mouth)%10;  //十進制轉換成DS1302要求的DCB碼
  202.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  203.                    write_1302(0x88,temp);          //向DS1302內寫月份寄存器88H寫入調整后的月份數據BCD碼
  204.                    write_1302(0x8e,0x80);          //打開寫保護
  205.                    write_1602com(er+2);
  206.                    break;

  207. }
  208.   }
  209.   while(!s1);
  210.    }
  211. }

  212. /**********************調整-********************************/                
  213.   if(n!=0)           //當mode按下以后,再按以下鍵才有效
  214. {
  215.   if(s2==0)          //調整-鍵
  216. {
  217.         delay(30);
  218. if(s2==0)
  219. {
  220.    TR0=0;                         //關閉中斷
  221.    switch(n)
  222. {
  223.         case 1:sec--;                         //設置鍵按動1次,調秒
  224.                    if(sec==-1)        sec=59;                  //秒數據減到-1時自動變成59       
  225.                     write_time(13,sec);          //令LCD在正確位置顯示"加"設定好的秒數
  226.                    temp=(sec)/10*16+(sec)%10;     //十進制轉換成DS1302要求的DCB碼
  227.                    write_1302(0x8e,0x00);         //允許寫,禁止寫保護
  228.                    write_1302(0x80,temp);         //向DS1302內寫秒寄存器80H寫入調整后的秒數據BCD碼
  229.                    write_1302(0x8e,0x80);         //打開寫保護
  230.                    write_1602com(er+14);                  //因為設置液晶的模式是寫入數據后,指針自動+1,需要光標回位
  231.                         break;
  232.         case 2:min--;
  233.                    if(min==-1)        min=59;                          //分數據減到-1時自動變成59
  234.                    write_time(10,min);          //令LCD在正確位置顯示"加"設定好的分數據
  235.                    temp=(min)/10*16+(min)%10;     //十進制轉換成DS1302要求的DCB碼
  236.                    write_1302(0x8e,0x00);         //允許寫,禁止寫保護
  237.                    write_1302(0x82,temp);         //向DS1302內寫分寄存器82H寫入調整后的分數據BCD碼
  238.                    write_1302(0x8e,0x80);         //打開寫保護
  239.                    write_1602com(er+11);
  240.                    break;
  241.         case 3:hour--;
  242.                    if(hour==-1) hour=23;                   //時數據減到-1時自動變成23
  243.                    write_time(7,hour);             //令LCD在正確的位置顯示"加"設定好的小時數據
  244.                    temp=(hour)/10*16+(hour)%10;    //十進制轉換成DS1302要求的DCB碼
  245.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  246.                    write_1302(0x84,temp);          //向DS1302內寫小時寄存器84H寫入調整后的小時數據BCD碼
  247.                    write_1302(0x8e,0x80);          //打開寫保護
  248.                write_1602com(er+8);           
  249.                       break;

  250.         case 4:day--;
  251.                    if(day==-1)        day=31;                           //天數據減到-1時自動變成31
  252.                      write_time(4,day);             //令LCD在正確的位置顯示"加"設定好的日期數據
  253.                    temp=(day)/10*16+(day)%10;      //十進制轉換成DS1302要求的DCB碼
  254.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  255.                    write_1302(0x86,temp);          //向DS1302內寫日期寄存器86H寫入調整后的日期數據BCD碼
  256.                    write_1302(0x8e,0x80);          //打開寫保護
  257.                    write_1602com(er+5);
  258.                    break;
  259.         case 5:mouth--;
  260.                    if(mouth==-1)        mouth=12;           //月數據減到-1時自動變成12
  261.                    write_time(1,mouth);           
  262.                    temp=(mouth)/10*16+(mouth)%10;  //十進制轉換成DS1302要求的DCB碼
  263.                    write_1302(0x8e,0x00);          //允許寫,禁止寫保護
  264.                    write_1302(0x88,temp);          //向DS1302內寫月份寄存器88H寫入調整后的月份數據BCD碼
  265.                    write_1302(0x8e,0x80);          //打開寫保護
  266.                    write_1602com(er+2);         
  267.                    break;

  268. }
  269.   }
  270.   while(!s2);                                                           //按鍵松開檢測
  271.    }
  272. }

  273. if(n!=0)
  274. {
  275.   if(yes==0)                        //調整值確認鍵按下,保存設置的參數,直接退出調整狀態,進入走時。
  276. {
  277.         delay(30);
  278.   if(yes==0)
  279.   {
  280.         n=0,
  281.         write_1602com(0x0c);        //設置光標不閃爍
  282.         TR0=1;                      //打開定時器
  283.         temp=(sec)/10*16+(sec)%10;
  284.         write_1302(0x8e,0x00);
  285.         write_1302(0x80,0x00|temp); //秒數據寫入DS1302
  286.         write_1302(0x8e,0x80);                
  287.   }
  288.   while(!yes);                                   //松開按鍵檢測
  289. }
  290. }

  291. }

  292. //*********************DHT11************************
  293. void DHT11_delay_us(uchar n)
  294. {
  295.     while(--n);
  296. }

  297. void DHT11_delay_ms(uint z)
  298. {
  299.    uint i,j;
  300.    for(i=z;i>0;i--)
  301.       for(j=110;j>0;j--);
  302. }

  303. void DHT11_start()
  304. {
  305.    Data=1;
  306.    DHT11_delay_us(2);
  307.    Data=0;
  308.    DHT11_delay_ms(30);   //延時18ms以上
  309.    Data=1;
  310.    DHT11_delay_us(30);
  311. }

  312. uchar DHT11_rec_byte()      //接收一個字節
  313. {
  314.    uchar i,dat=0;
  315.   for(i=0;i<8;i++)    //從高到低依次接收8位數據
  316.    {         
  317.       while(!Data);   ////等待50us低電平過去
  318.       DHT11_delay_us(8);     //延時60us,如果還為高則數據為1,否則為0
  319.       dat<<=1;           //移位使正確接收8位數據,數據為0時直接移位
  320.       if(Data==1)    //數據為1時,使dat加1來接收數據1
  321.          dat+=1;
  322.       while(Data);  //等待數據線拉低   
  323.     }  
  324.     return dat;
  325. }

  326. void DHT11_receive()      //接收40位的數據
  327. {
  328.     uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
  329.     DHT11_start();
  330.     if(Data==0)
  331.     {
  332.         while(Data==0);   //等待拉高     
  333.         DHT11_delay_us(40);  //拉高后延時80us
  334.         R_H=DHT11_rec_byte();    //接收濕度高八位  
  335.         R_L=DHT11_rec_byte();    //接收濕度低八位  
  336.         T_H=DHT11_rec_byte();    //接收溫度高八位  
  337.         T_L=DHT11_rec_byte();    //接收溫度低八位
  338.         revise=DHT11_rec_byte(); //接收校正位

  339.         DHT11_delay_us(25);    //結束

  340.         if((R_H+R_L+T_H+T_L)==revise)      //校正
  341.         {
  342.             RH=R_H;
  343.             RL=R_L;
  344.             TH=T_H;
  345.             TL=T_L;
  346.         }
  347.         /*數據處理,方便顯示*/
  348.         rec_dat[0]='T';
  349.         rec_dat[1]='e';
  350.         rec_dat[2]='m';
  351.         rec_dat[3]=':';
  352.         rec_dat[4]='0'+(TH/10);
  353.         rec_dat[5]='0'+(TH%10);
  354.         rec_dat[6]=' ';
  355.         rec_dat[7]='H';
  356.         rec_dat[8]='u';
  357.                 rec_dat[9]='m';
  358.         rec_dat[10]=':';
  359.         rec_dat[11]='0'+(RH/10);
  360.         rec_dat[12]='0'+(RH%10);
  361.         rec_dat[13]='%';


  362.     }
  363. }
  364. /****************************主函數**********************/
  365. void main()
  366. {
  367.         uchar i;
  368.     TMOD=0x11;       //指定定時/計數器的工作方式為3
  369.         TH0=0;           //定時器T0的高四位=0
  370.         TL0=0;           //定時器T0的低四位=0
  371.         EA=1;            //開總中斷
  372.         ET0=1;           //允許T0中斷
  373.         TR0=1;           //開啟中斷,啟動定時器
  374.     lcd_init();      //調用液晶屏初始化子函數
  375.         ds1302_init();   //調用DS1302時鐘的初始化子函數
  376.                    DHT11_delay_ms(100);    //DHT11上電后要等待1S以越過不穩定狀態在此期間不能發送任何指令
  377.        DHT11_receive();
  378.        write_1602com(yh+1);   //從lcd1602第一行第一個位置開始顯示
  379.        for(i=0;i<14;i++)
  380.        write_1602dat(rec_dat[i]);   //顯示數據
  381.        
  382.   while(1)
  383. {
  384.          key();  
  385. }

  386. }

  387. void timer0() interrupt 1  //取得并顯示日歷和時間
  388. {          
  389. /***************************讀取秒時分周日月年七個數據***********************/
  390.   sec  = BCD(read_1302(0x81));
  391.   min  = BCD(read_1302(0x83));
  392.   hour = BCD(read_1302(0x85));
  393.   day  = BCD(read_1302(0x87));
  394.   mouth= BCD(read_1302(0x89));


  395. /**************************顯示溫度、秒、時、分數據***************************/
  396.   write_time(13,sec);     //秒,從第二行第8個字后開始顯示(調用時分秒顯示子函數)
  397.   write_time(10,min);     //分,從第二行第5個字符后開始顯示
  398.   write_time(7,hour);    //小時,從第二行第2個字符后開始顯示
  399.   write_time(4,day);    //日期,從第二行第9個字符后開始顯示
  400.   write_time(1,mouth);  //月份,從第二行第6個字符后開始顯示

  401. }
復制代碼

1302時鐘.zip

4.24 KB, 下載次數: 16

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:552570 發表于 2019-6-1 17:20 | 只看該作者
線連接的都對嗎?
回復

使用道具 舉報

板凳
ID:96682 發表于 2019-6-1 17:45 | 只看該作者
源程序與仿真圖有出入,這仿真圖多處電路有誤如用于實物上肯定不妥
回復

使用道具 舉報

地板
ID:511890 發表于 2019-6-2 02:37 | 只看該作者
lcd_init()中的 write_1602com(0x01);  后面加個延時。然后顯示要么放到while中,要么放到一個中斷中。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩av在线一区 | 伊人网91 | 99视频在线免费观看 | 国产精品视频一区二区三区 | 蜜桃一区二区三区在线 | 日日操夜夜操天天操 | 日韩视频中文字幕 | 色视频在线播放 | 日韩免费网站 | 欧区一欧区二欧区三免费 | 国产97久久 | 日韩一区二 | 国产欧美精品一区二区 | 国产精品99久久久久久宅男 | 一级片免费观看 | 久久99精品国产 | 成人精品免费 | 日韩欧美在线一区 | 精品亚洲一区二区三区四区五区 | 黄色大片视频 | 91精品国产99 | 久久综合香蕉 | 九九在线视频 | 欧美视频1区 | 久久一二 | 免费性视频 | 综合久久综合久久 | 国产精品一二三区 | 久久久久国产精品一区二区 | 欧美久操网 | 日韩欧美国产精品综合嫩v 一区中文字幕 | 亚洲一区二区精品视频 | 欧美中文字幕在线 | 男人的天堂中文字幕 | 成人高潮片免费视频欧美 | 国产精品不卡视频 | 91高清在线观看 | 精品久久一区 | 亚洲综合色婷婷 | 精品一区二区久久久久久久网精 | 色婷婷综合久久久久中文一区二区 |