把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_WRITE0x80
#define MINUTE_REG_WRITE0x82
#define HOUR_REG_WRITE0x84
#define DAY_REG_WRITE0x86
#define MONTH_REG_WRITE0x88
#define WEEK_REG_WRITE0x8A
#define YEAR_REG_WRITE0x8C
// 各寄存器的读命令
#define SECOND_REG_READ0x81
#define MINUTE_REG_READ0x83
#define HOUR_REG_READ0x85
#define DAY_REG_READ0x87
#define MONTH_REG_READ0x89
#define WEEK_REG_READ0x8B
#define YEAR_REG_READ0x8D
// 三根线进行通讯,控制
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);
}