找回密码
 立即注册

QQ登录

只需一步,快速开始

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

DS1302的单片机时钟proteus通过了,但在实物上不显示?

[复制链接]
回帖奖励 2 黑币 回复本帖可获得 2 黑币奖励! 每人限 1 次
ID:187835 发表于 2017-8-9 04:54 来自手机 | 显示全部楼层 |阅读模式
有用过DS1302的亲吗,帮我看一下?
----------------2017.8.9更新------------------
额,源程序和电路图如下:

DS1302电子钟原理图

DS1302电子钟原理图


  1. #include<reg51.h>
  2. #include<string.h>
  3. #include<intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. sbit SDA = P3^4;// 实物
  7. sbit CLK = P3^6;
  8. sbit RST = P3^5;
  9. sbit EN = P2^7;
  10. sbit RW = P2^5;
  11. sbit RS = P2^6;
  12. sbit K1 = P3^1;
  13. sbit K2 = P3^0;
  14. sbit K3 = P3^2;
  15. sbit K4 = P3^3;

  16. uchar tCount = 0;
  17. //一年中每个月的天数,2月的天数由年份决定
  18. uchar MonthsDays[] = { 0,31,0,31,30,31,30,31,31,30,31,30,31 };
  19. uchar *WEEK[]= {"SUN","MON","TUS","WEN","THU","FRI","SAT"};

  20. //LCD显示缓冲
  21. uchar LCD_DSY_BUFFER1[] = {"DATE 00-00-00   "};//???为什么要空4键?----为后面的YMHD等留空间
  22. uchar LCD_DSY_BUFFER2[] = {"TIME 00:00:00   "};
  23. uchar DateTime[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13}; //所读取的日期时间
  24. char Adjust_Index = -1;//当前调节的时间对象(不调节秒与周)
  25. uchar Change_Flag[] = "-MHDM-Y";

  26. //----------------------------------------------------
  27. //延时
  28. //----------------------------------------------------
  29. void DelayMS(uint x)
  30. {
  31. uchar i;
  32. while(x--) for(i=0;i<120;i++);
  33. }

  34. //----------------------------------------------------
  35. //向DS1302写入一个字节
  36. //----------------------------------------------------
  37. void Write_A_Byte_TO_DS1302(uchar x)
  38. {
  39. uchar i;
  40. for(i=0;i<8;i++)
  41. {
  42.   SDA = x & 0x01;
  43.   x >>= 1;  
  44.   CLK = 1;
  45.   _nop_();
  46.   CLK = 0;
  47.   _nop_();
  48.    }
  49. }

  50. //----------------------------------------------------
  51. //从DS1302读取一字节
  52. //----------------------------------------------------
  53. uchar Get_A_Byte_FROM_DS1302()
  54. {
  55.     uchar i,b,t;
  56. for(i = 0 ;i < 8 ;i++)
  57. {
  58.   t = SDA;
  59.   b = (b>>=1) | (t<<7);  //3
  60.   
  61.   CLK = 1;
  62.   _nop_();
  63.   CLK = 0;
  64.   _nop_();
  65. }
  66. //BCD码转换
  67. return b / 16 * 10+ b % 16;
  68. }

  69. //------------------------------------------------------
  70. //向DS1302某地址写入数据
  71. //------------------------------------------------------
  72. void Write_DS1302(uchar addr,uchar dat)
  73. {
  74. RST = 0;
  75. _nop_();
  76. CLK = 0;                        
  77. _nop_();
  78. RST = 1;
  79. _nop_();
  80. Write_A_Byte_TO_DS1302(addr);
  81. Write_A_Byte_TO_DS1302(dat);
  82. RST = 0;
  83. _nop_();
  84. }

  85. //------------------------------------------------------
  86. //从DS1302指定位置读数据
  87. //------------------------------------------------------
  88. uchar Read_Data(uchar addr)
  89. {
  90. uchar dat;
  91. RST = 0;
  92. _nop_();
  93. CLK = 0;
  94. _nop_();
  95. RST = 1;
  96. _nop_();

  97. Write_A_Byte_TO_DS1302(addr);
  98. dat = Get_A_Byte_FROM_DS1302();

  99. RST = 0;                            //2.以下为DS1302复位的稳定时间,必须的。
  100. _nop_();
  101. CLK = 1;
  102. _nop_();
  103. SDA = 0;
  104. _nop_();
  105. SDA = 1;
  106. _nop_();
  107. // CLK =1;
  108. // RST=0;
  109. return dat;
  110. }

  111. //------------------------------------------------------
  112. //设置时间
  113. //------------------------------------------------------
  114. void SET_DS1302()                                         //(初始化)
  115. {
  116. uchar i;
  117. //写控制字,取消写保护
  118.     Write_DS1302(0x8E,0x00);
  119. //分时日年月依次写入
  120.     for(i = 1; i < 7; i++ )
  121.    {
  122.      Write_DS1302(0x80 + 2*i, (DateTime[i]/10<<4) | (DateTime[i]%10));
  123.      }
  124.   Write_DS1302(0x8E,0x80);//加保护

  125. }

  126. //----------------------------------------------------
  127. //读取当前日期时间
  128. //----------------------------------------------------
  129. void GetTime()
  130. {
  131. uchar i;
  132. for(i = 0; i < 7; i++)
  133.   {
  134.   DateTime[i] = Read_Data(0x81 + 2*i);
  135.   }
  136. }

  137. //------------------------------------------------------
  138. //1602LCD的若干控制代码
  139. //------------------------------------------------------
  140. uchar Read_LCD_State(){
  141. uchar state;
  142. RS=0;RW=1;EN=1;DelayMS(1);state = P0; EN = 0; DelayMS(1);
  143. return state;
  144. }

  145. //------------------------------------------------------
  146. //忙等待
  147. //-------------------------------------------------------
  148. void LCD_Busy_Wait()
  149.    {
  150.     while((Read_LCD_State() & 0x80) == 0x80);
  151.     DelayMS(5);
  152.    }

  153. //------------------------------------------------------
  154. //向LCD写数据
  155. //------------------------------------------------------
  156. void Write_LCD_Data(uchar dat)
  157. {
  158. LCD_Busy_Wait();
  159. RS = 1;
  160. RW = 0;
  161. EN = 0;
  162. P0 = dat;
  163. DelayMS(1);
  164. EN = 1;
  165. DelayMS(5);
  166. EN = 0;
  167. }

  168. //------------------------------------------------------
  169. //写LCD指令
  170. //------------------------------------------------------
  171. void Write_LCD_Command(uchar cmd)
  172. {
  173. LCD_Busy_Wait();
  174. RS = 0;
  175. RW = 0;
  176. EN = 0;
  177. P0 = cmd;
  178. DelayMS(1);
  179. EN = 1;
  180. DelayMS(5);
  181. EN = 0;
  182. }
  183. //------------------------------------------------------
  184. //LCD初始化
  185. //------------------------------------------------------
  186. void Init_LCD()
  187. {
  188. Write_LCD_Command(0x38);DelayMS(1);
  189. Write_LCD_Command(0x0F);DelayMS(1);
  190. Write_LCD_Command(0x01);DelayMS(1);
  191. Write_LCD_Command(0x06);DelayMS(1);
  192. Write_LCD_Command(0x0c);DelayMS(1);
  193. }
  194. //------------------------------------------------------
  195. //设置液晶显示位置
  196. //------------------------------------------------------
  197. void Set_LCD_POS(uchar p)
  198. {
  199. Write_LCD_Command(p | 0x80);
  200. }
  201. //------------------------------------------------------
  202. //在LCD上显示字符串
  203. //------------------------------------------------------
  204. void Display_LCD_String(uchar p,uchar *s)
  205. {
  206. uchar i;
  207. Set_LCD_POS(p);
  208. for(i = 0;i<16;i++)
  209. {
  210.   Write_LCD_Data(s[i]);
  211.   DelayMS(1);
  212. }
  213. }
  214. //------------------------------------------------------
  215. //日期与时间值转换为数字字符
  216. //------------------------------------------------------
  217. void Format_DateTime(uchar d, uchar *a)
  218. {
  219. a[0] = d / 10+'0'; a[1] = d % 10 + '0';
  220. }
  221. //------------------------------------------------------
  222. //判断是否为闰年
  223. //------------------------------------------------------
  224. uchar isLeapYear(uint y)
  225. {
  226. return (y & 4 == 0 && y & 100 != 0) || (y & 400 == 0);
  227. }
  228. //------------------------------------------------------
  229. //求星期几
  230. //------------------------------------------------------
  231. void RefreshWeekDay()
  232. {
  233. uint i,d,w = 5;
  234. for(i = 2000;i< 2000 + DateTime[6];i++)
  235. {
  236.   d = isLeapYear(i) ? 366 : 365;
  237.   w = (w + d) % 7;
  238. }
  239. d = 0;
  240. for(i = 1;i < DateTime[4] ;i++ ) d += MonthsDays[i];
  241. d += DateTime[3];
  242. //保存星期,0~6表示星期日,星期一,二,,,,六,为了与DS1302星期格式匹配,返回值需要加1
  243. DateTime[5] = (w + d) % 7 + 1;
  244. }
  245. //------------------------------------------------------
  246. //年月日时分++ / --
  247. //------------------------------------------------------
  248. void DateTime_Adjust(char x)
  249. {

  250. switch ( Adjust_Index )
  251. {
  252.   case 6://年00-99
  253.         if(x == 1 && DateTime[6] < 99 ) DateTime[6]++;
  254.   if(x == -1 && DateTime[6] > 0 ) DateTime[6]--;
  255.   MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28;
  256.   if(DateTime[3] > MonthsDays[DateTime[4]] )
  257.   DateTime[3] = MonthsDays[DateTime[4]];
  258.   RefreshWeekDay();
  259.   break;
  260.   
  261.   case 4://月
  262.         if(x == 1 && DateTime[4] < 12 ) DateTime[4]++;
  263.   if(x ==-1 && DateTime[4] > 1 ) DateTime[4]--;
  264.   MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28;
  265.   if(DateTime[3] > MonthsDays[DateTime[4]] )
  266.    DateTime[3] = MonthsDays[DateTime[4]];
  267.   RefreshWeekDay();
  268.   break;
  269.   
  270.   case 3://日
  271.   MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28;
  272.         if(x == 1 && DateTime[3] < MonthsDays[DateTime[4]] ) DateTime[3]++;
  273.   if(x == -1 && DateTime[3]>0 ) DateTime[3]--;
  274.   RefreshWeekDay();
  275.   break;
  276.   
  277.   case 2://时
  278.         if(x == 1 && DateTime[2] < 23 ) DateTime[2]++;
  279.   if(x ==-1 && DateTime[2] > 0 ) DateTime[2]--;
  280.   break;
  281.   
  282.   case 1://分
  283.         if(x == 1 && DateTime[1]<59 ) DateTime[1]++;
  284.   if(x == -1 && DateTime[1]>0 ) DateTime[1]--;
  285.   break;
  286. }
  287. }
  288. //------------------------------------------------------
  289. //定时器0每秒刷新LCD显示
  290. //------------------------------------------------------
  291. void T0_INT() interrupt 1
  292. {
  293. TH0 = -5000 / 256;
  294. TL0 = -5000 % 256;

  295. if( ++tCount != 2 ) return;
  296. tCount = 0;
  297. //按指定格式生成待显示的日期时间串
  298. Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5);
  299. Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8);
  300. Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11);
  301. //星期
  302. strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5] - 1]);
  303. //时分秒
  304. Format_DateTime(DateTime[2],LCD_DSY_BUFFER2 + 5);
  305. Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8);
  306. Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11);
  307. //显示年月日、星期、时分秒
  308. Display_LCD_String(0x00,LCD_DSY_BUFFER1);
  309. Display_LCD_String(0x40,LCD_DSY_BUFFER2);
  310. }
  311. //------------------------------------------------------
  312. //键盘中断
  313. //------------------------------------------------------
  314. void EX_INT0() interrupt 0
  315. {
  316. if(K1==0)//选择调整对象(Y M D H M)
  317. {
  318.   while(K1==0);
  319.   if (Adjust_Index == -1 || Adjust_Index == 1 )Adjust_Index = 7;
  320.   Adjust_Index --;
  321.   if (Adjust_Index == 5) Adjust_Index = 4;//跳过对星期的调节
  322.   LCD_DSY_BUFFER2[13] = '[';
  323.   LCD_DSY_BUFFER2[14] = Change_Flag[Adjust_Index];
  324.   LCD_DSY_BUFFER2[15] = ']';
  325. }
  326.      else
  327.   if(K2==0)//加
  328.   {
  329.   while(K2==0);DateTime_Adjust(1);
  330.   }
  331.   else
  332.   if(K3==0)//减
  333.   {
  334.   while(K3==0);DateTime_Adjust(-1);
  335.   }
  336.   else
  337.   if(K4==0)//确定
  338.   {
  339.       while(K4==0);
  340.    SET_DS1302();//将调整后的时间写入DS1302
  341.    LCD_DSY_BUFFER2[13] = ' ';
  342.    LCD_DSY_BUFFER2[14] = ' ';
  343.    LCD_DSY_BUFFER2[15] = ' ';
  344.    Adjust_Index = -1;//操作索引重设为-1,时间继续正常显示
  345.   }
  346. }
  347. //------------------------------------------------------
  348. //主程序
  349. //------------------------------------------------------
  350. //void Int0Configuration()
  351. //{
  352. // //设置INT0
  353. // IT0=1;//跳变沿出发方式(下降沿)
  354. // EX0=1;//打开INT0的中断允许。
  355. // EA=1;//打开总中断
  356. //}
  357. void main()
  358. {   
  359. Init_LCD();//液晶初始化
  360. IE = 0x83;//允许INT0,T0中断
  361. IP = 0x01;
  362. IT0 = 0X01;
  363. TMOD = 0x01;
  364. TH0 = -5000 / 256;
  365. TL0 = -5000 % 256;
  366. TR0 = 1;
  367. while(1)
  368. {
  369.    //如果未执行调整操作则正常读取当前时间
  370.   if(Adjust_Index == -1) GetTime();
  371. }
  372. }
复制代码


全部资料下载地址:
DS1302设计的电子钟.rar (60.13 KB, 下载次数: 7)
回复

使用道具 举报

ID:105206 发表于 2017-8-9 05:18 | 显示全部楼层
没程序怎么看,发程序上来。
回复

使用道具 举报

ID:167440 发表于 2017-8-9 08:11 | 显示全部楼层
亲,仔细看看你的实物真的是DS1302吗?肯能是DS1307呀!!!DS1302与DS1307通信是不一样的
回复

使用道具 举报

ID:219560 发表于 2017-8-9 09:50 | 显示全部楼层
如果仿真可以的话,很大的可能是硬件问题。建议:1. 确定IO都对应;2. 测试一下显示模块;
回复

使用道具 举报

ID:219560 发表于 2017-8-9 09:50 | 显示全部楼层
最好把电路和程序贴出来!
回复

使用道具 举报

ID:187835 发表于 2017-8-9 19:16 | 显示全部楼层
jubaolun 发表于 2017-8-9 05:18
没程序怎么看,发程序上来。

已更新
回复

使用道具 举报

ID:187835 发表于 2017-8-9 19:22 | 显示全部楼层
本帖最后由 Magatop 于 2017-8-9 20:21 编辑
浮云骑士 发表于 2017-8-9 08:11
亲,仔细看看你的实物真的是DS1302吗?肯能是DS1307呀!!!DS1302与DS1307通信是不一样的

回复

使用道具 举报

ID:187835 发表于 2017-8-9 19:22 | 显示全部楼层
qingtao 发表于 2017-8-9 09:50
如果仿真可以的话,很大的可能是硬件问题。建议:1. 确定IO都对应;2. 测试一下显示模块;

这两项都正确。。
回复

使用道具 举报

ID:187835 发表于 2017-8-9 19:23 | 显示全部楼层
qingtao 发表于 2017-8-9 09:50
最好把电路和程序贴出来!

已贴
回复

使用道具 举报

ID:187835 发表于 2017-8-9 20:24 | 显示全部楼层
qingtao 发表于 2017-8-9 09:50
如果仿真可以的话,很大的可能是硬件问题。建议:1. 确定IO都对应;2. 测试一下显示模块;

这两项是正确的
回复

使用道具 举报

ID:187835 发表于 2017-8-9 20:53 | 显示全部楼层
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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