【2020-10-28】DS12C887+驱动

STM32F103ZET6对DS12C887+时间模块的驱动

对于项目的一个小模块部分,如果因为驱动程序的问题而半天不能正常操作,这样的事还是挺令人抓狂的,在此整理出DS12C887+时间模块的驱动程序,属于大家的参考,也属于自己的积累。
DS12C887+的基本功能大家应该都了解,不太了解的可以百度下,这里就根据手册附上一些特别有用的内容哈!
芯片引脚图入图片描述
在EDIP封装的引脚图上有6个悬空引脚,在实际的芯片上这些引脚也都是没有的。
芯片实物图
首先是头文件:

#ifndef __DS12C887_H
#define __DS12C887_H
#include "sys.h"
/************************************
AD0-AD7——>PF0-PF7
IRQ——>PE0 中断中断请求输出,低电平有效
CS——>PE1
AS——>PE2
RW——>PE3
DS——>PE4

SQW  方波输出

MOT  总线时序选择,接地,1:Motorola模式,0:Intel模式。
RST  复位脚,接VCC
************************************/
#define DS12C887_CS PEout(1)  //片选
#define DS12C887_AS PEout(2)  //上升沿锁存,下降沿清除
#define DS12C887_RW PEout(3)  //1读,0写
#define DS12C887_DS PEout(4)  //读允许位

//PF0~7作为数据线
#define DS12C887_DATAOUT(x) GPIO_Write(GPIOF,x);//数据输出
#define DS12C887_DATAIN GPIO_ReadInputData(GPIOF)&0x00ff;//数据输入

//IO方向设置
#define DS12C887_DATE_IN()  {GPIOF->CRL&=0xf00000000;GPIOF->CRL|=0x88888888;GPIOF->ODR|=0xff;} //上拉输入
#define DS12C887_DATE_OUT() {GPIOF->CRL&=0xf00000000;GPIOF->CRL|=0x33333333;} //推挽输出

void Write_DS12C887(u8 add,u8 date);//写数据
u8 Read_DS12C887(u8 add);           //读数据
void Read_DS12C887Date(u8 *temp0);  //读时间
void DS12C887_Init(void);           //初始化

#endif

除了VCC和GND接到电源外,通常MOT接地选用Motorola操作模式,RST复位脚接VCC。
接下来是源代码:

#include "ds12c887.h"
#include "delay.h"
void Write_DS12C887(u8 add,u8 date)
{
	DS12C887_CS=0;
	DS12C887_AS=1;
	DS12C887_DS=1;
	DS12C887_RW=1;
	DS12C887_DATE_OUT();
	DS12C887_DATAOUT(add);
	delay_us(100);
	DS12C887_AS=0;
	DS12C887_RW=0;
	DS12C887_DATAOUT(date);
	delay_us(100);
	DS12C887_RW=1;
	DS12C887_AS=1;
	DS12C887_CS=1;

}
u8 Read_DS12C887(u8 add)
{
	u8 DS12C887_DATE;
	DS12C887_AS=1;
	DS12C887_DS=1;
	DS12C887_RW=1;
	DS12C887_CS=0;
	
	DS12C887_DATE_OUT();
	DS12C887_DATAOUT(add);
	delay_us(100);
	DS12C887_AS=0;
	DS12C887_DS=0;
	DS12C887_DATAOUT(0xff);
	DS12C887_DATE_IN();
	DS12C887_DATE=DS12C887_DATAIN;
	DS12C887_DS=1;
	DS12C887_AS=1;
	DS12C887_CS=1;
	return DS12C887_DATE;
}
//写入一个7字节数组,年/月/日/星期/时/分/秒
void Read_DS12C887Date(u8 *temp0)
{
	*temp0=Read_DS12C887(9); //年
	*(temp0+1)=Read_DS12C887(8); //月
	*(temp0+2)=Read_DS12C887(7); //日
	*(temp0+3)=Read_DS12C887(6); //星期
	*(temp0+4)=Read_DS12C887(4); //时
	*(temp0+5)=Read_DS12C887(2); //分
	*(temp0+6)=Read_DS12C887(0); //秒
}

void DS12C887_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF, ENABLE);
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStruct);
	GPIO_SetBits(GPIOE,0x78|GPIO_ReadOutputData(GPIOE));//控制脚初始化,置1
	
	GPIO_InitStruct.GPIO_Pin=0xff;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_Init(GPIOF,&GPIO_InitStruct);
	GPIO_SetBits(GPIOF,0xff);

	Write_DS12C887(0x0a,0x20);//打开振荡器
	Write_DS12C887(0x0b,0x26);//设置24小时模式,数据为二进制,开启闹铃
	
//	Write_DS12C887(0,xxx);  //秒
//	Write_DS12C887(2,xxx);  //分
//	Write_DS12C887(4,xxx);  //小时
//	Write_DS12C887(6,xxx);  //星期
//	Write_DS12C887(7,xxx);  //日
//	Write_DS12C887(8,xxx);  //月
//	Write_DS12C887(9,xxx);  //年 
//	Write_DS12C887(1,xxx);  //秒闹钟
//	Write_DS12C887(3,xxx);  //分闹钟
//	Write_DS12C887(5,xxx);  //小时闹钟
}

源代码中的“xxx”为自己设定的值,可根据自己的情况来修改。当数据设置为二进制模式时,寄存器表如下:
寄存器分布表
如想要设置脉冲输出,可对应下表来选择输出的频率:
方波频率配置
如输出8192Hz的方波:
Write_DS12C887(0x0b,0x2e); //设置方波输出,SQWE位置高,
Write_DS12C887(0x0a,0x23); //频率8192Hz,设置频率。
当然,还可以设置两个DS12C887+同时进行方波输出,可以看下它们的输出时钟精度。
在这里插入图片描述
0s处:
在这里插入图片描述
0.5s处:
在这里插入图片描述
1s处:
在这里插入图片描述
约错开了四分之一个周期,则1秒约错开了0.03ms。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值