【杰理AC63系列驱动时钟芯片DS1302】

杰理AC63系列驱动时钟芯片DS1302

1.DS1302时钟芯片介绍

DS1302可慢速充电实时时钟芯片包含实时时钟/日历和31字节的非易失性静态 RAM。它经过一个简单的串行接口与微处理器通信。实时时钟/日历可对秒,分,时,日,周,月,和年进行计数,对于小于31 天的月,月末的日期自动进行调整,还具有闰年校正的功能。时钟可以采用 24 小时格式或带 AM(上午)/PM(下午)的 12 小时格式。31 字节的 RAM 可以用来临时保存一些重要数据。使用同步串行通信,简化了 DS1302 与微处理器的通信。与时钟/RAM 通信仅需 3 根线:(1)RST(复位),(2)I/O(数据线)和(3)SCLK(串行时钟)。(数据可以以每次一个字节的单字节形式或多达 31 字节的多字节形式传输。DS1302能在非常低的功耗下工作,消耗小于 1µW 的功率便能保存数据和时钟信息。

注意:可能是芯片制造商或者版本的原因,有些芯片手册的RST引脚也叫做CE引脚,其功能都是一样的,不用刻意关注。

芯片读写时序图:
芯片读写时序图
需要注意的是:读时序的时候需要根据情况加一些延时,一般是us级。

芯片相关寄存器概要:
在这里插入图片描述

2.驱动程序开发

头文件DS1302.h:

#ifndef __DS1302_H__
#define __DS1302_H__

#include "app.h"

extern unsigned char DS1302_Time[8];
 
#define DS1302_SCLK IO_PORTA_03
#define DS1302_IO   IO_PORTA_04
#define DS1302_CE   IO_PORTA_05 //CE同RST,其功能一样

void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,unsigned char Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_ReadTime(void);
void DS1302_SetTime(void);
 

#endif

头文件DS1302.c:

#include "DS1302.h"
 
#define DS1302_SECOND  0x80
#define DS1302_MINUTE  0x82
#define DS1302_HOUR    0x84
#define DS1302_DATE    0x86
#define DS1302_MONTH   0x88
#define DS1302_DAY     0x8A
#define DS1302_YEAR    0x8C
#define DS1302_WP      0x8E
 
//初始化时间存放在该数组,左到右依次为年月日时分秒周 -- 2024.5.17 15:10:30 星期五
unsigned char DS1302_Time[8] = {20, 24, 05, 17, 15, 10, 30, 05};

//阻塞延时
void block_delay(uint16_t count){
  for(uint16_t i = 0;i < count;i++){
    asm volatile("nop");
  }
}
/**
  * @brief 初始化DS1302
  * @param 无
  * @retval 无
  */
void DS1302_Init(void)
{
    //引脚初始化--输出
    gpio_port_init(DS1302_SCLK, 0 ,1);
    gpio_port_init(DS1302_IO, 0 ,1);
    gpio_port_init(DS1302_CE, 0 ,1);

    gpio_write(DS1302_SCLK, 0);
    gpio_write(DS1302_CE, 0);
}
 
/**
  * @brief 写入
  * @param Command 地址/命令字节  Data 数据
  * @retval 无
  */
void DS1302_WriteByte(unsigned char Command, unsigned char Data)
{
	unsigned char i;
  uint16_t cnt = 100;
  //IO--输出
  gpio_port_init(DS1302_IO, 0 ,1);
  gpio_write(DS1302_CE, 0);

  gpio_write(DS1302_SCLK, 0);
	gpio_write(DS1302_CE, 1);

	for(i=0; i<8; i++)
	{
    if(Command & 0x01)
			gpio_write(DS1302_IO, 1);
		else
			gpio_write(DS1302_IO, 0); 
		Command >>=1;

    gpio_write(DS1302_SCLK, 0);
    gpio_write(DS1302_SCLK, 1);
	}
	for(i=0; i<8; i++)
	{
    if(Data & 0x01)
			gpio_write(DS1302_IO, 1);
		else
			gpio_write(DS1302_IO, 0); 
		Data >>=1;

    gpio_write(DS1302_SCLK, 0);
    gpio_write(DS1302_SCLK, 1);
	}
  gpio_write(DS1302_SCLK, 1);
  gpio_write(DS1302_CE, 0);
}	
 
/**
  * @brief 读出
  * @param Command 地址/命令字节
  * @retval 读出的数据
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i, Data = 0x00;

  gpio_write(DS1302_CE, 0);
  gpio_write(DS1302_SCLK, 0);
	gpio_write(DS1302_CE, 1);

  //IO--输出
  gpio_port_init(DS1302_IO, 0 ,1);

	Command |= 0x01;
	for(i=0; i<8; i++)
	{

        if(Command & 0x01)
          gpio_write(DS1302_IO, 1);
        else
          gpio_write(DS1302_IO, 0);
        Command>>=1;

        gpio_write(DS1302_SCLK, 0);
        gpio_write(DS1302_SCLK, 1);
	}
  //IO--输入
  gpio_port_init(DS1302_IO, 1 ,1);

	for(i=0; i<8;i++)
	{
        gpio_write(DS1302_SCLK, 1);
        gpio_write(DS1302_SCLK, 0);
        //阻塞延时
        block_delay(1);
        if(gpio_read(DS1302_IO)){Data = Data | (0x01<<i);}	
	}
  gpio_write(DS1302_SCLK, 1);
  gpio_write(DS1302_CE, 0);
  gpio_port_init(DS1302_IO, 0 ,1);
  gpio_write(DS1302_IO, 0);
    // //系统退出临界保护区
    // OS_EXIT_CRITICAL();
	return Data;
}
 
/**
  * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
  * @param  无
  * @retval 无
  */
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[1]/10*16+DS1302_Time[1]%10);//十进制转BCD码后写入
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_DAY,DS1302_Time[7]/10*16+DS1302_Time[7]%10);
	DS1302_WriteByte(DS1302_WP,0x80);
}
 
/**
  * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
  * @param  无
  * @retval 无
  */
void DS1302_ReadTime(void)
{
	unsigned char Temp = 0;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[1]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND);//屏蔽秒的第7位,避免超出59
	DS1302_Time[6]=Temp/16*10+Temp%16;//&0x7f
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[7]=Temp/16*10+Temp%16;
}

3.实验结果

经测试,上述驱动代码可正常驱动DS1302模块,若有疑问,欢迎留言咨询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值