#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(); //产生一个停止条件 }