以下是我编写的DS1302芯片驱动代码,已测试,可以正常操作芯片,但是我用到的是stm32单片机,估计会有同学不习惯使用库的风格,但是不重要,感兴趣的同学可以参考程序的步骤就可以了,比如要看时序,就只看那一个 函数就可以了。。。。。更希望用51单片机开发的同学要是方便的话,能上传你宝贵的代码,让更多的人简单清楚的明白驱动步骤,更好的帮助他们
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "ds1302.h"
#define DS1302_RESET_PORT GPIOC
#define DS1302_RESET_BIT GPIO_Pin_10
#define DS1302_SCLK_PORT GPIOC
#define DS1302_SCLK_BIT GPIO_Pin_11
#define DS1302_DATA_PORT GPIOC
#define DS1302_DATA_BIT GPIO_Pin_12
void DS1302Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//打开时钟模块
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS1302_RESET_BIT;//reset
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(DS1302_RESET_PORT, &GPIO_InitStructure);//复位引脚
GPIO_InitStructure.GPIO_Pin = DS1302_SCLK_BIT;
GPIO_Init(DS1302_SCLK_PORT, &GPIO_InitStructure);//SCLK
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);
GPIO_InitStructure.GPIO_Pin = DS1302_DATA_BIT;//data
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出,通过外接上拉电阻,达到双向通信
GPIO_Init(DS1302_DATA_PORT, &GPIO_InitStructure);
DS1302TimeConfig();
}
unsigned char CommunicationByte(unsigned char value)
{
unsigned char i, temp;
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
temp = 0;
i = 0;
for(i = 0; i < 8; i++)
{
//接收数据,数据是紧接着控制字最后一位输出的
asm("NOP");asm("NOP");asm("NOP");asm("NOP");
temp >>= 1;//低位在前
if (GPIO_ReadInputDataBit(DS1302_DATA_PORT, DS1302_DATA_BIT) == 1)
{
temp |= 0x80;
}
//发送数据
if ((value & 0x01) != 0)
{
GPIO_WriteBit(DS1302_DATA_PORT, DS1302_DATA_BIT, Bit_SET);
}
else
{
GPIO_WriteBit(DS1302_DATA_PORT, DS1302_DATA_BIT, Bit_RESET);
}
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_SET);//sclk = 1, 上升沿
value >>= 1;//低位在前
asm("NOP");asm("NOP");asm("NOP");asm("NOP");
GPIO_WriteBit(DS1302_DATA_PORT, DS1302_DATA_BIT, Bit_SET);//拉高DATA IO,避免影响芯片输出
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0,下降沿
}
return temp;
}
void DS1302WriteRegister(unsigned char reg, unsigned char value)
{
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//只有在SCLK为低电平时候,才允许将rst置位高电平
CommunicationByte(reg);
CommunicationByte(value);
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
}
unsigned char DS1302ReadRegister(unsigned char reg)
{
unsigned char temp;
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//只有在SCLK为低电平时候,才允许将rst置位高电平
CommunicationByte(reg);
temp = CommunicationByte(0xff);
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_SET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
return temp;
}
void DS1302WriteTime(unsigned char *data)
{
unsigned char i;
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//reset = 1;
CommunicationByte(0xbe);//连续写 日历/时钟寄存器
for (i = 0; i < 8; i++)
{
CommunicationByte(data[i]);
}
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
}
void DS1302ReadTime(unsigned char *buffer)
{
unsigned char i;
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//reset = 1;
CommunicationByte(0xbf);//连续读 日历/时钟寄存器
for (i = 0; i < 8; i++)
{
buffer[i] = CommunicationByte(0xff);
}
GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_SET);//sclk = 0;
GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
}
void DS1302TimeConfig(void)
{
unsigned char temp;
unsigned char data[8] = {0x01,0x10,0x11,0x30,0x11,0x05,0x12};//for test
temp = DS1302ReadRegister(0xc1);//读取ds1302ram 数据
if (temp != 0xaa)//第一次上电
{
DS1302WriteRegister(0x8e, 0x00);//允许写操作
DS1302WriteRegister(0xc0, 0xaa);//置标志位
DS1302WriteTime(data);
DS1302WriteRegister(0x8e, 0x80);//禁止写操作
/*
DS1302WriteRegister(0x80,0x01);//设置秒
DS1302WriteRegister(0x82,0x18);//设置分
DS1302WriteRegister(0x84,0x17);//设置时
DS1302WriteRegister(0x86,0x29);//设置日
DS1302WriteRegister(0x88,0x11);//设置月
DS1302WriteRegister(0x8a,0x04);//设置星期
DS1302WriteRegister(0x8c,0x12);//设置年
*/
}
}
void DS1302TimeUpdate(unsigned char *data)
{
//data 数据应为压缩bcd码
DS1302WriteRegister(0x8e, 0x00);//允许写操作
DS1302WriteRegister(0xc0, 0xaa);//置标志位
DS1302WriteTime(data);//连续写入 时钟/日历 寄存器数据
DS1302WriteRegister(0x8e, 0x80);//禁止写操作
}