模拟I2C通讯控制DS1307读写硬件时钟
#include "global.h"
#include "drv_ds1307.h"
#define I2C_CLK_PORT GPIOB
#define I2C_CLK_PIN GPIO_PIN_4
#define I2C_SDA_PORT GPIOB
#define I2C_SDA_PIN GPIO_PIN_5
#define SCL_High() GPIO_Init(I2C_CLK_PORT, I2C_CLK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define SCL_Low() GPIO_Init(I2C_CLK_PORT, I2C_CLK_PIN, GPIO_MODE_OUT_PP_LOW_SLOW)
#define SDA_High() GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define SDA_Low() GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP_LOW_SLOW)
#define SDAM() (GPIO_ReadInputData(I2C_SDA_PORT) & 0x20) ?1:0
#define SET_SCL_OUT() GPIO_Init(I2C_CLK_PORT, I2C_CLK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define SET_SDA_OUT() GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define SET_SDA_IN() GPIO_Init(GPIOA, GPIO_PIN_0, GPIO_MODE_IN_PU_NO_IT)
extern uint8_t Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData);
extern uint8_t Ds1307_ReadByte(uint8_t ReadAddr);
extern void Ds1307_WriteData();
extern void Ds1307_ReadData();
extern void Init_Timer();
extern void Write_Time();
uint8_t g_u8ReadData[8];
/*******************************************************************************
// Function: I2C_Int
// Description: 模拟I2C 与ds1307端口初始化
// Param:
// Return:
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static void I2C_Int(void)
{
SET_SDA_OUT();
SET_SCL_OUT();
}
/*******************************************************************************
// Function: Delay_5us
// Description: 微妙级延时函数 延时时间约为16us
// Param:
// Return: fcpu 16MHz 时
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static void Delay_5us(void)
{
uint8_t i;
for (i=5; i>0; i--);
}
/*******************************************************************************
// Function: I2C_Start
// Description: I2C 开始传输信号 当SCL 为高时 SDA由高变低
// Param:
// Return:
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static void I2C_Start(void)
{
// SDA 1->0 while SCL High
SDA_High();
SCL_High();
Delay_5us();
SDA_Low();
Delay_5us();
SCL_Low();
}
/*******************************************************************************
// Function: I2C_Stop
// Description: I2C 停止传输信号 当SCL 为高时 SDA由低变高
// Param:
// Return:
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static void I2C_Stop(void)
{
// SDA 0->1 while SCL High
SDA_Low();
SCL_High();
Delay_5us();
SDA_High();
Delay_5us();
}
/*******************************************************************************
// Function: I2C_SendACK
// Description: 主机向从机发送应答信号
// Param: 应答信号 1:表示SDA高电平(无应答) 0:SDA低电平(有应答)
// Return:
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static void I2C_SendACK(uint8_t ack)
{
if(ack == 0)
{
SDA_Low();
}
else
{
SDA_High();
}
SCL_High();
Delay_5us();
SCL_Low();
Delay_5us();
}
/*******************************************************************************
// Function: I2C_SendByte
// Description: 模拟I2C通信 发送8位数据
// Param: 发送的8为数据值
// Return: 返回应答信号 0表示有应答 1表示无应答
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static uint8_t I2C_SendByte(uint8_t SendByte)
{
static uint8_t i,RevAck;
SDA_Low();
for (i= 0 ; i< 8; i++)
{
SCL_Low();
if (SendByte & 0x80) // write data
{
SDA_High();
}
else
{
SDA_Low();
}
Delay_5us();
SendByte <<= 1;
SCL_High();
Delay_5us();
}
SCL_Low();
SDA_High();
Delay_5us();
SET_SDA_IN();
SCL_High();
asm("nop");
asm("nop");
RevAck = (uint8_t)SDAM();
Delay_5us();
SCL_Low();
SET_SDA_OUT();
Delay_5us();
return RevAck;
}
/*******************************************************************************
// Function: I2C_RecvByte
// Description: 模拟I2C通信 从从机读取8位数据
// Param:
// Return: 返回读取的8为数据值
// Author: Huangzhigang 2014-0410
*******************************************************************************/
static uint8_t I2C_RecvByte()
{
uint8_t i;
uint8_t RecvData = 0;
SDA_High(); // latch the Data port befor reading
SET_SDA_IN();
for (i=0; i<8; i++)
{
RecvData <<= 1;
SCL_High();
asm("nop");
asm("nop");
if (SDAM())
{
RecvData |= 0x01;
}
else
{
RecvData &= 0xfe;
}
Delay_5us();
SCL_Low();
Delay_5us();
}
SET_SDA_OUT();
return RecvData;
}
/*******************************************************************************
// Function: Ds1307_WriteByte
// Description: 模拟I2C通信 写入1字节数据到指定地址
// Param: WriteAddr:待写入数据 WriteData;写入的地址
// Return: 1: 成功写入 0: 写入出错
// Author: Huangzhigang 2014-0410
*******************************************************************************/
uint8_t Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData)
{
I2C_Start();
if(I2C_SendByte(0xD0)) // Device Addr + Write (operation)
{
return 0;
}
if(I2C_SendByte(WriteAddr))
{
return 0;
}
if(I2C_SendByte(WriteData))
{
return 0;
}
I2C_Stop();
return 1;
}
/*******************************************************************************
// Function: Ds1307_ReadByte
// Description: 模拟I2C通信 从指定地址读取1字节数据
// Param: ReadAddr:读取的地址
// Return: RevData:读取的8位数据
// Author: Huangzhigang 2014-0410
*******************************************************************************/
uint8_t Ds1307_ReadByte(uint8_t ReadAddr)
{
uint8_t RevData;
I2C_Start();
I2C_SendByte(0xD0); // Device Addr + Write (operation)
I2C_SendByte(ReadAddr);
I2C_Start();
I2C_SendByte(0xD1); // Device Addr + Write (operation)
RevData = I2C_RecvByte();
I2C_SendACK(1);
I2C_Stop();
return RevData;
}
/*******************************************************************************
// Function: Ds1307_WriteData
// Description: 模拟I2C通信 写入8字节数据 从0x00~0x07
// Param: pWriteData: 指针指向待写入的数组的地址
// Return:
// Author: Huangzhigang 2014-0410
*******************************************************************************/
void Ds1307_WriteData()
{
uint8_t i;
uint8_t *pWriteData;
pWriteData = (uint8_t *)&ICTimerBuf;
I2C_Start();
I2C_SendByte(0xD0); // Device Addr + Write (operation)
I2C_SendByte(0x00);
for(i=0; i<8; i++)
{
I2C_SendByte(*pWriteData++);
}
I2C_Stop();
}
/*******************************************************************************
// Function: Ds1307_ReadData
// Description: 模拟I2C通信 读取8字节数据 从0x00~0x07
// Param: pReadData: 指针指向保存数据的数组
// Return:
// Author: Huangzhigang 2014-0410
*******************************************************************************/
void Ds1307_ReadData()
{
uint8_t i;
uint8_t *pReadData;
pReadData = (uint8_t *)&ICTimerBuf;
I2C_Start();
I2C_SendByte(0xD0); // Device Addr + Write (operation)
I2C_SendByte(0x00);
I2C_Start();
I2C_SendByte(0xD1); // Device Addr + Write (operation)
for(i=0; i<7; i++)
{
// *pReadData++ = I2C_RecvByte();
*pReadData = I2C_RecvByte();
pReadData++;
if(i < 6)
I2C_SendACK(0); //DIO低电平 表示ACK 应答
else
I2C_SendACK(1);
}
I2C_Stop();
}
/*******************************************************************************
// Function: Init_Timer
// Description: 上电初始化时钟以及读时钟
// Param:
// Return: 判断0x00 地址bit7 是否为1 为1表示时钟芯片掉电
// Author: Huangzhigang 2014-0422
*******************************************************************************/
void Init_Timer()
{
I2C_Int();
Ds1307_ReadData();
if(ICTimerBuf.TimerSec & 0x80)
{
Ds1307_ReadData();
if(ICTimerBuf.TimerSec & 0x80)
{
ICTimerBuf.TimerSec =0x00;
ICTimerBuf.TimerMin =0x00;
ICTimerBuf.TimerHour =0x12;
ICTimerBuf.TimerWeek =0x02;
ICTimerBuf.TimerDay =0x15;
ICTimerBuf.TimerMonth =0x04;
ICTimerBuf.TimerYear =0x14;
Ds1307_WriteData();
}
}
ICTimer.TimerSec =(ICTimerBuf.TimerSec/16) * 10 + (ICTimerBuf.TimerSec%16);
ICTimer.TimerMin =(ICTimerBuf.TimerMin/16) * 10 + (ICTimerBuf.TimerMin%16);
ICTimer.TimerHour =((ICTimerBuf.TimerHour&0x1f)/16) * 10 + ((ICTimerBuf.TimerHour&0x1f)%16);
ICTimer.TimerWeek =(ICTimerBuf.TimerWeek/16) * 10 + (ICTimerBuf.TimerWeek%16);
ICTimer.TimerDay =(ICTimerBuf.TimerDay/16) * 10 + (ICTimerBuf.TimerDay%16);
ICTimer.TimerMonth =(ICTimerBuf.TimerMonth/16) * 10 + (ICTimerBuf.TimerMonth%16);
ICTimer.TimerYear =(ICTimerBuf.TimerYear/16) * 10 + (ICTimerBuf.TimerYear%16);
//更新系统时间参数
g_u8TimeSettingHourValue = ICTimer.TimerHour;
g_u8TimeSettingMinutesValue = ICTimer.TimerMin;
g_u8TimeSettingAmPmValue = (ICTimerBuf.TimerHour &0x20)?1:0;
}
/*******************************************************************************
// Function: Write_Time
// Description: 如果设置了时钟则写入时钟
// Param:
// Return:
// Author: Huangzhigang 2014-0422
*******************************************************************************/
void Write_Time()
{
if(g_u8TimeChangeFlag) //如果设置了时钟
{
g_u8TimeChangeFlag = 0;
ICTimerBuf.TimerSec = (ICTimer.TimerSec/10)*16 + (ICTimer.TimerSec%10);
ICTimerBuf.TimerMin = (ICTimer.TimerMin/10)*16 + (ICTimer.TimerMin%10);
ICTimerBuf.TimerHour = (ICTimer.TimerHour/10)*16 + (ICTimer.TimerHour%10);
ICTimerBuf.TimerWeek = (ICTimer.TimerWeek/10)*16 + (ICTimer.TimerWeek%10);
ICTimerBuf.TimerDay = (ICTimer.TimerDay/10)*16 + (ICTimer.TimerDay%10);
ICTimerBuf.TimerMonth = (ICTimer.TimerMonth/10)*16 + (ICTimer.TimerMonth%10);
ICTimerBuf.TimerYear = (ICTimer.TimerYear/10)*16 + (ICTimer.TimerYear%10);
//转换为12时制时间
if(g_u8TimeSettingAmPmValue %2) //为1 表示 pM
{
ICTimerBuf.TimerHour |= 0x60;
}
else //为0表示AM
{
ICTimerBuf.TimerHour |= 0x40;
}
//转换好之后把时间写入芯片
Ds1307_WriteData();
}
}硬件时钟--DS1307时钟芯片,布布扣,bubuko.com
原文地址:http://blog.csdn.net/a656343072/article/details/38709437