找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4952|回复: 10
收起左侧

单片机+lcd12864显示ds1302程序出现乱码,卡好几天了

[复制链接]
ID:434977 发表于 2019-1-16 09:30 | 显示全部楼层 |阅读模式
IMG_20190116_092713.jpg

单片机源码:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit lcd_rs=P3^4;
  6. sbit lcd_rw=P3^5;
  7. sbit lcd_e=P3^6;
  8. sbit lcd_psb=P3^7;
  9. sbit ds1302_io=P1^1;
  10. sbit ds1302_sclk=P1^2;
  11. sbit ds1302_rst=P1^0;
  12. //DS1302地址定义
  13. #define ds1302_sec_addr                        0x80                //秒数据地址
  14. #define ds1302_min_addr                        0x82                //分数据地址
  15. #define ds1302_hour_addr                0x84                //时数据地址
  16. #define ds1302_date_addr                0x86                //日数据地址
  17. #define ds1302_month_addr                0x88                //月数据地址
  18. #define ds1302_day_addr                        0x8a                //星期数据地址
  19. #define ds1302_year_addr                0x8c                //年数据地址
  20. #define ds1302_control_addr                0x8e                //控制数据地址
  21. #define ds1302_charger_addr                0x90                 //涓流充电                        
  22. #define ds1302_clkburst_addr        0xbe                //时钟多字节
  23. //初始时间定义
  24. uchar time_buf[8] = {0x20,0x19,0x01,0x12,0x15,0x30,0x50,0x02};//初始时间
  25. uchar readtime[14];//当前时间
  26. uchar sec_buf=0;  //秒缓存
  27. uchar sec_flag=0; //秒标志位
  28. void delay_ms(uint z)
  29. {
  30.         uint x,y;
  31.         x=0;
  32.         while(x<z)
  33.         {
  34.                 y=114;
  35.                 while(y)
  36.                 {
  37.                         y--;
  38.                 }
  39.                 x++;
  40.         }
  41. }
  42. void sendbyte(uint zj)
  43. {
  44.         int i;                                                                 
  45.         for(i=0;i<8;i++)
  46.         {
  47.                 lcd_rw=(bit)(zj&0x80);
  48.                 lcd_e=0;
  49.                 lcd_e=1;
  50.                 zj<<=1;
  51.         }
  52. }
  53. void lcd_write_com(uint com)
  54. {
  55.         uint _com;
  56.         lcd_rs=1;                                                                 
  57.         lcd_e=0;
  58.         _com=0xf8;
  59.         sendbyte(_com);
  60.         _com=com&0xf0;
  61.         sendbyte(_com);
  62.         _com=com<<4;
  63.         sendbyte(_com);
  64.         delay_ms(10);
  65. }
  66. void lcd_write_data(uint dt)
  67. {
  68.         uint _data;
  69.         lcd_rs=1;
  70.         lcd_e=0;
  71.         _data=0xfa;
  72.         sendbyte(_data);
  73.         _data=dt&0xf0;
  74.         sendbyte(_data);
  75.         _data=dt<<4;
  76.         sendbyte(_data);
  77.         delay_ms(10);
  78. }
  79. void lcd_pos(uint x,uint y)
  80. {
  81.         uint pos;
  82.         if(x==0)x=0x80;
  83.         if(x==1)x=0x90;
  84.         if(x==2)x=0x88;
  85.         if(x==3)x=0x98;
  86.         pos=x+y;
  87.         lcd_write_com(pos);
  88.         delay_ms(10);
  89. }
  90. void lcd_init()
  91. {
  92.         lcd_psb=0;
  93.         lcd_write_com(0x30);
  94.         lcd_write_com(0x0c);
  95.         lcd_write_com(0x01);
  96.         lcd_pos(0,0);
  97.         delay_ms(10);
  98. }
  99. void ds1302_write_byte(uchar byte)
  100. {
  101.         uchar i,temp;
  102.         ds1302_rst=0;
  103.         ds1302_sclk=0;
  104.         ds1302_rst=1;
  105.         for(i=0;i<8;i++)
  106.         {
  107.                 ds1302_sclk=0;
  108.                 _nop_();
  109.                 temp=byte&0x01;
  110.                 if(temp)ds1302_io=1;
  111.                 else ds1302_io=0;
  112.                 _nop_();
  113.                 ds1302_sclk=1;
  114.                 byte>>=1;
  115.                 _nop_();
  116.                 _nop_();

  117.         }
  118.         ds1302_rst=0;
  119.         _nop_();
  120. }
  121. uchar ds1302_read_byte(uchar addr)
  122. {
  123.         uchar i,temp;
  124.         ds1302_rst=0;
  125.         ds1302_sclk=0;
  126.         ds1302_rst=1;
  127.         addr=addr|0x01;
  128.         for(i=0;i<8;i++)
  129.         {
  130.                 ds1302_sclk=0;
  131.                 _nop_();
  132.                 temp=addr&0x01;
  133.                 if(temp)ds1302_io=1;
  134.                 else ds1302_io=0;
  135.                 _nop_();
  136.                 ds1302_sclk=1;
  137.                 addr>>=1;
  138.         }
  139.                 ds1302_io=1;
  140.         for(i=0;i<8;i++)
  141.         {
  142.                 ds1302_sclk=1;
  143.                 _nop_();
  144.                 if(ds1302_io)
  145.                 {temp=temp|0x80;}
  146.                 else {temp=temp&0x7f;}
  147.                 temp>>=1;
  148.                 _nop_();
  149.                 //if(i!=7)
  150.                 ds1302_sclk=0;
  151.                 _nop_();
  152.                 ds1302_io=1;
  153.         }
  154.         ds1302_rst=0;
  155.         delay_ms(5);
  156.         return temp;
  157. }
  158. void        ds1302_init_time()
  159. {
  160.         ds1302_write_byte(ds1302_control_addr&0xfe);ds1302_write_byte(0x00);
  161.         ds1302_write_byte(ds1302_sec_addr&0xfe);ds1302_write_byte(0x80);
  162.         ds1302_write_byte(ds1302_year_addr&0xfe);ds1302_write_byte(time_buf[1]);
  163.         ds1302_write_byte(ds1302_month_addr&0xfe);ds1302_write_byte(time_buf[2]);
  164.         ds1302_write_byte(ds1302_date_addr&0xfe);ds1302_write_byte(time_buf[3]);
  165.         ds1302_write_byte(ds1302_hour_addr&0xfe);ds1302_write_byte(time_buf[4]);
  166.         ds1302_write_byte(ds1302_min_addr&0xfe);ds1302_write_byte(time_buf[5]);
  167.         ds1302_write_byte(ds1302_sec_addr&0xfe);ds1302_write_byte(time_buf[6]);
  168.         ds1302_write_byte(ds1302_day_addr&0xfe);ds1302_write_byte(time_buf[7]);
  169.         ds1302_write_byte(ds1302_control_addr&0xfe);ds1302_write_byte(0x80);
  170. }
  171. void ds1302_read_time()
  172. {
  173.         time_buf[1]=ds1302_read_byte(ds1302_year_addr);                //年
  174.         time_buf[2]=ds1302_read_byte(ds1302_month_addr);           //月
  175.         time_buf[3]=ds1302_read_byte(ds1302_date_addr);                //日
  176.         time_buf[4]=ds1302_read_byte(ds1302_hour_addr);                //时
  177.         time_buf[5]=ds1302_read_byte(ds1302_min_addr);                //分
  178.         time_buf[6]=(ds1302_read_byte(ds1302_sec_addr))%59;        //秒,屏蔽秒的第7位,避免超出59
  179.         time_buf[7]=ds1302_read_byte(ds1302_day_addr);                //周        
  180. }
  181. void ds1302_init()
  182. {
  183.         ds1302_rst=0;
  184.         ds1302_sclk=0;
  185.         ds1302_io=1;

  186. }
  187. void main()
  188. {
  189.         delay_ms(10);
  190.         ds1302_init();
  191.         lcd_init();      
  192.         delay_ms(10);
  193.         ds1302_sclk=1;
  194.         ds1302_init_time();
  195.         ds1302_sclk=0;
  196.         while(1)
  197.         {         
  198.                 ds1302_sclk=1;
  199.                  ds1302_read_time();
  200.                 ds1302_sclk=0;
  201.                 readtime[0]=(time_buf[0]>>4);   //分离出年千位
  202.                   readtime[1]=(time_buf[0]&0x0F); //分离出年百位
  203.                   readtime[2]=(time_buf[1]>>4);   //分离出年十位
  204.                   readtime[3]=(time_buf[1]&0x0F); //分离出年个位

  205.                   readtime[4]=(time_buf[2]>>4);   //分离出月十位
  206.                   readtime[5]=(time_buf[2]&0x0F); //分离出月个位

  207.                 readtime[6]=(time_buf[3]>>4);   //分离出日十位
  208.                 readtime[7]=(time_buf[3]&0x0F); //分离出日个位

  209.                 readtime[8]=(time_buf[4]>>4);   //分离出小时十位
  210.                   readtime[9]=(time_buf[4]&0x0F); //分离出小时个位
  211.                   readtime[10]=(time_buf[5]>>4);   //分离出分钟十位
  212.                   readtime[11]=(time_buf[5]&0x0F); //分离出分钟个位
  213.                   readtime[12]=(time_buf[6]>>4);   //分离出秒钟十位
  214.                 readtime[13]=(time_buf[6]&0x0F); //分离出秒钟个位   
  215.                 if(readtime[13]!=sec_buf)      
  216.         {           
  217.                 sec_flag=0;   
  218.                 sec_buf=readtime[13];
  219.                 lcd_pos(1,1);         
  220.                 lcd_write_data(readtime[0]+'0');//年
  221.                 lcd_write_data(readtime[1]+'0');     
  222.             lcd_write_data(readtime[2]+'0');
  223.                 lcd_write_data(readtime[3]+'0');   

  224.                 lcd_write_data('-');
  225.          
  226.             lcd_write_data(readtime[4]+'0');//月
  227.                 lcd_write_data(readtime[5]+'0');

  228.                 lcd_write_data('-');

  229.             lcd_write_data(readtime[6]+'0');//日
  230.                 lcd_write_data(readtime[7]+'0');

  231.                 lcd_write_data(' ');

  232.                 lcd_pos(2,1);
  233.                 lcd_write_data(readtime[8]+'0');//时
  234.                 lcd_write_data(readtime[9]+'0');

  235.                 lcd_write_data(':');

  236.                 lcd_write_data(readtime[10]+'0');//分
  237.                 lcd_write_data(readtime[11]+'0');

  238.                 lcd_write_data(':');

  239.                 lcd_write_data(readtime[12]+'0');//秒
  240.                 lcd_write_data(readtime[13]+'0');      
  241.            }
  242.                            delay_ms(100);
  243.    }
  244. }
复制代码

回复

使用道具 举报

ID:434977 发表于 2019-1-16 13:37 | 显示全部楼层
哪位大佬指点一下,十分感谢,卡好几天了
回复

使用道具 举报

ID:454000 发表于 2019-1-16 15:01 | 显示全部楼层
字符占的位子不对,你将带问号的地方敲一下空格(英文输入情况下的空格),再输入数字看看。正常情况输入汉字没问题,但输数字与英文就会这样。要想正常显示,要重新写一个字符显示函数。坛子里面有一篇<<12864液晶数字任意显示器>>的文章,里面有写好的函数,可以试一下

评分

参与人数 3黑币 +62 收起 理由
钻牛尖滴刘尖尖 + 15
Sawardeakar + 35
yoxi + 12 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:7485 发表于 2019-1-16 15:13 | 显示全部楼层
ds1302写和读不是一个地址。81、83、85、......91是读,80、82、84、........90是写。
回复

使用道具 举报

ID:386762 发表于 2019-1-16 15:57 | 显示全部楼层
你的写入程序有点问题:写入地址之后直接写入数据,你的时序导致数据没有写入,读出数据都为0X7F.
EM截图_201911615558.jpg

可以参考以下DS1302程序
  1. //---DS1302写入和读取时分秒的地址命令---////---秒分时日月周年 最低位读写位;-------//uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
  2. uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
  3. //---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---////---存储顺序是秒分时日月周年,存储格式是用BCD码---//
  4. uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16};
  5. /********************************************************************************
  6. 函 数 名         : Ds1302Write
  7. * 函数功能         : 向DS1302命令(地址+数据)
  8. * 输    入         : addr,dat
  9. * 输    出         : 无
  10. *******************************************************************************/
  11. void Ds1302Write(uchar addr, uchar dat)
  12. {   
  13. uchar n;   
  14. RST = 0;   
  15. _nop_();   
  16. SCLK = 0;
  17. //先将SCLK置低电平。
  18.    _nop_();   
  19. RST = 1;
  20. //然后将RST(CE)置高电平。   
  21. _nop_();   
  22. for (n=0; n<8; n++)
  23. //开始传送八位地址命令   
  24. {        
  25. DSIO = addr & 0x01;//数据从低位开始传送        
  26. addr >>= 1;        
  27. SCLK = 1;//数据在上升沿时,DS1302读取数据      
  28. _nop_();      
  29. SCLK = 0;        
  30. _nop_();   
  31. }   
  32. for (n=0; n<8; n++)//写入8位数据   
  33. {        
  34. DSIO = dat & 0x01;        
  35. dat >>= 1;      
  36. SCLK = 1;//数据在上升沿时,DS1302读取数据        
  37. _nop_();        
  38. SCLK = 0;        
  39. _nop_();      
  40. }               
  41. RST = 0;//传送数据结束    _
  42. nop_();}
  43. /********************************************************************************
  44. 函 数 名         : Ds1302Read
  45. * 函数功能         : 读取一个地址的数据
  46. * 输    入         : addr
  47. * 输    出         : dat
  48. *******************************************************************************/
  49. uchar Ds1302Read(uchar addr)
  50. {   
  51. uchar n,dat,dat1;   
  52. RST = 0;   
  53. _nop_();   
  54. SCLK = 0;//先将SCLK置低电平。   
  55. _nop_();   
  56. RST = 1;//然后将RST(CE)置高电平。   
  57. _nop_();   
  58. for(n=0; n<8; n++)//开始传送八位地址命令   
  59. {        
  60. DSIO = addr & 0x01;//数据从低位开始传送        
  61. addr >>= 1;        
  62. SCLK = 1;//数据在上升沿时,DS1302读取数据        
  63. _nop_();        
  64. SCLK = 0;//DS1302下降沿时,放置数据        
  65. _nop_();   
  66. }   
  67. _nop_();   
  68. for(n=0; n<8; n++)//读取8位数据   
  69. {        
  70. dat1 = DSIO;//从最低位开始接收        
  71. dat = (dat>>1) | (dat1<<7);        
  72. SCLK = 1;        
  73. _nop_();        
  74. SCLK = 0;//DS1302下降沿时,放置数据        
  75. _nop_();   
  76. }   
  77. RST = 0;   
  78. _nop_();    //以下为DS1302复位的稳定时间,必须的。   
  79. SCLK = 1;   
  80. _nop_();   
  81. DSIO = 0;   
  82. _nop_();   
  83. DSIO = 1;   
  84. _nop_();   
  85. return dat;
  86. }
  87. /*******************************************************************************
  88. * 函 数 名         : Ds1302Init
  89. * 函数功能         : 初始化DS1302.
  90. * 输    入         : 无
  91. * 输    出         : 无
  92. *******************************************************************************/
  93. void Ds1302Init()
  94. {   
  95. uchar n;   
  96. Ds1302Write(0x8E,0X00);      //禁止写保护,就是关闭写保护功能   
  97. for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年   
  98. {        
  99. Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);     
  100. }   
  101. Ds1302Write(0x8E,0x80);      //打开写保护功能}
  102. /*******************************************************************************
  103. * 函 数 名         : Ds1302ReadTime
  104. * 函数功能         : 读取时钟信息
  105. * 输    入         : 无
  106. * 输    出         : 无
  107. *******************************************************************************/
  108. void Ds1302ReadTime()
  109. {   
  110. uchar n;   
  111. for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年   
  112. {        
  113. TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);   
  114. }      
  115.   }
复制代码


评分

参与人数 1黑币 +15 收起 理由
凌净清河 + 15 赞一个!

查看全部评分

回复

使用道具 举报

ID:7485 发表于 2019-1-17 04:20 | 显示全部楼层
你仔细看看Jason_Jay 给你的程序,关键是 addr & 0x01      
,将地址的二进制码的末位变成“1”,就是80变成 81, 82变成 83……,这才是“读”的地址!
回复

使用道具 举报

ID:66761 发表于 2019-1-17 11:06 | 显示全部楼层
IIC通讯最好要进行ASK 超时处理,可以仿真一下确定一下具体问题,看看读取的数据不正确,还是显示部分有问题,
回复

使用道具 举报

ID:434977 发表于 2019-1-18 15:54 | 显示全部楼层
ahshmj 发表于 2019-1-16 15:13
ds1302写和读不是一个地址。81、83、85、......91是读,80、82、84、........90是写。

我读函数里面,地址都加了一,这样就只定义写的地址就行了,读的地址可以在读函数里更改
回复

使用道具 举报

ID:434977 发表于 2019-1-18 16:02 | 显示全部楼层
ahshmj 发表于 2019-1-17 04:20
你仔细看看Jason_Jay 给你的程序,关键是 addr & 0x01      
,将地址的二进制码的末位变成“1”,就是80 ...

我读的地址,是在读的函数里把写的地址每个后面都加1,这样应该也是可以的吧?
回复

使用道具 举报

ID:434977 发表于 2019-1-18 16:03 | 显示全部楼层
shuisheng 发表于 2019-1-16 15:01
字符占的位子不对,你将带问号的地方敲一下空格(英文输入情况下的空格),再输入数字看看。正常情况输入汉字 ...

我看了一下,显示函数没问题,我怀疑,会不会是ds1302原件没有工作的原因,但我不知道怎么检测ds1302是否工作了。
回复

使用道具 举报

ID:434977 发表于 2019-1-18 16:05 | 显示全部楼层
xingxing123w 发表于 2019-1-17 11:06
IIC通讯最好要进行ASK 超时处理,可以仿真一下确定一下具体问题,看看读取的数据不正确,还是显示部分有问 ...

我刚接触,不会仿真......
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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