最近想看下DS1302内部RAM掉电后的状态,会是默认的全0x00么?
首先查阅网上的资料和芯片相关手册,并没有对它的介绍,DS1302是块很普通的时钟芯片,之前用别的单片机也操作过,但从来没有留意这点。决定操作下1302,看下RAM究竟是什么状态。
手头别的什么单片机都没有,就有块上次代理商留下的stm8L15X系列单片机demo板。那就用这块单片机试下吧。
首先配置系统时钟,在stm8的库文件(STM8S_StdPeriph_Lib_V2.1.0)里有相关的函数获取相关时钟状态,如下:
SysClkFreq = CLK_GetClockFreq();
SysClkSource = CLK_GetSYSCLKSource();
从返回值可以看出,芯片默认时钟为内部HSI,2MHz。
重新设置成16M,内部时钟:
/*set system clock*/
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
之后是DS1302的相关函数,DS1302.h文件如下:
#ifndef DS1302_H
#define DS1302_H
//DS1302相关PIN
#define DS1302_PORT GPIOC
#define DS1302_PORT_RST GPIOE
#define DS1302_RST_PIN GPIO_Pin_7
#define DS1302_IO_PIN GPIO_Pin_0
#define DS1302_CLK_PIN GPIO_Pin_7
#define DS1302_SEC_REG 0x80
#define DS1302_MIN_REG 0x82
#define DS1302_HR_REG 0x84
#define DS1302_DATE_REG 0x86
#define DS1302_MONTH_REG 0x88
#define DS1302_DAY_REG 0x8a
#define DS1302_YEAR_REG 0x8c
#define DS1302_CONTROL_REG 0x8e
#define DS1302_CHARGER_REG 0x90
#define DS1302_CLKBURST_REG 0xbe
#define DS1302_RAM_REG 0xc0
typedef struct _DS1302_TIME
{
unsigned char year;
unsigned char month;
unsigned char day;
unsigned char week;
unsigned char hour;
unsigned char minute;
unsigned char second;
}DS1302_TIME;
extern void ds1302_port_init(void);
extern unsigned char ds1302_check(void);
extern void ds1302_write_time(DS1302_TIME* time);
extern void ds1302_read_time(DS1302_TIME* time);
extern void ds1302_write_ram(unsigned char ram_num,unsigned char dat);
extern unsigned char ds1302_read_ram(unsigned char ram_num);
#endif
DS1302.c文件:
#include "stm8l15x.h"
#include "stm8l_discovery_lcd.h"
#include "discover_board.h"
#include "icc_measure.h"
#include "discover_functions.h"
#include "ds1302.h"
void delay()
{
int i;
for(i=0;i<10;i++)
;
}
void ds1302_port_init(void)
{
GPIO_Init(DS1302_PORT,DS1302_CLK_PIN, GPIO_Mode_Out_PP_High_Fast);//RTC_CLK
GPIO_Init(DS1302_PORT_RST,DS1302_RST_PIN, GPIO_Mode_Out_PP_High_Fast);//
GPIO_Init(DS1302_PORT,DS1302_IO_PIN, GPIO_Mode_In_FL_No_IT); //RTC_DATA
GPIO_LOW(DS1302_PORT_RST,DS1302_RST_PIN);
GPIO_LOW(DS1302_PORT,DS1302_CLK_PIN);
}
void read_IO(void){
GPIO_Init(DS1302_PORT,DS1302_IO_PIN, GPIO_Mode_In_FL_No_IT); //RTC_DATA
}
void write_IO(void){
GPIO_Init(DS1302_PORT,DS1302_IO_PIN, GPIO_Mode_Out_OD_HiZ_Fast);//RTC_DATA
}
void ds1302_write_byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
// delay_10us(5);
GPIO_LOW(DS1302_PORT,DS1302_CLK_PIN);
if(temp&0x01) {
GPIO_HIGH(DS1302_PORT,DS1302_IO_PIN);
}else {
GPIO_LOW(DS1302_PORT,DS1302_IO_PIN);
}
temp>>=1;
// delay_10us(10);
GPIO_HIGH(DS1302_PORT,DS1302_CLK_PIN);
}
}
unsigned char ds1302_read_byte(void)
{
unsigned char i,temp=0;
for (i=0;i<8;i++)
{
GPIO_LOW(DS1302_PORT,DS1302_CLK_PIN);
temp>>=1;
if(GPIO_ReadInputDataBit(DS1302_PORT,DS1302_IO_PIN))
{
temp|=0x80;
}
// delay_10us(5);
GPIO_HIGH(DS1302_PORT,DS1302_CLK_PIN);
}
return temp;
}
void ds1302_write( unsigned char address,unsigned char dat )
{
write_IO();
GPIO_LOW(DS1302_PORT_RST,DS1302_RST_PIN); //写地址,写数据 RST保持高电平
GPIO_LOW(DS1302_PORT,DS1302_CLK_PIN);
GPIO_HIGH(DS1302_PORT_RST,DS1302_RST_PIN);
//delay_10us(1);
ds1302_write_byte(address);
ds1302_write_byte(dat);
//delay_10us(1);
GPIO_LOW(DS1302_PORT_RST,DS1302_RST_PIN);
}
/****************************************************************************/
unsigned char ds1302_read( unsigned char address )
{
unsigned char ret;
write_IO();
GPIO_LOW(DS1302_PORT_RST,DS1302_RST_PIN);
GPIO_LOW(DS1302_PORT,DS1302_CLK_PIN);
GPIO_HIGH(DS1302_PORT_RST,DS1302_RST_PIN);
// delay_10us(1);
ds1302_write_byte(address|0x01); //读标志:地址最后一位为1
read_IO();
ret = ds1302_read_byte();
//delay_10us(1);
GPIO_LOW(DS1302_PORT_RST,DS1302_RST_PIN);
return (ret);
}
unsigned char ds1302_check(void)
{
unsigned char ret;
ds1302_write(DS1302_CONTROL_REG,0x80);
ret = ds1302_read(DS1302_CONTROL_REG);
if(ret==0x80)
return 1;
return 0;
}
void ds1302_read_time(DS1302_TIME* time)
{
time->year=ds1302_read(DS1302_YEAR_REG); //年
time->month=ds1302_read(DS1302_MONTH_REG);//月
time->day=ds1302_read(DS1302_DATE_REG); //日
time->week=ds1302_read(DS1302_DAY_REG); //周
time->hour=ds1302_read(DS1302_HR_REG); //时
time->minute=ds1302_read(DS1302_MIN_REG); //分
time->second=ds1302_read(DS1302_SEC_REG); //秒
}
void ds1302_write_time(DS1302_TIME* time)
{
ds1302_write(DS1302_CONTROL_REG,0x00); //关闭写保护
ds1302_write(DS1302_SEC_REG,0x80); //暂停
ds1302_write(DS1302_CHARGER_REG,0xa9); //涓流充电
//ds1302_write(DS1302_SECOND_ADDR, 0x00); // 启动振荡器
// ds1302_write(DS1302_YEAR_REG,time->year); //年
// ds1302_write(DS1302_MONTH_REG,time->month); //月
// ds1302_write(DS1302_DATE_REG,time->day); //日
// ds1302_write(DS1302_DAY_REG,time->week); //周
ds1302_write(DS1302_HR_REG,time->hour); //时
ds1302_write(DS1302_MIN_REG,time->minute); //分
ds1302_write(DS1302_SEC_REG,0x00); //秒
ds1302_write(DS1302_CONTROL_REG,0x80); //打开写保护
}
void ds1302_write_ram(unsigned char ram_num,unsigned char dat)
{
ds1302_write(DS1302_CONTROL_REG,0x00); //关闭写保护
ds1302_write((DS1302_RAM_REG|(ram_num<<2)),dat);
ds1302_write(DS1302_CONTROL_REG,0x80);
}
unsigned char ds1302_read_ram(unsigned char ram_num)
{
unsigned char ret;
ret = ds1302_read((DS1302_RAM_REG|(ram_num<<2)));
return ret;
}
注意:芯片手册上说读数据是在写完地址后紧接着的第一个下降沿开始读取。实际是在第一个上升沿读取。
从调试过程上来看,对于相关的时间寄存器和31字节的RAM空间,写过数值之后,断电重启,相关寄存器的数值不确定。
但是CONTROL(0x8e)寄存器的值没有变化,还是最后写入的0x80.
版权声明:本文为L_Backkom原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。