
#include "config.h"	 	//全局声明

//===========================================================================
//Subroutine:	 iic_init 
//IIC初始化
//===========================================================================

//void delay_us(unsigned int Counter)
//{
//	uint32_t count;
//	while (Counter--) 
//	{
//		count = 42;  // 根据主频和编译器调整该值
//		while (count--) 
//		{
//				__asm__ volatile("nop");  // 确保不被优化
//			}
//  }
//}
void DS1307_Init()
{
	u8 i = 0;
 	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = iic_scl|iic_sda;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(iic_gpio, &GPIO_InitStructure);
	GPIO_SetBits(iic_gpio,iic_scl|iic_sda);
	TXHData.CTIMEReadTimer.Init = 0;               //清除初始化标志
	TXHData.CTIMEReadTimer.Flag = 0;               //清除到时标志
	TXHData.CTIMEReadTimer.ON_OFF = 1;             //打开
	TXHData.CTIMEReadTimer.Cycle = 1;              //设置为循环模式，发送时启动
	TXHData.CTIMEReadTimer.TimerCountMax = 500;//周期0.5秒
	DS1307_Read();
	if(TXHData.CTIME.Sec > 0x59)
	{
	  //TXHData.PREXDATA_WaitUpNummber = 0;
	  TXHData.CTIME.Year  = 0x24;//年
	  TXHData.CTIME.Month = 0x08;//月
	  TXHData.CTIME.Day   = 0x30;//日
	//TXHData.CTIME.Week  = 0x02;//周	
	  TXHData.CTIME.Hour  = 0x14;//时
	  TXHData.CTIME.Min   = 0x20;//分
	  TXHData.CTIME.Sec   = 0x00;//秒
	  DS1307_Write();
	  }
}
//===========================================================================
//Subroutine:	 iic_start 
//IIC数据传送启动信号
//SCL为高电平的时候，SDA下降沿
//===========================================================================
 void iic_start(void)
{
	iic_sdaout();    				 //SDA线输出
	GPIO_SetBits(iic_gpio,iic_sda);	 //SDA为高电平 	  
	GPIO_SetBits(iic_gpio,iic_scl);	 //SCL为高电平
	delay_us(4);
 	GPIO_ResetBits(iic_gpio,iic_sda); //SDA下降沿
}	  
//===========================================================================
//Subroutine:	 iic_stop 
//IIC数据传送停止信号
//SCL为高电平时，SDA上升沿
//===========================================================================
void iic_stop(void)
{
	iic_sdaout();					  //SDA线输出
	GPIO_ResetBits(iic_gpio,iic_sda); //SDA为低电平
 	delay_us(4);
	GPIO_SetBits(iic_gpio,iic_scl);  //SCL高电平
	GPIO_SetBits(iic_gpio,iic_sda);  //SDA上升沿，I2C总线数据传送结束信号						   	
}
//===========================================================================
//Subroutine:	 iic_wait4ack 
//IIC等待应答
//返回值：1，接收应答失败
//        0，接收应答成功
//===========================================================================

u8 iic_wait4ack(void)
{
	u8 times=0;
	iic_sdain();      //SDA设置为输入  
	GPIO_SetBits(iic_gpio,iic_sda);//sda发送高点平
	delay_us(1);	   
	GPIO_SetBits(iic_gpio,iic_scl);	//时钟高电平，上升沿
	delay_us(1);	 
	while(GPIO_ReadInputDataBit(iic_gpio, iic_sda))	//读数据，直到从机给出应答
	{
		if(++times>IICWAITTIMEOUT)
		{
			iic_stop(); //无应答，停止
			return 1;
		}
	}
	GPIO_ResetBits(iic_gpio,iic_scl);//时钟输出低电平，下降沿 	   
	return 0;  
} 
//===========================================================================
//Subroutine:	 iic_act    产生应答
//表示将继续接收数据
//===========================================================================

void iic_ack(void)
{
	GPIO_ResetBits(iic_gpio,iic_scl); //时钟低电平
	iic_sdaout();
	GPIO_ResetBits(iic_gpio,iic_sda); //数据低电平,表示有应答
	delay_us(2);
	GPIO_SetBits(iic_gpio,iic_scl);	  //时钟上升沿
	delay_us(2);
	GPIO_ResetBits(iic_gpio,iic_scl); //时钟下降沿
}

//===========================================================================
//Subroutine:	 iic_noact 	无应答或否认应答
//表示不再接收数据               
//===========================================================================
void iic_noack(void)
{
	GPIO_ResetBits(iic_gpio,iic_scl);  //时钟低电平
	iic_sdaout();
	GPIO_SetBits(iic_gpio,iic_sda);	   //数据高电平,表示无应答
	delay_us(2);
	GPIO_SetBits(iic_gpio,iic_scl);		//时钟上升沿
	delay_us(2);
	GPIO_ResetBits(iic_gpio,iic_scl);	//时钟下降沿
}					 				     

//===========================================================================
//Subroutine:	 iic_sendbyte 
//IIC发送一个字节
//===========================================================================
void iic_sendbyte(u8 txd)
{
   u8 t;   
	 iic_sdaout(); //SDA设置为输出，因为要发送数据	    
    GPIO_ResetBits(iic_gpio,iic_scl); //时钟低电平，只有SCL为低才可改变数据
    for(t=0;t<8;t++)//循环发送8个字节
    {              
 		if ((txd&0x80)>>7) 	GPIO_SetBits(iic_gpio,iic_sda); //发出第7-t位
		else GPIO_ResetBits(iic_gpio,iic_sda);
       txd<<=1; 	  
		delay_us(2);   
		GPIO_SetBits(iic_gpio,iic_scl); //拉高SCL，发数据
		delay_us(2); 
		GPIO_ResetBits(iic_gpio,iic_scl); //SCL恢复低电平，准备修改SDA	
		delay_us(2);
    }	 
} 	 
 
  
//===========================================================================
//Subroutine:	 iic_readbyte 
//读1个字节，ack=1时，读之后发送ACK，ack=0，读者后发送nACK   
//===========================================================================
u8 iic_readbyte(u8 ack)
{
	unsigned char i,receive=0;
	iic_sdain();//准备接收数据，SDA设置为输入
    for(i=0;i<8;i++ )			//循环接收8位
	{
        GPIO_ResetBits(iic_gpio,iic_scl); //SCL为低电平 
        delay_us(2);
		GPIO_SetBits(iic_gpio,iic_scl);   //SCL上升沿，开始读取数据
        receive<<=1;
        if(GPIO_ReadInputDataBit(iic_gpio, iic_sda)) //读取数据
			receive|=0x01; //如果读到的数据为1，receive最低位应为1  
		delay_us(1); 
    }					 
    if (ack) //如果需要应答
        iic_ack();//发送应答
    else
        iic_noack(); //发送无应答   
    return receive;
}

//===========================================================================
//在指定地址读出一个数据
//返回值  :读到的数据   
//===========================================================================
void DS1307_Read(void)//93us
{				  
	u8 temp[7],i;		  
	
  iic_start();  						  //启动
	iic_sendbyte(0XD0);         //发送器件地址0XD0	 
	iic_wait4ack(); 					  //等待应答
  iic_sendbyte(0);   		      //发送字地址
	iic_wait4ack();	    				//等待应答
	iic_start();  	 	   				//产生一个起动条件
	iic_sendbyte(0XD1);         //发送地址0XD1进入接收模式			   
	iic_wait4ack();	 					  //等待应答
	for (i = 0;i < 7;i ++)    
	{   
		if (i < 6) 
			temp[i] = iic_readbyte(1);
		else 
			temp[i] = iic_readbyte(0);
	  } 
  iic_stop();	    					 //产生一个停止条件
	TXHData.CTIME.Year  = temp[6];//年
	TXHData.CTIME.Month = temp[5];//月
	TXHData.CTIME.Day   = temp[4];//日

	TXHData.CTIME.Hour  = temp[2];//时
	TXHData.CTIME.Min   = temp[1];//分
	TXHData.CTIME.Sec   = temp[0];//秒
}
//===========================================================================
//在指定地址写一个数据
//返回值  :无   
//===========================================================================
void DS1307_Write(void)
{
  u8 i = 0,temp[7];	
	
	temp[0]= TXHData.CTIME.Sec;
	temp[1]= TXHData.CTIME.Min;
	temp[2]= TXHData.CTIME.Hour;
	temp[3]= 0x01;
	temp[4]= TXHData.CTIME.Day;
	temp[5]= TXHData.CTIME.Month;
	temp[6]= TXHData.CTIME.Year;
  iic_start();  
	iic_sendbyte(0XD0);   //发送器件地址0XD0 
	iic_wait4ack();	   		//等待应答
	iic_sendbyte(0x00);   //发送字地址
	iic_wait4ack(); 	 		//等待应答
	for(i = 0;i < 7;i ++)
	{								  		   
	  iic_sendbyte(temp[i]);   //发送字节			
	  iic_wait4ack();  		     //等待应答	  
	  }		
  iic_stop();					 //产生一个停止条件 
}
