把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); }