时间记录:2024/3/30
一、知识点
(1)读写数据时序(伪SPI协议)
1.1 读写时序默认电平均为SCLK线低电平,CE线低电平
1.2 写数据,CE线拉高为高电平,开始传输数据,然后准备数据在SCLK线的上升沿DS1302读取数据,发送8位控制命令后,发送8位数据(低位先发)
1.3 读数据,CE线拉高为高电平,开始传输数据,然后在SCLK低电平时准备数据,上升沿发送数据,发送8位控制命令后,下一个下降沿开始读取数据(低位先发,低位先读)
(2)读写命令及数据格式
2.1 READ和WRITE的命令即为发送和读取数据前需要先发送的对应8位控制命令
2.2 秒数据的BIT7位CH决定时钟的开启/关闭
2.3 小时数据的BIT7位决定是12小时显示还是24小时显示
2.4 WP位决定开启写保护还是取消写保护,写入0取消写保护,写入1打开写保护
(3)数据转换
3.1 DS1302读取的数据为BCD编码格式,需要转为10进制,写入时10进制数据需要转为BCD格式
3.2 BCD->10进制,BCD/1610+BCD%16
3.3 10进制->BCD,10进制/1016+10进制%10
二、示例代码
(1)头文件
#ifndef __DS1302_H__
#define __DS1302_H__
#include "stm32f10x.h"
void ds1302Init(void);
u8 ds1302_ReadRam(u8 addr);
#endif
(2)源文件
#include "ds1302.h"
static void datLineMode(u8 mode);
static void write(u8 addr,u8 data);
void ds1302Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
}
static void write(u8 addr,u8 data)
{
//1.拉高CE片选线,开始通信
GPIO_SetBits(GPIOA,GPIO_Pin_10);
datLineMode(0);
for(u8 i=0;i<8;i++) //写入命令字节
{
//2.拉低CLK线准备数据
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
if(addr&0x01)
GPIO_SetBits(GPIOA,GPIO_Pin_11);
else
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
//3.拉高CLK线将数据发送出去
GPIO_SetBits(GPIOA,GPIO_Pin_12);
addr>>=1;
}
for(u8 i=0;i<8;i++) //写入数据字节
{
//2.拉低CLK线准备数据
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
if(data&0x01)
GPIO_SetBits(GPIOA,GPIO_Pin_11);
else
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
//3.拉高CLK线将数据发送出去
GPIO_SetBits(GPIOA,GPIO_Pin_12);
data>>=1;
}
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
}
u8 ds1302_ReadRam(u8 addr)
{
//1.拉高CE片选线,开始通信
GPIO_SetBits(GPIOA,GPIO_Pin_10);
datLineMode(0);
for(u8 i=0;i<8;i++) //写入命令字节
{
//2.拉低CLK线准备数据
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
if(addr&0x01)
GPIO_SetBits(GPIOA,GPIO_Pin_11);
else
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
//3.拉高CLK线将数据发送出去
GPIO_SetBits(GPIOA,GPIO_Pin_12);
addr>>=1;
}
u8 data = 0x00;
datLineMode(1);
for(u8 i=0;i<8;i++) // 读取数据
{
//产生下降沿,然后读出数据
data >>= 1; // 第一位数据为控制位
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11)) //读取数据
{
data |= 0x80;
}
GPIO_SetBits(GPIOA,GPIO_Pin_12);
}
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
return data;
}
static void datLineMode(u8 mode)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(mode==0)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
else if(mode==1)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
}