• 普中51单片机学习(DS1302)


    DS1302时钟

    DS1302实时时钟具有能计算2100年之前的秒、分、时、日、日期、星期、月、年的能力,还有闰年调整的能力。内部含有31个字节静态RAM,可提供用户访问。采用串行数据传送方式,使得管脚数量最少,简单SPI 3线接口。工作电压范围宽:2.0~5.5V。工作电流:2.0V时,小于300nA。时钟或RAM数据的读/写有两种传送方式:单字节传送和多字节传送方式。采用8脚DIP封装或SOIC封装。与TTL兼容,Vcc=5V。可选工业级温度范围:-40℃~+85℃。具有涓流充电能力。采用主电源和备份电源双电源供应。备份电源可由电池或大容量电容实现。

    SPI总线概念
    SPI接口的全称是“Serial Peripheral Interface”,意为串行外围接口。
    SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
    SPI接口是在CPU和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,高位在前,地位在后,为全双工通信,数据传输速度总体来说比I2C总线要快,速度可达到几Mbps。
    SPI接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从器件,其接口包括以下四种信号:

    • MOSI – 主器件数据输出,从器件数据输入
    • MISO – 主器件数据输入,从器件数据输出
    • SCLK – 时钟信号,由主器件产生
    • /CS – 从器件使能信号,由主器件控制

    在这里插入图片描述
    引脚功能
    在这里插入图片描述
    其中:

    • X1、X2:32.768KHz晶振接入引脚。
    • GND:地。
    • RST :复位引脚,低电平有效,操作时高电平。
    • I/O:数据输入/输出引脚,具有三态功能。
    • SCLK:串行时钟输入引脚。
    • Vcc1:工作电源引脚。
    • Vcc2:备用电源引脚。 接入电池断电时提供1302电源

    DS1302的寄存器及片内RAM
    DS1302有一个控制寄存器、12个日历、时钟寄存器和31个RAM。可读写。
    控制寄存器用于存放DS1302的控制命令字,DS1302的RST引脚回到高电平后写入的第一个字就为控制命令。它用于对DS1302读写过程进行控制,它的格式如下:
    在这里插入图片描述
    DS1302共有12个寄存器,其中有7个与日历、时钟相关,存放的数据为BCD码形式。日历、时钟寄存器的格式如表。
    在这里插入图片描述
    在这里插入图片描述
    片内RAM
    DS1302片内有31个RAM单元,对片内RAM的操作有两种方式:单字节方式和多字节方式。当控制命令字为C0HFDH时为单字节读写方式,命令字中的D5D1用于选择对应的RAM单元,其中奇数为读操作,偶数为写操作。
    当控制命令字为FEH、FFH时为多字节操作(表中的RAM突发模式),多字节操作可一次把所有的RAM单元内容进行读写。FEH为写操作,FFH为读操作。

    数据输入输出(I/O)
    在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

    单字节读写
    在这里插入图片描述

    • DS1302是通过SPI串行总线跟单片机通信的,当进行一次读写操作时最少得读写两个字节,第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOK寄存器操作。第二个字节就是要读或写的数据了。
    • 单字节读写:只有在SCLK为低电平时,才能将CE置为高电平。所以在进行操作之前先将SCLK置低电平,然后将CE置为高电平,接着开始在IO上面放入要传送的电平信号,然后跳变SCLK。数据在SCLK上升沿时,DS1302读写数据,在SCLK下降沿时,DS1302放置数据到IO上。

    在这里插入图片描述

    实验代码

    ds1302.h

    #ifndef __DS1302_H_
    #define __DS1302_H_
    
    //---包含头文件---//
    #include
    #include
    
    //---重定义关键词---//
    #ifndef uchar
    #define uchar unsigned char
    #endif
    
    #ifndef uint 
    #define uint unsigned int
    #endif
    
    //---定义ds1302使用的IO口---//
    sbit DSIO=P3^4;
    sbit RST=P3^5;
    sbit SCLK=P3^6;
    
    //---定义全局函数---//
    void Ds1302Write(uchar addr, uchar dat);
    uchar Ds1302Read(uchar addr);
    void Ds1302Init();
    void Ds1302ReadTime();
    
    //---加入全局变量--//
    extern uchar TIME[7];	//加入全局变量
    
    #endif
    
    • 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

    da13.2.c

    #include"ds1302.h"
    
    //---DS1302写入和读取时分秒的地址命令---//
    //---秒分时日月周年 最低位读写位;-------//
    uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
    uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
    
    //---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---//
    //---存储顺序是秒分时日月周年,存储格式是用BCD码---//
    uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16};
    
    /*******************************************************************************
    * 函 数 名         : Ds1302Write
    * 函数功能		   : 向DS1302命令(地址+数据)
    * 输    入         : addr,dat
    * 输    出         : 无
    *******************************************************************************/
    
    void Ds1302Write(uchar addr, uchar dat)
    {
    	uchar n;
    	RST = 0;
    	_nop_();
    
    	SCLK = 0;//先将SCLK置低电平。
    	_nop_();
    	RST = 1; //然后将RST(CE)置高电平。
    	_nop_();
    
    	for (n=0; n<8; n++)//开始传送八位地址命令
    	{
    		DSIO = addr & 0x01;//数据从低位开始传送
    		addr >>= 1;
    		SCLK = 1;//数据在上升沿时,DS1302读取数据
    		_nop_();
    		SCLK = 0;
    		_nop_();
    	}
    	for (n=0; n<8; n++)//写入8位数据
    	{
    		DSIO = dat & 0x01;
    		dat >>= 1;
    		SCLK = 1;//数据在上升沿时,DS1302读取数据
    		_nop_();
    		SCLK = 0;
    		_nop_();	
    	}	
    		 
    	RST = 0;//传送数据结束
    	_nop_();
    }
    
    /*******************************************************************************
    * 函 数 名         : Ds1302Read
    * 函数功能		   : 读取一个地址的数据
    * 输    入         : addr
    * 输    出         : dat
    *******************************************************************************/
    
    uchar Ds1302Read(uchar addr)
    {
    	uchar n,dat,dat1;
    	RST = 0;
    	_nop_();
    
    	SCLK = 0;//先将SCLK置低电平。
    	_nop_();
    	RST = 1;//然后将RST(CE)置高电平。
    	_nop_();
    
    	for(n=0; n<8; n++)//开始传送八位地址命令
    	{
    		DSIO = addr & 0x01;//数据从低位开始传送
    		addr >>= 1;
    		SCLK = 1;//数据在上升沿时,DS1302读取数据
    		_nop_();
    		SCLK = 0;//DS1302下降沿时,放置数据
    		_nop_();
    	}
    	_nop_();
    	for(n=0; n<8; n++)//读取8位数据
    	{
    		dat1 = DSIO;//从最低位开始接收
    		dat = (dat>>1) | (dat1<<7);
    		SCLK = 1;
    		_nop_();
    		SCLK = 0;//DS1302下降沿时,放置数据
    		_nop_();
    	}
    
    	RST = 0;
    	_nop_();	//以下为DS1302复位的稳定时间,必须的。
    	SCLK = 1;
    	_nop_();
    	DSIO = 0;
    	_nop_();
    	DSIO = 1;
    	_nop_();
    	return dat;	
    }
    
    /*******************************************************************************
    * 函 数 名         : Ds1302Init
    * 函数功能		   : 初始化DS1302.
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    
    void Ds1302Init()
    {
    	uchar n;
    	Ds1302Write(0x8E,0X00);		 //禁止写保护,就是关闭写保护功能
    	for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
    	{
    		Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);	
    	}
    	Ds1302Write(0x8E,0x80);		 //打开写保护功能
    }
    
    /*******************************************************************************
    * 函 数 名         : Ds1302ReadTime
    * 函数功能		   : 读取时钟信息
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    
    void Ds1302ReadTime()
    {
    	uchar n;
    	for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
    	{
    		TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
    	}
    		
    }
    
    
    
    • 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

    main.c

    /*************************************************************************************
    
    *
    实验现象:下载程序后,数码管显示时钟
    		  
    接线说明: (具体接线图可见开发攻略对应实验的“实验现象”章节)
    		   1,单片机-->DS1302时钟模块
    		   		P34-->DIO
    				P35-->CE
    				P36-->CLK
    		   2,单片机-->动态数码管模块
    		   		J22-->J6
    				P22-->J9(A)
    				P23-->J9(B)
    				P24-->J9(C)	
    	
    注意事项:										
    
    										  
    **************************************************************************************
    
    */
    
    #include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
    #include "ds1302.h"	
    
    typedef unsigned int u16;	  //对数据类型进行声明定义
    typedef unsigned char u8;
    
    sbit LSA=P2^2;
    sbit LSB=P2^3;
    sbit LSC=P2^4;
    
    
    char num=0;
    u8 DisplayData[8];
    u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
    
    /*******************************************************************************
    * 函 数 名         : delay
    * 函数功能		   : 延时函数,i=1时,大约延时10us
    *******************************************************************************/
    void delay(u16 i)
    {
    	while(i--);	
    }
    
    
    /*******************************************************************************
    * 函 数 名         : datapros()
    * 函数功能		   : 时间读取处理转换函数
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    
    void datapros() 	 
    {
       	Ds1302ReadTime();
    	DisplayData[0] = smgduan[TIME[2]/16];				//时
    	DisplayData[1] = smgduan[TIME[2]&0x0f];				 
    	DisplayData[2] = 0x40;
    	DisplayData[3] = smgduan[TIME[1]/16];				//分
    	DisplayData[4] = smgduan[TIME[1]&0x0f];	
    	DisplayData[5] = 0x40;
    	DisplayData[6] = smgduan[TIME[0]/16];				//秒
    	DisplayData[7] = smgduan[TIME[0]&0x0f];
    }
    
    
    /*******************************************************************************
    * 函数名         :DigDisplay()
    * 函数功能		 :数码管显示函数
    * 输入           : 无
    * 输出         	 : 无
    *******************************************************************************/
    void DigDisplay()
    {
    	u8 i;
    	for(i=0;i<8;i++)
    	{
    		switch(i)	 //位选,选择点亮的数码管,
    		{
    			case(0):
    				LSA=1;LSB=1;LSC=1; break;//显示第0位
    			case(1):
    				LSA=0;LSB=1;LSC=1; break;//显示第1位
    			case(2):
    				LSA=1;LSB=0;LSC=1; break;//显示第2位
    			case(3):
    				LSA=0;LSB=0;LSC=1; break;//显示第3位
    			case(4):
    				LSA=1;LSB=1;LSC=0; break;//显示第4位
    			case(5):
    				LSA=0;LSB=1;LSC=0; break;//显示第5位
    			case(6):
    				LSA=1;LSB=0;LSC=0; break;//显示第6位
    				case(7):
    				LSA=0;LSB=0;LSC=0; break;//显示第7位
    		}
    		P0=DisplayData[i];//发送数据
    		delay(100); //间隔一段时间扫描	
    		P0=0x00;//消隐
    	}		
    }
    
    /*******************************************************************************
    * 函 数 名       : main
    * 函数功能		 : 主函数
    * 输    入       : 无
    * 输    出    	 : 无
    *******************************************************************************/
    void main()
    {	
    	//Ds1302Init();	   //第一次初始化后就可以注释该条语句,这样下次重启就不会再次初始化了
    	while(1)
    	{
    		datapros();	 //数据处理函数
    		DigDisplay();//数码管显示函数		
    	}		
    }
    
    
    • 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
  • 相关阅读:
    C语言高级教程-C语言数组(一)
    java读取OPC DA数据---Utgard
    关于使用Java-JWT的笔记
    【23期】你知道Java面向对象设计的六大原则吗
    十六、代码校验(1)
    Istio网关流量转发
    Nacos集群配置以及在springboot中使用
    YouTrack 中如何设置邮件通知
    学习JavaScript进阶
    linux提权辅助工具linux-smart-enumeration(三种工具)
  • 原文地址:https://blog.csdn.net/qq_44845100/article/details/136251845