找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机DS1302时钟程序分段式编写,调试良好

[复制链接]
跳转到指定楼层
楼主
ID:1009788 发表于 2022-5-1 22:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单片机源程序如下:
  1. /*-----------------------------------------------
  2.   名称:DS1302时钟数码管显示 串口更新
  3.   内容:DS1302实时时钟数码管显示,时间和日期切换显示 按下按键,循环切换
  4.         时间格式xx-xx-xx
  5.                 日期格式xx-xx-xx
  6.                 周秒格式-x-   xx
  7.                 开发板使用12M晶振,通过dofly自带的串口调试软件,打开串口,波特率默认2400,点击更新时间即可,如果不行,按下开发板复位重新更新
  8. ------------------------------------------------*/
  9. #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
  10. #include "ds1302.h"

  11. #define KeyPort P3 //定义按键端口

  12. #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换

  13. sbit LATCH1=P2^2;//定义锁存使能端口 段锁存
  14. sbit LATCH2=P2^3;//                 位锁存

  15. bit ReadTimeFlag;//定义读时间标志
  16. bit SetFlag;     //更新时间标志位
  17. unsigned char time_buf2[16];

  18. unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
  19. unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
  20. unsigned char TempData[5]; //存储显示值的全局变量

  21. void DelayUs2x(unsigned char t);//us级延时函数声明
  22. void DelayMs(unsigned char t); //ms级延时
  23. void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数
  24. unsigned char KeyScan(void);//键盘扫描
  25. void Init_Timer0(void);//定时器初始化
  26. void UART_Init(void);
  27. /*------------------------------------------------
  28.                     主函数
  29. ------------------------------------------------*/
  30. void main (void)
  31. {
  32. unsigned char i,num,displaynum;                  

  33. Init_Timer0();
  34. Ds1302_Init();
  35. UART_Init();
  36. while (1)         //主循环
  37.   {


  38. if(SetFlag)     //如果接收到串口信息则更新时钟
  39.   {
  40.         for(i=0;i<8;i++)
  41.                 {
  42.                 time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];
  43.                 }//数据整合,如2个数 1和5整合成15
  44.                 Ds1302_Write_Time();
  45.                 SetFlag=0;       //时钟信息更新后标志位清零
  46.    }

  47. num=KeyScan();
  48. if(num==5)
  49.   {
  50.    displaynum++;
  51.    if(displaynum==3)
  52.       displaynum=0;
  53.   }
  54. if(ReadTimeFlag==1)
  55. {
  56.   ReadTimeFlag=0;
  57.   Ds1302_Read_Time();
  58. if(displaynum==0) //显示时间
  59. {
  60. TempData[0]=dofly_DuanMa[time_buf1[4]/10];//时                        //数据的转换,因我们采用数码管0~9的显示,将数据分开
  61. TempData[1]=dofly_DuanMa[time_buf1[4]%10];       
  62. TempData[2]=0x40;        //加入"-"
  63. TempData[3]=dofly_DuanMa[time_buf1[5]/10];//分
  64. TempData[4]=dofly_DuanMa[time_buf1[5]%10];

  65. }
  66. else if(displaynum==1)//显示日期
  67. {

  68. TempData[0]=dofly_DuanMa[time_buf1[2]/10];//月
  69. TempData[1]=dofly_DuanMa[time_buf1[2]%10];
  70. TempData[2]=0x40;        //加入"-"
  71. TempData[3]=dofly_DuanMa[time_buf1[3]/10];//日
  72. TempData[4]=dofly_DuanMa[time_buf1[3]%10];       
  73. }
  74. else if(displaynum==2)//显示周  秒
  75. {
  76. TempData[0]=0x40;                                //数据的转换,因我们采用数码管0~9的显示,将数据分开
  77. TempData[1]=dofly_DuanMa[time_buf1[7]%10];//周
  78. TempData[2]=0x40;        //加入"-"

  79. TempData[3]=dofly_DuanMa[time_buf1[6]/10];//秒
  80. TempData[4]=dofly_DuanMa[time_buf1[6]%10];       
  81. }
  82. }       
  83. }
  84. }
  85. /*------------------------------------------------
  86.               串口通讯初始化
  87. ------------------------------------------------*/
  88. void UART_Init(void)
  89. {
  90.     SCON  = 0x50;                        // SCON: 模式 1, 8-bit UART, 使能接收  
  91.     TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
  92.     TH1   = 0xF3;               // TH1:  重装值 2400 波特率 晶振 12MHz  
  93.     TR1   = 1;                  // TR1:  timer 1 打开                        
  94.     EA    = 1;                  //打开总中断
  95.     ES    = 1;                  //打开串口中断
  96. }
  97. /*------------------------------------------------
  98. uS延时函数,含有输入参数 unsigned char t,无返回值
  99. unsigned char 是定义无符号字符变量,其值的范围是
  100. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
  101. 长度如下 T=tx2+5 uS
  102. ------------------------------------------------*/
  103. void DelayUs2x(unsigned char t)
  104. {   
  105. while(--t);
  106. }
  107. /*------------------------------------------------
  108. mS延时函数,含有输入参数 unsigned char t,无返回值
  109. unsigned char 是定义无符号字符变量,其值的范围是
  110. 0~255 这里使用晶振12M,精确延时请使用汇编
  111. ------------------------------------------------*/
  112. void DelayMs(unsigned char t)
  113. {
  114.      
  115. while(t--)
  116. {
  117.      //大致延时1mS
  118.      DelayUs2x(245);
  119.          DelayUs2x(245);
  120. }
  121. }
  122. /*------------------------------------------------
  123. 显示函数,用于动态扫描数码管
  124. 输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
  125. 如输入0表示从第一个显示。
  126. Num表示需要显示的位数,如需要显示99两位数值则该值输入2
  127. ------------------------------------------------*/
  128. void Display(unsigned char FirstBit,unsigned char Num)
  129. {
  130.       static unsigned char i=0;
  131.           

  132.            DataPort=0;   //清空数据,防止有交替重影
  133.        LATCH1=1;     //段锁存
  134.        LATCH1=0;

  135.        DataPort=dofly_WeiMa[i+FirstBit]; //取位码
  136.        LATCH2=1;     //位锁存
  137.        LATCH2=0;

  138.        DataPort=TempData[i]; //取显示数据,段码
  139.        LATCH1=1;     //段锁存
  140.        LATCH1=0;
  141.       
  142.            i++;
  143.        if(i==Num)
  144.               i=0;


  145. }
  146. /*------------------------------------------------
  147.                     定时器初始化子程序
  148. ------------------------------------------------*/
  149. void Init_Timer0(void)
  150. {
  151. TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
  152. //TH0=0x00;              //给定初值
  153. //TL0=0x00;
  154. EA=1;            //总中断打开
  155. ET0=1;           //定时器中断打开
  156. TR0=1;           //定时器开关打开
  157. }
  158. /*------------------------------------------------
  159.                  定时器中断子程序
  160. ------------------------------------------------*/
  161. void Timer0_isr(void) interrupt 1
  162. {
  163. static unsigned int num;
  164. TH0=(65536-2000)/256;                  //重新赋值 2ms
  165. TL0=(65536-2000)%256;

  166. Display(0,5);       // 调用数码管扫描
  167. num++;
  168. if(num==50)        //大致100ms
  169.    {
  170.     num=0;
  171.     ReadTimeFlag=1; //读标志位置1
  172.         }
  173. }

  174. /*------------------------------------------------
  175. 按键扫描函数,返回扫描键值
  176. ------------------------------------------------*/
  177. unsigned char KeyScan(void)
  178. {
  179. unsigned char keyvalue;
  180. if(KeyPort!=0xff)
  181.    {
  182.     DelayMs(10);
  183.     if(KeyPort!=0xff)
  184.            {
  185.             keyvalue=KeyPort;
  186.             while(KeyPort!=0xff);
  187.                 switch(keyvalue)
  188.                 {
  189.                  case 0xfe:return 1;break;
  190.                  case 0xfd:return 2;break;
  191.                  case 0xfb:return 3;break;
  192.                  case 0xf7:return 4;break;
  193.                  case 0xef:return 5;break;
  194.                  case 0xdf:return 6;break;
  195.                  case 0xbf:return 7;break;
  196.                  case 0x7f:return 8;break;
  197.                  default:return 0;break;
  198.                 }
  199.           }
  200.    }
  201.    return 0;
  202. }
  203. /*------------------------------------------------
  204.                   串口中断程序
  205. ------------------------------------------------*/
  206. void UART_SER (void) interrupt 4 //串行中断服务程序
  207. {
  208.     unsigned char Temp;          //定义临时变量
  209.     unsigned char i;
  210.     if(RI)                        //判断是接收中断产生
  211.      {
  212.           RI=0;                      //标志位清零
  213.           Temp=SBUF;                 //读入缓冲区的值
  214.           time_buf2[i]=Temp&0x0F;
  215.           i++;
  216.           if(i==16)                  //连续接收16个字符信息
  217.            {
  218.             i=0;
  219.                 SetFlag=1;               //接收完成标志位置1
  220.            }
  221.       SBUF=Temp; //把接收到的值再发回电脑端
  222.          }
  223.    if(TI)  //如果是发送标志位,清零
  224.      TI=0;
  225. }
复制代码
Keil2代码下载:
Keil2代码只能用Keil2打开.7z (17.95 KB, 下载次数: 49)


评分

参与人数 1黑币 +10 收起 理由
admin + 10 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:278457 发表于 2022-5-4 03:47 | 只看该作者
程序很好,有清晰的思路,模块编程
回复

使用道具 举报

板凳
ID:336378 发表于 2022-5-4 10:09 | 只看该作者
一个字,牛。 模块化的编程思路。
回复

使用道具 举报

地板
ID:645485 发表于 2022-5-27 00:00 | 只看该作者
很标准的编写,阅读性也强,多谢楼主的分享!
但我有一个问题想问一下,没有用LCD1602显示,作者用的是数码管,用的是几位数码管?数码管和单片机的管脚是怎样连接的?还望指教!多谢了!
回复

使用道具 举报

5#
ID:645485 发表于 2022-5-27 00:07 | 只看该作者
分析你程序,位码是8位的话,然后通过按键切换时间和日期,并在数码管显示。这样来看的话,显示的时候中间是没有间隔的,数字是连续的,是这样吗?请帮我解释一下,谢谢!
回复

使用道具 举报

6#
ID:645485 发表于 2022-5-27 00:20 | 只看该作者
我是一名初学者,说的不对的地方,还请楼主多担待!
回复

使用道具 举报

7#
ID:1009788 发表于 2022-9-25 14:09 | 只看该作者
tongguan123 发表于 2022-5-27 00:07
分析你程序,位码是8位的话,然后通过按键切换时间和日期,并在数码管显示。这样来看的话,显示的时候中间 ...

显示是不连续的,但频率超过人眼识别频率了,所以看起来是一秒动一下
回复

使用道具 举报

8#
ID:19006 发表于 2023-2-5 09:45 | 只看该作者
有参考电路图吗?
回复

使用道具 举报

9#
ID:19006 发表于 2023-2-5 09:46 | 只看该作者
3910 发表于 2022-9-25 14:09
显示是不连续的,但频率超过人眼识别频率了,所以看起来是一秒动一下

有原理图吗?电路如何连接的?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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