模拟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