JackCin's blog JackCin's blog
首页
  • 页面

    • Html
    • CSS
  • 核心

    • JavaScript基础
    • JavaScript高级
  • 框架

    • Vue
  • jQuery
  • Node
  • Ajax
Linux
  • 操作系统
  • 数据结构与算法
  • 51单片机
  • CC2530
  • 网站
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

JackCin

前端小菜鸡(✪ω✪)
首页
  • 页面

    • Html
    • CSS
  • 核心

    • JavaScript基础
    • JavaScript高级
  • 框架

    • Vue
  • jQuery
  • Node
  • Ajax
Linux
  • 操作系统
  • 数据结构与算法
  • 51单片机
  • CC2530
  • 网站
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 51单片机

    • 51单片机及补充知识
    • LED
    • 独立按键
    • 数码管
    • LCD1602液晶显示器
    • 矩阵按键
    • 定时器
    • 串口
    • LED点阵屏
    • 蜂鸣器
    • AT24C02存储器
    • AD与DA
    • DS18B20温度传感器
    • DS1302时钟
      • LCD1602液晶显示屏
      • 红外遥控
      • 呼吸灯与直流电机调速(PWM)
    • 单片机
    • 51单片机
    JackCin
    2023-09-13
    目录

    DS1302时钟

    # DS1302时钟

    # 1、DS1302介绍

    • DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能
    • RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片
      • 我们51单片机的就是这样一个DS1302芯片。

    img

    # 2、引脚定义和应用电路

    img

    • 这边是DS1302与CPU之间的一个关系,我先列一个表格来介绍一下各个部分的功能。

    # 3、寄存器定义

    • DS1302的寄存器比较多,我们来一一介绍一下:

    img

    从上往下,依次是秒,分,时,天,月,星期几(1~7),年。之后的WP是写入保护,置1则写入无效哎,但还可以读数。再下面一行,就是涓流充电模式,也就是内置电源,51单片机没有,我们就先不写这个。

    注:CH是时钟停止引脚

    # 4、命令字

    img

    命令字要解决的问题就是,我要去哪操作,以及,我要读出还是写入这两个问题。第一位,就是看是读出还是写入,当为0时,是写入,为1是读出;2~6位是地址,7位是操控的地方是时钟还是RAM;8位都是1。命令字其实都已经在前两列表示出来了。

    # 5、时序

    img

    • 注意这里的读时序和写时序他们的 SCLK 上下沿有区别

    首先,我们需要写好刚刚介绍的命令字部分,每一个上升沿就是一次写入,而下降沿就是输出,所以输入输出主要的区别就是后面部分,从D0~D7,就是我们要操作的数据。

    # 6、代码

    • DS1302.c
    #include <REGX52.H>
    
    // 根据原理图,应该可以写出下面几个引脚定义
    sbit DS1302_SCLK = P3^6;
    sbit DS1302_CE = P3^5;
    sbit DS1302_IO = P3^4;
    
    
    //寄存器写入地址/指令定义
    #define DS1302_SECOND		0x80
    #define DS1302_MINUTE		0x82
    #define DS1302_HOUR			0x84
    #define DS1302_DATE			0x86
    #define DS1302_MONTH		0x88
    #define DS1302_DAY			0x8A
    #define DS1302_YEAR			0x8C
    #define DS1302_WP			0x8E
    
    //时间数组,索引0~6分别为年、月、日、时、分、秒、星期
    unsigned char DS1302_Time[]={23,3,1,11,57,55,3};
    
    
    // 初始化函数,因为单片机接电后默认为1
    /**
      * @brief  DS1302初始化
      * @param  无
      * @retval 无
    */
    void DS1302_Init()
    {
    	DS1302_CE=0;
    	DS1302_SCLK=0;
    }
    
    
    // 写入函数
    /**
      * @brief  DS1302写一个字节
      * @param  Command 命令字/地址
      * @param  Data 要写入的数据
      * @retval 无
      */
    void DS1302_WriteByte(unsigned char Command,Date)
    {
    	unsigned char i;
    	DS1302_CE=1;
    	//读取低位
    	for(i=0;i<8;i++)
    	{
    	DS1302_IO=Command&(0x01<<i);
    	//可能需要加延时函数,因为切换太快了,但是51可以不加
    	DS1302_SCLK=1;
    	DS1302_SCLK=0;
    	}
    	
    	for(i=0;i<8;i++)
    	{
    	DS1302_IO=Date&(0x01<<i);
    	// 可能需要加延时函数,因为切换太快了,但是51可以不加
    	DS1302_SCLK=1;
    	DS1302_SCLK=0;
    	}
    	
    	DS1302_CE=0;
    }
    
    
    // 读取的话,周期是15个,与写入的16个周期不同,所以才有下面代码的转变
    /**
      * @brief  DS1302读一个字节
      * @param  Command 命令字/地址
      * @retval 读出的数据
      */
    unsigned char DS1302_ReadByte(unsigned char Command)
    {
    	unsigned int i,Date=0x00;
    	
    	//为了统一数据,因为读的时候,末尾一定是1
    	Command|=0x01;//写Command++也可以
    	DS1302_CE=1;
    	//读取地位
    	for(i=0;i<8;i++)
    	{
    		DS1302_IO=Command&(0x01<<i);
    		// 这么做的原因就是在第8个脉冲下降沿的时候,数据已经读出了
    		DS1302_SCLK=0;
    		DS1302_SCLK=1;
    	}
    	//读取下降沿
    	for(i=0;i<8;i++)
    	{
    		DS1302_SCLK=1;
    		DS1302_SCLK=0;
    		if(DS1302_IO)
    		{
    			Date|=(0x01<<i);
    		}
    	}
    	
    	// 返回前先将IO口置为0(这个操作必须加)
    	DS1302_IO=0;
    	DS1302_CE=0;
    	
    	return Date;
    }
    
    
    /**
      * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
      * @param  无
      * @retval 无
      */
    
    void DS1302_SetTime(void)
    {
    	DS1302_WriteByte(DS1302_WP,0x00);
    	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
    	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
    	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
    	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
    	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
    	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
    	DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
    	DS1302_WriteByte(DS1302_WP,0x80);	
    }
    
    
    /**
      * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
      * @param  无
      * @retval 无
      */
    void DS1302_ReadTime(void)
    {
    	unsigned char Temp;
    	Temp=DS1302_ReadByte(DS1302_YEAR);
    	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
    	Temp=DS1302_ReadByte(DS1302_MONTH);
    	DS1302_Time[1]=Temp/16*10+Temp%16;
    	Temp=DS1302_ReadByte(DS1302_DATE);
    	DS1302_Time[2]=Temp/16*10+Temp%16;
    	Temp=DS1302_ReadByte(DS1302_HOUR);
    	DS1302_Time[3]=Temp/16*10+Temp%16;
    	Temp=DS1302_ReadByte(DS1302_MINUTE);
    	DS1302_Time[4]=Temp/16*10+Temp%16;
    	Temp=DS1302_ReadByte(DS1302_SECOND);
    	DS1302_Time[5]=Temp/16*10+Temp%16;
    	Temp=DS1302_ReadByte(DS1302_DAY);
    	DS1302_Time[6]=Temp/16*10+Temp%16;
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    • main.c
    #include <REGX52.H>
    #include "LCD1602.h"
    #include "DS1302.h"
    
    
    void main()
    {
    	
    	LCD_Init();
    	DS1302_Init();
    	
    	LCD_ShowString(1,1,"  -  -  ");//静态字符初始化显示
    	LCD_ShowString(2,1,"  :  :  ");
    
    	DS1302_SetTime();//设置时间
    	
    	while(1)
    	{
    		DS1302_ReadTime();//读取时间
    		LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
    		LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
    		LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
    		LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
    		LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
    		LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
    
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    编辑 (opens new window)
    上次更新: 2023/09/13, 12:29:52
    DS18B20温度传感器
    LCD1602液晶显示屏

    ← DS18B20温度传感器 LCD1602液晶显示屏→

    最近更新
    01
    51单片机及补充知识
    09-13
    02
    独立按键
    09-13
    03
    LCD1602液晶显示器
    09-13
    更多文章>
    Theme by Vdoing | Copyright © 2019-2023 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式