蓝桥杯突击6-DS1302时钟芯片

本次学习DS1302时钟芯片.

       DS1302芯片采用SPI 3线通信, 分别是SCLK, I/O,CE三根线.

                                   

由于比赛时给出DS1302的SPI协议的文件, 所以这次重点介绍其寄存器.

 

DS1302有一个控制寄存器,12个日历.时钟寄存器和31个RAM.可读写.

     控制寄存器:

 

如果R/W为0为则是写模式, 如果R/W为1则是读模式.

       日历.时钟寄存器:

                           

                           

(1). 数据在寄存器中以BCD码形式存在

(2). 小时寄存器的D7为12小时制和24小时制的选择位,为1时是12小时制,为0时是24小时制; D5的1是上午,0是下午; 当24小时制时,D5,D4为小时的十位

(3). 秒寄存器中的CH位是时钟暂停位,当为1时钟暂停, 为0时钟开始

(4). 写保护寄存器中的WP为写保护位,当WP=1,写保护,当WP=0未写保护,当对日历、时钟寄存器或片内RAM进行写时WP应清零,当对日历、时钟寄存器或片内RAM进行读时WP一般置1。

(5). 慢充电寄存器的TCS位为控制慢充电的选择,当它为1010才能使慢充电工作。DS为二极管选择位。DS为01选择一个二极管,DS为10选择二个二极管,DS为11或00充电器被禁止,与TCS无关。RS用于选择连接在VCC2与VCC1之间的电阻,RS为00,充电器被禁止,与TCS无关,电阻选择情况见表.

                                                      

片内RAM不介绍.

 

下面介绍程序流程:

    首先我们利用竞赛时给的ds1302.c,进行DS1302的初始化,也就是关闭写保护寄存器, 并在日历寄存器里面写入命令和初始化时间.然后开启写保护, 最后再读取日历寄存器中的时间,并再数码管上显示:

贴上代码ds1302.c:

#include "ds1302.h"

uchar Write_Ds1302_addr[]={0x80,0x82,0x84}; //秒分时
uchar Read_Ds1302_addr[]={0x81,0x83,0x85}; //秒分时
uchar TIME[7] = {0, 0x12, 0x12};           //秒分时
/********************************************************************/ 
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	for (i=0;i<8;i++) 
	{ 
		if (dat & 0x01) 	// 等价于if((addr & 0x01) ==1) 
		{
			SDA_SET;		//#define SDA_SET SDA=1 /*电平置高*/
		}
		else 
		{
			SDA_CLR;		//#define SDA_CLR SDA=0 /*电平置低*/
		}		 
		SCK_SET;
		SCK_CLR;		
		dat = dat >> 1; 
	} 
}
/********************************************************************/ 
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void) 
{
	unsigned char i, dat=0;	
	for (i=0;i<8;i++)
	{	
		dat = dat >> 1;
		if (SDA_R) 	  //等价于if(SDA_R==1)    #define SDA_R SDA /*电平读取*/	
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK_SET;
		SCK_CLR;
	}	             
	SDA_CLR;              //以下为DS1302复位的稳定时间,必须的。
	return dat;
}

/********************************************************************/ 
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;			/*启动DS1302总线,RST=1电平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
	Write_Ds1302_Byte(dat);	 /*写入数据:dat*/
	RST_CLR;				 /*停止DS1302总线*/
}

/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;	/*启动DS1302总线,RST=1电平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
	temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
	RST_CLR;	/*停止DS1302总线*/
	return temp;
}

void DS1302Init()
{
	uchar i;
	Ds1302_Single_Byte_Write(0x8e,0x00);       //0x00关闭写保护
	for (i=0;i<3;i++)
	{
		Ds1302_Single_Byte_Write(Write_Ds1302_addr[i],TIME[i]);
	}
	Ds1302_Single_Byte_Write(0x8e,0x80);      //0x80写保护
}

void DS1302ReadTime()
{
	uchar i;
	for (i=0;i<3;i++)
	{
		TIME[i]=Ds1302_Single_Byte_Read(Read_Ds1302_addr[i]);
	}
}

 

ds1302.h:


#ifndef  __DS1302_H__
#define  __DS1302_H__

#include<reg52.h>
#include<intrins.h>
/********************************************************************/ 
sbit SCK=P1^7;		
sbit SD=P2^3;		
sbit RST=P1^3;
typedef unsigned char uchar;
typedef unsigned int uint;
/********************************************************************/ 
/*复位脚*/
#define RST_CLR	RST=0	/*电平置低*/
#define RST_SET	RST=1	/*电平置高*/
/*双向数据*/
#define SDA_CLR	SD=0	/*电平置低*/
#define SDA_SET	SD=1	/*电平置高*/
#define SDA_R	SD	/*电平读取*/	
/*时钟信号*/
#define SCK_CLR	SCK=0	/*时钟信号*/
#define SCK_SET	SCK=1	/*电平置高*/
/********************************************************************/ 
#define ds1302_sec_addr			0x80		//秒数据地址
#define ds1302_min_addr			0x82		//分数据地址
#define ds1302_hr_addr			0x84		//时数据地址
#define ds1302_date_addr		0x86		//日数据地址
#define ds1302_month_addr		0x88		//月数据地址
#define ds1302_day_addr			0x8A		//星期数据地址
#define ds1302_year_addr		0x8C		//年数据地址

#define ds1302_control_addr		0x8Ee		//写保护命令字单元地址
#define ds1302_charger_addr		0x90 		//涓电流充电命令字地址			 
#define ds1302_clkburst_addr	0xBE		//日历、时钟突发模式命令字地址
/********************************************************************/ 

/********************************************************************/ 
/*单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/ 
/*单字节读出一字节数据*/
extern unsigned char Read_Ds1302_Byte(void);
  
/********************************************************************/ 
/********************************************************************/ 
/*向DS1302单字节写入一字节数据*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);

extern uchar TIME[7];
void DS1302ReadTime();
void DS1302Init();

#endif	 
/********************************************************************/
//		     	END FILE
/********************************************************************/

 

下面是main.c:

#include <reg52.h>
#include "ds1302.h"

sbit BUZZ=P0^6;
sbit RELAY=P0^4;

uchar discom;
uchar DisplayData[8];
uchar code table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

void Display();
void TimePros();
void CloseBUZZ();
void CloseLED();

void main()
{
	DS1302Init();
	CloseBUZZ();
	CloseLED();
	while (1)
	{
		TimePros();
		Display();
	}
}

void CloseBUZZ()
{
	BUZZ=0;
	RELAY=0;
	P2=(P2&0x1f)|0xa0;
	P2&=0x1f;
}

void CloseLED()
{
	P0=0xff;
	P2=(P2&0x1f)|0x80;
	P2&=0x1f;
}

void TimePros()
{
	DS1302ReadTime();
	DisplayData[0] = table[TIME[2]/16];				//时
	DisplayData[1] = table[TIME[2]&0x0f];				 
	DisplayData[2] = 0xbf;						 
	DisplayData[3] = table[TIME[1]/16];				//分
	DisplayData[4] = table[TIME[1]&0x0f];	
	DisplayData[5] = 0xbf;
	DisplayData[6] = table[TIME[0]/16];				//秒
	DisplayData[7] = table[TIME[0]&0x0f];
}

void Display()
{
	P0=0xff;
	P2=(P2&0x1f)|0xe0;
	P2&=0x1f;
	
	P0=(1<<discom);
	P2=(P2&0x1f)|0xc0;
	P2&=0x1f;
	
	P0=DisplayData[discom];
	P2=(P2&0x1f)|0xe0;
	P2&=0x1f;
	
	discom++;
	if (discom==8)
		discom=0;
}

实现的效果为:在数码管上从 12:12:00开始显示时间.

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值