STC单片机学习------DS1302时钟芯片

时间:2021-02-21 16:32:59

        把DS1302调试出来了,写个记录吧,下次用着时候省得再重新满大街的找资料。 芯片介绍就不写了,度娘一搜一大把,写几点笔记:

1、向寄存器写入数据前,要先关闭写保护,即向 0x8E 写入 0x00,开启写保护时候写入0x80;

2、DS1302 第5脚 RST脚,类似于一般芯片的CS脚,读写寄存器时候要将其拉高。一般的片子都是拉低,这里跟其他不一样;

3、接收或发送数据时候,低位在前,高位在后。感觉有点别扭;

4、设置时间,或读取时间时候,是BCD码,不是十六进制。比如,11时56分,读出时候就是0x11时,0x56分。



/* Includes ------------------------------------------------------------------*/
#include "STC_NEW_8051.h"
#include <stdio.h>
#include "mySTC.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

// 各寄存器的写命令。KEIL对中文支持不太好,原文注释这里原样表述一遍
#define SECOND_REG_WRITE	0x80
#define MINUTE_REG_WRITE	0x82
#define HOUR_REG_WRITE		0x84
#define DAY_REG_WRITE		0x86
#define MONTH_REG_WRITE		0x88
#define WEEK_REG_WRITE		0x8A
#define YEAR_REG_WRITE		0x8C

// 各寄存器的读命令
#define SECOND_REG_READ		0x81
#define MINUTE_REG_READ		0x83
#define HOUR_REG_READ		0x85
#define DAY_REG_READ		0x87
#define MONTH_REG_READ		0x89
#define WEEK_REG_READ		0x8B
#define YEAR_REG_READ		0x8D

// 三根线进行通讯,控制
sbit DS1302_SCK  = P1^0;
sbit DS1302_IO   = P1^1;
sbit DS1302_RST  = P2^0;

// 向DS1302写入一个字节
void DS1302_WriteByte(u8 writeByte)
{
	u8 retry = 0;
	// DS1302 接收或发送数据时,低位在前,高位在后
	for(retry=0; retry!=8; ++retry){
		if(1 == (writeByte & 0x01)){
			DS1302_IO = 1;
		}else{
			DS1302_IO = 0;
		}
		// 参考了别人的例程,这里竟然不需要延时..好吧
		DS1302_SCK = 1;
		DS1302_SCK = 0;
		writeByte >>= 1;
	}
}

// 从DS1302中读出一个字节
u8 DS1302_ReadByte(void)
{
	u8 retry = 0;
	u8 readByte = 0;
	// 最低位在前,高位在后。跟一般的通讯不太一样
	for(retry=0; retry!=8; ++retry){
		readByte >>= 1;
		if(DS1302_IO){
			readByte |= 0x80;
		}		
		DS1302_SCK = 1;		
		DS1302_SCK = 0;			
	}	
	return readByte;
}

// 向某个寄存器写入一个字节数值
void DS1302_WriteReg(u8 addr, u8 value)
{
	DS1302_RST = 0;
	DS1302_SCK = 0;
	DS1302_RST = 1;
	DS1302_WriteByte(addr);
	DS1302_WriteByte(value);
	DS1302_SCK = 1;
	DS1302_RST = 0;
}

// 读取某个寄存器的值
u8 DS1302_ReadReg(u8 addr)
{
	u8 readByte = 0;
	DS1302_RST = 0;
	DS1302_SCK = 0;
	DS1302_RST = 1;
	DS1302_WriteByte(addr);
	readByte = DS1302_ReadByte();
	DS1302_SCK = 1;
	DS1302_RST = 0;
	
	return readByte;
}

// DS1302的初始化
void DS1302_Init(void)
{
	// 先关闭写保护
	DS1302_WriteReg(0x8E, 0x00);
	// 设置时间,秒、分、时等等,注意噢,写入的是BCD码
	DS1302_WriteReg(SECOND_REG_WRITE, 0);	
	DS1302_WriteReg(MINUTE_REG_WRITE, 0x20);
	DS1302_WriteReg(HOUR_REG_WRITE, 0x17);
	DS1302_WriteReg(DAY_REG_WRITE, 0x52);
	DS1302_WriteReg(MONTH_REG_WRITE, 0x12);
	DS1302_WriteReg(YEAR_REG_WRITE, 0x13);
	DS1302_WriteReg(WEEK_REG_WRITE, 0x04);
	
	// 一些设置后,继续开户写保护
	DS1302_WriteReg(0x90, 0x01);
	DS1302_WriteReg(0xC0, 0xF0);
	DS1302_WriteReg(0x8E, 0x80);
}

// 读时间,然后在八段数码管上显示出来
void DS1302_Test(void)
{
	u8 hour, min, sec;
	
	hour = DS1302_ReadReg(HOUR_REG_READ);
        // BCD码转换成十六进制
	hour = (hour/16)*10 + (hour%16);
	
	min = DS1302_ReadReg(MINUTE_REG_READ);	
	min = (min/16)*10 + (min%16);
	
	sec = DS1302_ReadReg(SECOND_REG_READ);	
	sec = (sec/16)*10 + (sec%16);
	
	LedSegmentDisplay(7, hour/10);
	DelayTime(2);
	LedSegmentDisplay(6, hour%10);
	DelayTime(2);
	
        // 显示个横线,下同
	LedSegmentDisplayRaw(5, 0x40);
	DelayTime(2);
		
	LedSegmentDisplay(4, min/10);
	DelayTime(2);
	LedSegmentDisplay(3, min%10);
	DelayTime(2);
	
	LedSegmentDisplayRaw(2, 0x40);
	DelayTime(2);
		
	LedSegmentDisplay(1, sec/10);
	DelayTime(2);
	LedSegmentDisplay(0, sec%10);
	DelayTime(1);
}