找回密码
 立即注册

QQ登录

只需一步,快速开始

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

这个单片机LCD1602程序仿真的时候为什么显示都是问号?

[复制链接]
回帖奖励 1 黑币 回复本帖可获得 1 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主

  1. #include<reg52.h>//52单片机头文件,规定了52单片机的寄存器和IO口等
  2. #include<intrins.h>//_nop_空指令及左右循环移位子函数库
  3. #define uchar unsigned char//宏定义
  4. #define uint unsigned int//宏定义
  5.         
  6. sbit lcd_rs=P2^0;//定义选数据寄存器选指令寄存器控制端
  7. sbit lcd_rw=P2^1;//定义下面通过lcd_rw来操作P2^5口,1602读写选择端
  8. sbit lcd_en=P2^2;//定义下面通过lcd_en来操作P2^7口,1602液晶使能控制端

  9. sbit DS_rst=P3^4;//DS1302复位
  10. sbit DS_sck=P3^5;//定义时钟总线
  11. sbit DS_io=P3^6;//定义DS1302数据总线

  12. sbit s1=P1^0;//定义设置按钮
  13. sbit s2=P1^1;//定义调时按钮
  14. sbit s3=P1^2;//定义确定按钮
  15. sbit s4=P1^3;//定义闹钟调整按钮

  16. sbit ACC0=ACC^0;//累加器
  17. sbit ACC7=ACC^7;

  18. sbit BELL=P1^6; //喇叭

  19. char fen,shi,miao,ri,yue,nian,zhou,s1num,s2num,s4num,flag1,flag2,lshi,lfen;
  20. uchar code table[]={" 2022-  -    W  "};//要写入1602液晶的数据
  21. uchar code table1[]={"  :  :    T  :  "};//字库中的字可直接以外加""号的形式直接写入
  22. uchar code table2[]={" Welcome To Lcd!"};//欢迎界面
  23. uchar code table3[]={"Happy Every Day!"};           //欢迎界面
  24. /*******************************************************************************
  25. 时函数,z的取值为这个函数的延时ms数,delay(200);大约延时200ms. delay(500);大约延时500ms
  26. *******************************************************************************/
  27. void delay(uint z)
  28. {                                                      
  29.         uint x,y;
  30.         for(x=z;x>0;x--)
  31.         for(y=110;y>0;y--);
  32. }
  33. /*********************蜂鸣器函数************************************************/
  34. void didi()
  35. {         
  36.     uchar i;
  37.      for(i=0;i<60;i++)
  38.       {
  39.         BELL = 0;
  40.                 delay(1);
  41.              BELL = 1;
  42.                 delay(1);
  43.        }
  44. }

  45. /*******************向1602液晶中写一个指令**************************************/
  46. void write_com(uchar com)
  47. {        
  48.         lcd_rw=0;                        //lcd_rw为读写控制端,lcd_rw=0,这里可不写
  49.         lcd_rs=0;           //液晶rs接口为0时,写指令,rs为1时写数据
  50.         P0=com;          //将要写的指令赋给P0口,
  51.         delay(5);    //由1602读写操作时序图,先将指令赋给P0口,延时后将使能
  52.         lcd_en=1;    //  端lcd_en置高,再延时一段时间,然后将lcd_en置低,这样指令
  53.         delay(5);          // 就写入到LCD了        
  54.         lcd_en=0;
  55. }
  56. /****************************向液晶写数据***************************************/
  57. void write_data(uchar date)//与写指令类似,这里lcd_rs设为1
  58. {
  59.         
  60.         lcd_rs=1;
  61.         lcd_rw=0;
  62.         P0=date;
  63.         delay(5);
  64.         lcd_en=1;
  65.         delay(5);
  66.         lcd_en=0;
  67. }
  68. /*****************************初使化1602液晶************************************/
  69. void init_1602()
  70. {
  71.         lcd_en=0;
  72.         nian=22;
  73.         yue=6;
  74.         ri=21;
  75.         zhou=5;
  76.         shi=13;
  77.         fen=59;
  78.         miao=59;
  79.         s1num=0;
  80.         s2num=0;
  81.         s4num=0;
  82.         lshi=7;
  83.         lfen=59;
  84.         write_com(0x38);//设置LCD为16*2显示、5*7点阵、8位数据接口模式
  85.         write_com(0x0c);//开显示、不显示光标
  86.         write_com(0x06);//写一个字符后,地址指针加1
  87.         write_com(0x01);//显示清0
  88. }
  89. /*******************************************************************************/
  90. void gudingtime_1602()
  91. {
  92.     uchar num;
  93.         write_com(0x80);//将指针指向初始位置
  94.         for(num=0;num<16;num++)//循环函数,用于将" 2022-  -     "写入液晶
  95.                         write_data(table[num]);
  96.         write_com(0x80+0x40);//将指针指向1602液晶的第二行
  97.         for(num=0;num<16;num++)//功能与上同,用于将"  :  :    T  :  "写入
  98.                         write_data(table1[num]);
  99. }
  100. /**************************显示欢迎界面函数*************************************/
  101. void displaystar(void)
  102. {
  103.          uchar i;
  104.          write_com(0x80);
  105.          for(i=0;i<16;i++)
  106.          write_data(table2[i]);
  107.          write_com(0x80+0x40);
  108.          for(i=0;i<16;i++)
  109.           write_data(table3[i]);
  110. }
  111. /***************************显示时间、日期子函数*********************************/
  112. void write_sfm(uchar add,uchar time)//用于在1602上显示年、月、日、时、分、秒。Add为显示位置,time为要显示的内容
  113. {                              
  114.         uchar shiwei,gewei;                                                
  115.         shiwei=time/16;   //将从DS1302中读取的BCD码数据转化成10进制个位和10
  116.         gewei=time%16;   //进制十位
  117.         write_com(add+0x80);//定义显示在液晶的什么位置
  118.         write_data(0x30+shiwei);//由1602液晶字库可知,0~9的数据码分别对应0x30~0x39
  119.         write_data(0x30+gewei);        //初使化中设定了写一个字符后,地址指针加1,因此这里
  120. }                     // 不用重新光标写位

  121. /**************************显示周子函数*****************************************/
  122. void write_zhou(uchar time1)//用于在1602上显示周信息,与显示
  123. {                        //时间日期子函数类似
  124.         uchar gewei;
  125.         gewei=time1%16;//一周七天,因此只需个位
  126.         write_com(0x80+14);//初始位置加13个
  127.         write_data(0x30+gewei);
  128. }
  129. /***************************写数据字节子函数************************************/
  130. void Input_1byte(uchar TD)//写一字节数据
  131. {
  132.     uchar i;
  133.     ACC=TD;
  134.     for(i=8;i>0;i--)
  135.     {
  136.        DS_io=ACC0;
  137.        DS_sck=1;
  138.        DS_sck=0;
  139.        ACC=ACC>>1; //右移一位
  140.     }
  141. }


  142. /*************************读数据字节子函数**************************************/
  143. uchar Output_1byte(void)//读一字节数据
  144. {
  145.     uchar i;
  146.     for(i=8;i>0;i--)
  147.      {
  148.          ACC=ACC>>1;
  149.          ACC7=DS_io;
  150.          DS_sck=1;
  151.          DS_sck=0;
  152.      }

  153.      return(ACC);

  154. }
  155. /***************************写DS1302数据函数***********************************/
  156. void write_1302(uchar DS_ADD,uchar DS_DAT)//写操作
  157. {   
  158.                  DS_rst=0;
  159.                  DS_sck=0;
  160.                  DS_rst=1;
  161.                  Input_1byte(DS_ADD);
  162.                  Input_1byte(DS_DAT);
  163.                  DS_sck=1;
  164.                  DS_rst=0;
  165. }

  166. /***************************读DS1302数据函数***********************************/
  167. uchar read_1302(uchar DS_ADD)//读操作
  168. {   
  169.           uchar DS_INF;
  170.                 DS_rst=0;
  171.           DS_sck=0;  
  172.           DS_rst=1;
  173.           Input_1byte(DS_ADD);
  174.           DS_INF=Output_1byte();
  175.           DS_sck=1;
  176.           DS_rst=0;
  177.           return(DS_INF);
  178. }

  179. /*************************初始化DS1302子函数***********************************/
  180. void inital_1302()
  181. {
  182.     write_1302(0x8e,0x00);//禁止写保护
  183.     write_1302(0x90,0xaa);//定义充电
  184.                 write_1302(0x80,0x53);//秒   
  185.     write_1302(0x84,0x13);//时     
  186.                 write_1302(0x82,0x43);//分
  187.                 write_1302(0x8c,0x12);//年
  188.                 write_1302(0x88,0x06);//月
  189.                 write_1302(0x86,0x03);//日
  190.                 write_1302(0x8a,0x06);//星期
  191.     write_1302(0xc0,0x08);//闹钟小时初始化
  192.                 write_1302(0xfc,0x00);//闹钟分钟初始化
  193.                 write_1302(0x8e,0x80);//开保护

  194. }
  195. /********************************************************************************
  196.                               扫描函数
  197. ********************************************************************************/

  198. void keyscan()
  199. {  
  200.         if(s1==0&&s4num==0)        //按键1按下且s4再次之前未曾按过
  201.         {
  202.                 delay(5);
  203.                 if(s1==0&&s4num==0)
  204.                 {   
  205. flag1=1;
  206.                     s1num++;
  207.                         while(!s1);didi();
  208.                         if(s1num==1)
  209.                         {                                
  210.                                         write_com(0x80+0x40+8);//光标移动到**位置
  211.                                         write_com(0x0f);//显示光标
  212.                         }

  213.                         if(s1num==2)
  214.                         {
  215.                                    write_1302(0x8e,0x00);//禁止写保护
  216.                                         write_1302(0x80,miao);//写入秒信息
  217.                                         write_1302(0x8e,0x80);//开写保护
  218.                                         write_com(0x80+0x40+5);
  219.                         }
  220.                         if(s1num==3)
  221.                         {
  222.                                    write_1302(0x8e,0x00);
  223.                                         write_1302(0x82,fen);
  224.                                         write_1302(0x8e,0x80);
  225.                                         write_com(0x80+0x40+2);                                                               
  226.                         }
  227.                         if(s1num==4)
  228.                         {
  229.                                         write_1302(0x8e,0x00);
  230.                                         write_1302(0x88,yue);
  231.                                         write_1302(0x8e,0x80);
  232.                             write_com(0x80+13);
  233.                         }
  234.                         if(s1num==5)
  235.                         {
  236.                                         write_1302(0x8e,0x00);
  237.                                         write_1302(0x84,shi);
  238.                                         write_1302(0x8e,0x80);
  239.                                         write_com(0x80+10);
  240.                         }
  241.                         if(s1num==6)
  242.                         {
  243.                                         write_1302(0x8e,0x00);
  244.                                         write_1302(0x86,ri);
  245.                                         write_1302(0x8e,0x80);
  246.                                         write_com(0x80+7);
  247.                         }
  248.                         if(s1num==7)
  249.                         {
  250.                                         write_1302(0x8e,0x00);
  251.                                         write_1302(0x8c,nian);
  252.                                         write_1302(0x8e,0x80);
  253.                                         write_com(0x80+4);
  254.                         }
  255.             if(s1num==8)
  256.                         {  
  257.                         flag1=0;
  258.                                         s1num=0;
  259.                                         write_1302(0x8e,0x00);
  260.                                         write_1302(0x8a,zhou);
  261.                                         write_1302(0x8e,0x80);
  262.                                         write_com(0x0c);//不显示光标
  263.                         }
  264.                 }
  265.         }        
  266. /*******************************************************************************/        
  267.         if(s1num!=0&&s4num==0)//按键1按下*次且s4再次之前未曾按过
  268.                 {
  269.                         if(s2==0)
  270.                         {
  271.                                 delay(5);
  272.                                 if(s2==0)
  273.                                 {   
  274.                                         while(!s2);didi();
  275.                                         if(s1num==1)
  276.                                         {
  277.                                                 int x1,x2;
  278.                                                 x1=miao%16;
  279.                                                 x2=miao/16;
  280.                                                 x1++;
  281.                                                 if(x1==10)
  282.                                                 {
  283.                                                         x1=0;
  284.                                                         x2++;
  285.                                                         if(x2>=6)
  286.                                                                 x2=0;
  287.                                                 }
  288.                                                 miao=x1+x2*16;
  289.                                                 write_sfm(7+0x40,miao);//将修改的数送到1602显示
  290.                                                 write_com(0x80+0x40+8);//挪回光标
  291.                                         }
  292.                                         if(s1num==2)
  293.                                         {
  294.                                                 int x3,x4;
  295.                                                 x3=fen%16;
  296.                                                 x4=fen/16;
  297.                                                 x3++;
  298.                                                 if(x3==10)
  299.                                                 {
  300.                                                         x3=0;
  301.                                                         x4++;
  302.                                                         if(x4>=6)
  303.                                                                 x4=0;
  304.                                                 }
  305.                                                 fen=x3+x4*16;
  306.                                                 write_sfm(4+0x40,fen);
  307.                                                 write_com(0x80+0x40+5);
  308.                                         }        
  309.                                         if(s1num==3)
  310.                                         {
  311.                                                 int x5,x6;
  312.                                                 x5=shi%16;
  313.                                                 x6=shi/16;
  314.                                                 x5++;
  315.                                                  if(x6>=2&&x5>=4)        
  316.                                                 {
  317.                                                         x5=0;
  318.                                                         x6=0;
  319.                                                 }
  320.                                                 if(x5==10)
  321.                                                 {
  322.                                                         x5=0;
  323.                                                         x6++;
  324.                                                 }
  325.                                                 shi=x5+x6*16;
  326.                                                 write_sfm(1+0x40,shi);
  327.                                                 write_com(0x80+0x40+2);
  328.                                         }
  329.                                         if(s1num==4)
  330.                                         {
  331.                                                  zhou++;
  332.                                                  if(zhou==8)
  333.                                                  zhou=1;
  334.                                                  write_zhou(zhou);
  335.                                                  write_com(0x80+13);
  336.                                                 
  337.                                 }
  338.                                         if(s1num==5)
  339.                                         {
  340.                                                 int x5,x6;
  341.                                                 x5=ri%16;
  342.                                                 x6=ri/16;
  343.                                                 x5++;
  344.                                                 if(x6>=3&&x5>=1)        
  345.                                                 {
  346.                                                         x5=1;
  347.                                                         x6=0;
  348.                                                 }
  349.                                                 if(x5==10)
  350.                                                 {
  351.                                                         x5=0;
  352.                                                         x6++;
  353.                                                 }
  354.                                                 ri=x5+x6*16;
  355.                                                 write_sfm(9,ri);
  356.                                                 write_com(0x80+10);
  357.                                         }
  358.                                         if(s1num==6)
  359.                                         {
  360.                                                 int x5,x6;
  361.                                                 x5=yue%16;
  362.                                                 x6=yue/16;
  363.                                                 x5++;
  364.                                                 if(x6>=1&&x5>=3)        
  365.                                                 {
  366.                                                         x5=1;
  367.                                                         x6=0;
  368.                                                 }
  369.                                                 if(x5==10)
  370.                                                 {
  371.                                                         x5=0;
  372.                                                         x6++;
  373.                                                 }
  374.                                                 yue=x5+x6*16;
  375.                                                 write_sfm(6,yue);
  376.                                                 write_com(0x80+7);
  377.                                 }
  378.                                         if(s1num==7)
  379.                                         {
  380.                                                 int x5,x6;
  381.                                                 x5=nian%16;
  382.                                                 x6=nian/16;
  383.                                                 x5++;
  384.                                                 if(x6>=2&&x5>=1)        
  385.                                                 {
  386.                                                         x5=1;
  387.                                                         x6=0;
  388.                                                 }
  389.                                                 if(x5==10)
  390.                                                 {
  391.                                                         x5=0;
  392.                                                         x6++;
  393.                                                 }
  394.                                                 nian=x5+x6*16;
  395.                                                 write_sfm(3,nian);
  396.                                                 write_com(0x80+4);
  397.                                 }
  398.                                 }
  399.                         }
  400.             }
  401. /*******************************************************************************/

  402.         if(s1num!=0||s4num!=0)// 在调整模式下
  403.                 {
  404.                         if(s3==0)//如果确定键按下
  405.                         {
  406.                                 delay(5);
  407.                                 if(s3==0) //延时并重新检测S3是否按下,用于差小误差
  408.                                 {
  409.                                    if(s1num!=0)
  410.                                    {
  411.                                     while(!s3);didi();//在松手时将调整后的时间、日期及周信息写入DS1302,退出调整模式并隐藏光标,按键次数清0
  412.                                                 write_1302(0x8e,0x00);
  413.                                            write_1302(0x80,miao);
  414.                                     write_1302(0x84,shi);
  415.                                                 write_1302(0x82,fen);
  416.                                                 write_1302(0x8a,zhou);
  417.                                                 write_1302(0x8c,nian);//年
  418.                                                 write_1302(0x88,yue);//月
  419.                                                 write_1302(0x86,ri);
  420.                                                 write_1302(0x8e,0x80);
  421.                                                 flag1=0;
  422.                                                 write_com(0x0c);
  423.                                                 s1num=0;
  424.                    }
  425.                                    if(s4num!=0)
  426.                                    {
  427.                                            while(!s3);didi();//在松手时将调整后的时间、日期及周信息写入DS1302,退出调整模式并隐藏光标,按键次数清0
  428.              write_1302(0x8e,0x00);
  429.                                       write_1302(0xc0,lshi);
  430.              write_1302(0xfc,lfen);
  431.                                                  write_1302(0x8e,0x80);
  432.                                                   flag2=0;
  433.                                                  s4num=0;
  434.                                                  write_com(0x0c);
  435.                    }

  436.                                 }
  437.                         }        
  438.         }

  439.    if(s4==0&&s1num==0)//按键4按下*次且s1再次之前未曾按过
  440.         {  
  441.                      
  442.               delay(5);
  443.                             if(s4==0&&s1num==0)
  444.                           {   
  445.                             s4num++;
  446.                                         flag2=1;
  447.             while(!s4);didi();
  448.                                       if(s4num==1)
  449.                                         {                                
  450.                                                                                 
  451.                                                         write_com(0x80+0x40+14);
  452.                                                         write_com(0x0f);
  453.                                         }
  454.                                              
  455.                                           if(s4num==2)
  456.                                         {
  457.                                                    write_1302(0x8e,0x00);//禁止写保护
  458.                                             write_1302(0xfc,lfen);//闹钟初始化
  459.                                                         write_1302(0x8e,0x80);//开写保护
  460.                                                         write_com(0x80+0x40+11);
  461.                                         }
  462.                                         if(s4num==3)
  463.                                         {   
  464.                                             s4num=0;
  465.                                                         flag2=0;
  466.                                                    write_1302(0x8e,0x00);//禁止写保护
  467.                                                         write_1302(0xc0,lshi);//闹钟初始化
  468.                                                         write_1302(0x8e,0x80);//开写保护
  469.                                                         write_com(0x0c);//不显示光标
  470.                                         }
  471.                           }
  472.                 }
  473.         
  474.                         if(s4num!=0&&s1num==0)
  475.                         {
  476.                                 if(s2==0)
  477.                                 {
  478.                                         delay(5);
  479.                                         if(s2==0)
  480.                                         {   
  481.                                                 while(!s2);didi();
  482.                                                 if(s4num==1)
  483.                                                 {
  484.                                                         int x1,x2;
  485.                                                         x1=lfen%16;
  486.                                                         x2=lfen/16;
  487.                                                         x1++;
  488.                                                         if(x1==10)
  489.                                                         {
  490.                                                                 x1=0;
  491.                                                                 x2++;
  492.                                                                 if(x2>=6)
  493.                                                                         x2=0;
  494.                                                         }
  495.                                                         lfen=x1+x2*16;
  496.                                                         write_sfm(13+0x40,lfen);
  497.                                                         write_com(0x80+0x40+14);
  498.                             }
  499.                                                 if(s4num==2)
  500.                                                 {
  501.                                                         int x5,x6;
  502.                                                         x5=lshi%16;
  503.                                                         x6=lshi/16;
  504.                                                         x5++;
  505.                                                          if(x6>=2&&x5>=4)        
  506.                                                         {
  507.                                                                 x5=0;
  508.                                                                 x6=0;
  509.                                                         }
  510.                                                         if(x5==10)
  511.                                                         {
  512.                                                                 x5=0;
  513.                                                                 x6++;
  514.                                                         }
  515.                                                         lshi=x5+x6*16;
  516.                                                         write_sfm(10+0x40,lshi);
  517.                                                         write_com(0x80+0x40+11);
  518.                                                 }
  519.                         }
  520.                     }
  521.                 }
  522. }
  523. void laba()
  524. {  
  525.    if((shi==lshi)&&(fen==lfen)&&(miao<=10&&miao>=0))//当闹钟的时和分分别与时钟的时和分相等时,闹钟时间到,蜂鸣器鸣响,鸣响10s
  526.    {
  527.        didi();
  528.    }
  529. }
  530. void main()
  531. {   
  532.     init_1602();
  533.                 delay(5);
  534.                 displaystar();//初始化1602后马上显示欢迎语句
  535.                 delay(5000);//让欢迎界面停留一段时间
  536.                 gudingtime_1602();//显示液晶固定不变部分
  537.     inital_1302();
  538.                 lshi=read_1302(0xc1);//从ds1302里面的RAM读取闹钟时,此处不放在while(1)大循环里面是因为ds1302里面的RAM里的数据是不变的只需读取一次
  539.     lfen=read_1302(0xfd);//从ds1302里面的RAM读取闹钟分
  540.     write_sfm(0x40+11,lshi);//将闹钟时送到1602显示
  541.     write_sfm(0x40+14,lfen);//将闹钟分送到1602显示
  542.         while(1)
  543.                 {      
  544.                         keyscan();
  545.                                 laba();
  546.                         if(flag1==0&&flag2==0)//只有当不在调整的时候才从DS1302里面读取数据并且送到1602上显示
  547.                             {
  548.                                     miao=read_1302(0x81);//先读出,再送到1602显示,不断循环操作,使1602动态显示时间的走动
  549.                                                 fen=read_1302(0x83);
  550.                                                 shi=read_1302(0x85);
  551.                                                 ri=read_1302(0x87);
  552.                                                 yue=read_1302(0x89);
  553.                                                 zhou=read_1302(0x8b);
  554.                         nian=read_1302(0x8d);
  555.                                                 
  556.                                     write_sfm(6+0x40,miao);
  557.                                                 write_sfm(3+0x40,fen);
  558.                                                 write_sfm(0+0x40,shi);
  559.                                                 write_sfm(9,ri);
  560.                                                 write_sfm(6,yue);
  561.                                                 write_sfm(3,nian);
  562.                                                 write_zhou(zhou);
  563.                         }
  564. }
  565. }
复制代码

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

使用道具 举报

沙发
ID:123289 发表于 2023-4-20 15:43 | 只看该作者
读通显示屏的显示原理就清楚了,下次遇到任意显示就都能明白了。
仔细读手册吧。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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