找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1665|回复: 4
收起左侧

单片机LCD12864显示DS302数字时钟,但是显示出来都是问号?

[复制链接]
ID:997450 发表于 2022-2-19 14:57 | 显示全部楼层 |阅读模式
单片机源程序如下.单片机是89c51RC,屏幕是带字库12864,ds1302
51hei图片_20220219184810.jpg

  1. #include <reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. sbit PSB = P2 ^ 4;
  5. sbit SCLK = P2 ^ 5;
  6. sbit SID = P2 ^ 6;

  7. sbit clk=P1^0;
  8. sbit io=P1^1;
  9. sbit ce=P1^2;

  10. uchar add_write[]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};
  11. uchar add_read[]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};
  12. uchar tim0[]={20,1,4,13,9,10,26};//年、星期、月、日、时、分秒

  13. uchar tim_bcd[7];//保存读出的时间日期
  14. uchar tim[14];//保存分解开的十位、个位

  15. //将8位二进制数逐位写入
  16. void LCD_sendbyte(uchar dat);
  17. //写入命令
  18. void LCD_write_com(uchar com);
  19. //写入数据
  20. void LCD_write_dat(uchar dat);
  21. //LCD初始化
  22. void LCD_init();
  23. //LCD屏幕地址定位
  24. void LCD_Setaddress(uchar x, uchar y);
  25. //LCD显示字符数组(文字)
  26. void LCD_Putstring( uchar x, uchar y, uchar *pData );

  27. void display_1302();
  28. void write_1302_8(uchar dat);
  29. void write_1302_byte(uchar add,uchar dat);
  30. uchar read_1302_byte(uchar add);
  31. void ds1302_initial();
  32. void read_1302time();


  33. void Delayms(uint n)                 //延时时间为 1ms * x 晶振是11.0592M
  34. {
  35.         unsigned int i, j;
  36.         for (i = n; i > 0; i--)
  37.                 for (j = 110; j > 0; j--);
  38. }


  39. //将8位二进制数逐位写入
  40. void LCD_sendbyte(uchar dat) {
  41.         unsigned char i;
  42.         for (i = 0; i < 8; i++) {
  43.                 SCLK = 0;
  44.                 if (dat & 0x80)
  45.                         SID = 1;
  46.                 else
  47.                         SID = 0;
  48.                 SCLK = 1;
  49.                 dat = dat << 1;     //左移一位
  50.         }
  51. }



  52. //写入命令
  53. void write_com(uchar com) {
  54.         LCD_sendbyte(0xf8);          //送入5个连续的“1“,启动一个周期,11111,RW(0),RS(0),0
  55.         LCD_sendbyte(0xf0 & com);    //取高四位,数据分两次传送,每个字节的内容被送入两个字节,高四位放在第一个字节的高四位
  56.         LCD_sendbyte(0xf0 & (com << 4)); //低四位放在第二个字节的高四位
  57.         Delayms(1);                   //串行不支持读操作,不可检测忙操作,这里用延时替代
  58. }



  59. //写入数据
  60. void write_data(uchar dat) {
  61.         LCD_sendbyte(0xfa);
  62.         LCD_sendbyte(0xf0 & dat);
  63.         LCD_sendbyte(0xf0 & (dat << 4));
  64.         Delayms(1);
  65. }



  66. //LCD初始化
  67. void initial_12864() {
  68.         write_com(0x30);    //选择基本指令集
  69.         write_com(0x0c);    //开显示,无游标,不反白
  70.         write_com(0x01);    //清除显示屏幕,把DDRAM位址计数器调整为00H
  71.         Delayms(1);            //清屏操作时间较长1.6ms 因此加此延时
  72.         write_com(0x02);    //清DDRAM位址归位,此处貌似与清屏重复
  73.         write_com(0x06);    //设定光标右移,整体显示不移动
  74. }


  75. //LCD屏幕地址定位
  76. void LCD_Setaddress(uchar x, uchar y) { //地址从第1行第1列开始不从0开始(y)
  77.         unsigned char addr;
  78.         switch (x) {
  79.                 case 1:
  80.                         addr = 0x80 + y - 1;
  81.                         break;
  82.                 case 2:
  83.                         addr = 0x90 + y - 1;
  84.                         break;
  85.                 case 3:
  86.                         addr = 0x88 + y - 1;
  87.                         break;
  88.                 case 4:
  89.                         addr = 0x98 + y - 1;
  90.                         break;
  91.                 default :
  92.                         break;
  93.         }
  94.         write_com(addr);   //字符显示开始地址
  95. }




  96. //LCD显示字符数组(文字)
  97. void LCD_Putstring( uchar x, uchar y, uchar *pData ) {
  98.         LCD_Setaddress(x, y);
  99.         while (*pData) {
  100.                 write_data( *pData++ );
  101.         }
  102. }

  103. /****************写一个字节*************/
  104. /*************写地址,写数据(方式)**************/

  105. void write_1302_8(uchar dat)
  106. {
  107.         uchar i,temp ;
  108.         for(i=0; i<8; i++)
  109.         {
  110.                 clk = 0;//时钟信号为低时,数据才能改变,同时为出现上升沿做准备
  111.                 temp  = dat&0x01;//取出最低位
  112.                 if(temp )
  113.                         io =1;//如果这一位为1,io拉高
  114.                 else
  115.                         io=0;//如果这一位为0,io拉低
  116.                 clk = 1;//出现上升沿,1302读数据
  117.                 dat=dat>>1;//为送出下一位做准备
  118.                
  119.         }
  120. }

  121. /*****************写操作******************/
  122. /*************写地址,写数据(目的)**************/

  123. void write_1302_byte(uchar add,uchar dat)
  124. {
  125.         ce =0;//不进行操作时拉低
  126.         clk = 0;//时钟线开始前为低
  127.         ce =1;//拉高启动一次写操作过程
  128.         write_1302_8(add );//送地址字节
  129.         write_1302_8(dat );//送数据字节
  130.         ce =0;//一次写操作的结束
  131. }


  132. /*****************读操作*************/
  133. /*************写地址,读数据(sclk)**************/

  134. uchar read_1302_byte(uchar add)
  135. {
  136.         uchar i,value;
  137.         ce =0;
  138.         clk =0;
  139.         ce =1;//开始一次读操作
  140.         write_1302_8(add );//送地址字节
  141.         for(i=0; i<8; i++)
  142.         {
  143.                 clk =0;//读数据时下降沿有效
  144.                 value =value >>1;//将上一次保存的数据移到次高位
  145.                 if(io)//若检测为1
  146.                         value =value|0x80;//将1放到最高位
  147.                 clk =1;//接受完一位后将时钟线拉高,为再次出现下降沿做准备
  148.         
  149.         }
  150.         ce =0;//结束一次读操作过程
  151.         return value ;//将读取的1字节数据传递出去
  152. }



  153. /***************初始化**************/
  154. /**********时间、日期的初始值设置**********/

  155. void ds1302_initial()
  156. {
  157.         uchar i,temp;
  158.         for(i=0; i<7; i++)//给寄存器赋初值之前,将日期、时间转换为BCD码
  159.         {
  160.                 temp = tim0[i]/10;//取十位
  161.                 tim0[i]=temp*16+tim0[i]%10;//bcd 码
  162.         }
  163.         
  164.         write_1302_byte(0x8e,0x00);//给寄存器设置初始值之前,需要去掉写保护
  165.         
  166.         for(i=0; i<7; i++)//每次循环给一个寄存器赋初值
  167.         {
  168.                 write_1302_byte(add_write[i],tim0[i]);
  169.         }
  170.         
  171.         write_1302_byte(0x8e,0x80);//给寄存器设置初始值后,需要加上写保护
  172.         

  173. }



  174. /***************读取时间并进行转换*************/

  175. void read_1302time()
  176. {
  177.         uchar i;
  178.         for(i=0; i<7; i++)//每次循环读一个寄存器内容,保存到tim_bcd[]数组中
  179.         {
  180.                 tim_bcd[i]=read_1302_byte(add_read[i]);
  181.         }
  182.         
  183.         for(i=0; i<7; i++)//将读出的日期、时间分解为十位和个位
  184.         {
  185.                 tim[2*i]=tim_bcd[i]/16;
  186.                 tim[2*i+1]=tim_bcd[i]%16;
  187.         }
  188. }





  189. void Int_232()        //2323?ê??ˉ
  190. {
  191.   TMOD=0x20;
  192.   SCON=0x50;
  193.   TH1=0xFD;
  194.   TL1=0xFD;
  195.   TR1=1;
  196.   TI=0;
  197. }

  198. void TX(uchar TX_char)//′??ú·¢?íêy?Y
  199. {
  200.   SBUF=TX_char;
  201.   while(!TI);
  202.   TI=0;
  203. }

  204. void TXT()//′??ú·¢?í??êy?Y
  205. {
  206.                         uchar i;
  207.                         for(i=0;i<13;i++)
  208.                          {
  209.                                  TX(tim[i]);        
  210.                                        
  211.                          }
  212. }




  213. /***************显示日期和时间**************/

  214. void display_1302()
  215. {
  216.         //Int_232();

  217.         LCD_Setaddress(1,1);
  218.         write_data(0x30+tim[0]);//年
  219.         write_data(0x30+tim[1]);
  220.         write_data('-');
  221.         write_data(0x30+tim[4]);//月
  222.         write_data(0x30+tim[5]);
  223.         write_data('-');
  224.         write_data(0x30+tim[6]);//日
  225.         write_data(0x30+tim[7]);
  226.         write_data(' ');
  227.         write_data(0x30+tim[2]);//周
  228.         write_data(0x30+tim[3]);
  229.         

  230.         LCD_Setaddress(2,1);
  231.         write_data(0x30+tim[8]);
  232.         write_data(0x30+tim[9]);
  233.         write_data(':');
  234.         write_data(0x30+tim[10]);
  235.         write_data(0x30+tim[11]);
  236.         write_data(':');
  237.         write_data(0x30+tim[12]);
  238.         write_data(0x30+tim[13]);
  239. //        TXT();
  240. }



  241. void main()
  242. {
  243.         initial_12864();
  244.         ds1302_initial();
  245.         while(1)
  246.         {        
  247.                 read_1302time();
  248.                 display_1302();

  249.         }

  250. }
复制代码

ds1302.zip

6.28 KB, 下载次数: 6

回复

使用道具 举报

ID:254046 发表于 2022-2-19 21:02 | 显示全部楼层
加载字库的问题吧
回复

使用道具 举报

ID:997450 发表于 2022-2-20 08:05 | 显示全部楼层
cql1980 发表于 2022-2-19 21:02
加载字库的问题吧

但是?之间的“-”和“:”都是正常显示
回复

使用道具 举报

ID:997450 发表于 2022-2-20 16:51 | 显示全部楼层
已确认,找到问题了,是我1302坏了,板上一个坏了,备用的一个也坏了,刚才试第三个的时候突然就好了,运气背到家了
回复

使用道具 举报

ID:96682 发表于 2022-2-20 21:39 来自手机 | 显示全部楼层
这个什么板那么多短接帽?还数码管、LCD 同时显示
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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