DS1302教程及proteus仿真(51和stm32)

DS1302是一款时钟芯片,能精确对年月日时分秒进行计算,并且能自动校准闰年和每个月的不同天数,下面从51和stm32两款单片机介绍其用法

DS1302采用三线SPI通信 ,下图详细说明了各引脚的接线方式

 DS1302使用的并不是标准的SPI通信,它的数据输入输出为同一根线。通信时序图如下图所示

空闲状态时SCK为低电平,时钟信号的第一个沿开始传输数据,低位在前高位在后,每次通信前都需要将CE引脚拉高。值得注意的是DS1302输出的数据为BCD码,比如串行通信输出的16进制数据0x21,按照正常其转换为十进制为33,但DS1302输出的0x21就代表十进制数21。其他没有什么需要特别注意的。

下面是代码和proteus仿真部分

先是51的,使用STC89C52RC单片机

DS1302驱动函数的头文件

#ifndef _DS1302_H_
#define _DS1302_H_
#include <reg52.h>
sbit CE=P1^0;
sbit SCK=P1^1;
sbit IO=P1^2;
void DS1302_Init();
void DS1302_Write_Reg(unsigned char Reg,unsigned char Dat);
unsigned char DS1302_Read_Reg(unsigned char Reg);
void SPI_Write(unsigned char Dat);
unsigned char SPI_Read();
#endif

DS1302的驱动函数

#include "ds1302.h"
void DS1302_Init()
{
  CE=0;
	SCK=0;
}
void DS1302_Write_Reg(unsigned char Reg,unsigned char Dat)
{
  CE=1;
	SPI_Write(Reg);
	SPI_Write(Dat);
	CE=0;
}
unsigned char DS1302_Read_Reg(unsigned char Reg)
{
	unsigned char Dat;
	CE=1;
  SPI_Write(Reg);
	Dat=SPI_Read();
	CE=0;
	return Dat;
}
void SPI_Write(unsigned char Dat)
{
	unsigned char i=0;
	for(i=0;i<8;i++)
	{
	if(Dat&0x01)
	{
	IO=1;
	}
	else
	{
	IO=0;
	}
	SCK=1;
	SCK=0;
	Dat>>=1;
	}
	IO=1;
}
unsigned char SPI_Read()
{
  unsigned char i=0,Dat=0;
	for(i=0;i<8;i++)
	{
	Dat>>=1;
	SCK=1;
	if(IO)
	{
	Dat|=0x80;
	}
	SCK=0;
	}
	return Dat;
}

 主函数部分

首先进行DS1302的初始化,将时分秒部分清0,年月日暂且不管,然后进入主循环,不断的对时间进行读取,这里并没有执行BCD码的转换

#include "ds1302.h"
void main()
{
	unsigned char h,m,s;
	DS1302_Init();
	DS1302_Write_Reg(0x8e,0x80);
	DS1302_Write_Reg(0x80,0x00);
	DS1302_Write_Reg(0x82,0x00);
	DS1302_Write_Reg(0x84,0x00);
	while(1)
	{
	  h=DS1302_Read_Reg(0x85);
	  m=DS1302_Read_Reg(0x83);
		s=DS1302_Read_Reg(0x81);
	}
}

下面是proteus仿真电路图,DS1302的晶振不接也是可以正常运行的

接下来是stm32部分,使用stm32f103c8t6单片机 

DS1302驱动函数的头文件

#ifndef _DS1302_H_
#define _DS1302_H_
void DS1302_Init(void);
void SPI_Write(unsigned char Dat);
unsigned char SPI_Read(void);
void DS1302_Write_Reg(unsigned char Reg,unsigned char Dat);
unsigned char DS1302_Read_Reg(unsigned char Reg);

#endif

DS1302驱动函数

#include "stm32f10x_rcc.h"
//CE PA0
//SCK PA1
//IO PA2
void DS1302_Init(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef DS1302={0};
	DS1302.GPIO_Mode=GPIO_Mode_Out_OD;
	DS1302.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;
	DS1302.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&DS1302);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
void SPI_Write(unsigned char Dat)
{
  unsigned char i=0;
	for(i=0;i<8;i++)
	{
	if(Dat&0x01)
	{
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
	}
	else
	{
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	}
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	Dat>>=1;
	}
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
unsigned char SPI_Read(void)
{
  unsigned char i=0,Dat=0;
	for(i=0;i<8;i++)
	{
		Dat>>=1;
	  GPIO_SetBits(GPIOA,GPIO_Pin_1);
    if(GPIOA->IDR&1<<2)
		{
		Dat|=0x80;
		}
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	}
	return Dat;
}
void DS1302_Write_Reg(unsigned char Reg,unsigned char Dat)
{
  GPIO_SetBits(GPIOA,GPIO_Pin_0);
	SPI_Write(Reg);
	SPI_Write(Dat);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
unsigned char DS1302_Read_Reg(unsigned char Reg)
{
	unsigned char Dat=0;
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	SPI_Write(Reg);
	Dat=SPI_Read();
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
  return Dat;
}

主函数

#include "ds1302.h"
#include "stm32f10x.h"
int main()
{
  DS1302_Init();
	DS1302_Write_Reg(0x8e,0x80);
	DS1302_Write_Reg(0x80,0x00);
	DS1302_Write_Reg(0x82,0x00);
	DS1302_Write_Reg(0x84,0x00);
	while(1)
	{
	  DS1302_Read_Reg(0x85);
	  DS1302_Read_Reg(0x83);
		DS1302_Read_Reg(0x81);
	}
}

下面是proteus仿真,管于这个proteus仿真,我要说点什么

就是关于这个开漏输出的上拉电阻,之前用oled12864的时候,I2C通信我选用开漏输出,没有加上拉电阻,它可以正常显示,再加上stm32本身就比较强悍,使得我对它内部带有上拉电阻深信不疑。本想着花两三个小时在51上把这款芯片研究通,再把他映射到stm32上将会非常简单,万万没想到,对着程序研究了一下午,就在最后快要放弃的时候,我尝试性地在通讯线上加了三颗上拉电阻,没想到竟然成功了。。。。

 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值