硬件时钟--DS1307时钟芯片

模拟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时钟芯片

时间: 2024-08-08 14:40:35

硬件时钟--DS1307时钟芯片的相关文章

硬件时钟--ht1381时钟芯片驱动

ht1381时钟芯片驱动 #include "global.h" //时钟芯片ht1381各引脚定义 #define HT1381_CS_GPIO_PORT GPIOD #define HT1381_CS_GPIO_PIN GPIO_PIN_3 #define HT1381CsHigh() (HT1381_CS_GPIO_PORT->ODR |= (u8)(HT1381_CS_GPIO_PIN)) #define HT1381CsLow() (HT1381_CS_GPIO_POR

网页计算器 &amp;&amp; 简易网页时钟 &amp;&amp; 倒计时时钟

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

舌尖上的硬件:CPU/GPU芯片制造解析(高清)(组图)

一沙一世界,一树一菩提,我们这个世界的深邃全部蕴藏于一个个普通的平凡当中.小小的厨房所容纳的不仅仅是人们对味道的情感,更有推动整个世界前进的动力.要想理解我们的世界,有的时候只需要细细品味一下我们所喜爱的美食即可.正因为此,我们才规划了<舌尖上的硬件>这样一个系列栏目.通过对美食的品味和体会,我们可以更好地理解许多硬件相关的原理.内涵甚至是趣闻,我们所需要为此准备的,其实仅仅是一颗平和的心而已. 在上一期的<舌尖上的硬件>栏目中,我们第一次接触到了隐藏在食物背后的其与半导体业界的神

分布式系统阅读笔记(二十二)-----时钟和时钟同步

时钟的基本概念 时钟 时钟在一般意义上指的是一个计算机的物理时间,每个计算机都会包括他们自己的物理时钟,不同的计算机的物理可能会不同. 时钟漂移 经过在同个地方的计算机,他们的物理也有可能会不一样,如果他们从刚刚开始相同的时间计时开始,过了1过月,1年也可能会有快又慢,这在专业名词上讲叫做时间漂移.本质的原因是每秒的时间偏移,经过日记月累之后,就会有可能达到1秒钟的差距,解决的办法很简单,就是过一段时间之后,将时间纠正回来就可以了. UTC UTC全称是Coordinated Universal

美女时钟+电子时钟

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <title>美女时钟</ti

X-005 FriendlyARM tiny4412 uboot移植之时钟初始化

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  开发环境:

STM32时钟系统

一.在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. ①HSI是高速内部时钟,RC振荡器,频率为8MHz. ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz.一般接8MHZ. ③LSI是低速内部时钟,RC振荡器,频率为40kHz. ④LSE是低速外部时钟,接频率为32.768kHz的石英晶体. ⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2.HSE或者HSE/2.倍频可选择为2~16倍,但是其输出频率最大不得超过72

SOC时钟

什么是时钟?SOC为什么需要时钟? 时钟是同步工作系统的同步节拍. SOC内部有很多器件,譬如CPU.串口.DRAM控制器,GPIO等内部外设,这些东西要彼此协调工作,需要一个同步的时钟系统来指挥. 时钟的获得? SOC时钟获得一般有: 外部直接输入时钟信号,SOC有一个引脚用来输入外部时钟信号,用的很少 外部晶振+内部时钟发生器产生时钟,大部分低频单片机这么工作 外部晶振+内部时钟发生器+内部PLL产生高频时钟+内部分频器分频得到各种频率的时钟 s5pv210属于第3种,为什么这么设计? 第一

ARM时钟及电源管理

电源管理模块具有正常模式(NORMAL MODE).慢速模式(SLOW MODE).空闲模式(IDLE MODE).掉电模式(POWER_OFF MODE)共四种工作模式. 产生的时钟信号有 1.MPLL时钟(锁相环): 2.UPLL时钟(USB时钟) 3.HCLK(连接到AHB总线上外围高速组件使用的时钟) 4.PCLK时钟(连接到APB总线上外围组件使用的时钟) 5.FCLK时钟(内核所需时钟)等供不同 正常模式下电源管理模式为内核及ARM芯片内部所有硬件组件提供时钟源,即所有设备处于开启状