- #include<stm32f4xx.h>
 
-  
 
- /********************软件模拟IIC*********************/
 
- /*****************PB8=SCL,PB9=SDA*****************/
 
-  
 
-  
 
- #define        DS3231_ADDRESS_Write        0xD0
 
- #define        DS3231_ADDRESS_Read                0xD1
 
-  
 
-  
 
- /**************DS3231内部寄存器地址***************/
 
-  
 
- #define DS3231_SEC        0x00  // 秒
 
- #define DS3231_MIN        0x01  //分
 
- #define DS3231_HOUR       0x02        //时
 
- #define DS3231_WEEK       0x03        //周
 
- #define DS3231_DATE       0x04        //日
 
- #define DS3231_MONTH      0x05        //月
 
- #define DS3231_YEAR       0x06        //年
 
-  
 
- #define DS3231_AL1SEC     0x07
 
- #define DS3231_AL1MIN     0x08
 
- #define DS3231_AL1HOUR    0x09
 
- #define DS3231_AL1WDAY    0x0A
 
-  
 
- #define DS3231_AL2MIN     0x0B
 
- #define DS3231_AL2HOUR    0x0C
 
- #define DS3231_AL2WDAY    0x0D
 
-  
 
- #define DS3231_CONTROL          0x0E
 
- #define DS3231_STATUS           0x0F
 
- #define DS3231_AGING_OFFSET     0x0F
 
- #define DS3231_TMP_High         0x11
 
- #define DS3231_TMP_LOW          0x12
 
-  
 
- /******DS3231内部寄存器地址******/
 
- /**************END**************/
 
-  
 
-  
 
- #define Read_IIC_SDA GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)                //定义Read_IIC_SDA为PB11的输入值
 
-  
 
- #define IIC_SCL_H() GPIO_SetBits(GPIOB,GPIO_Pin_8)                                        //定义IIC_SCL_H()函数为将RES(PB10)置高电平        
 
- #define IIC_SCL_L() GPIO_ResetBits(GPIOB,GPIO_Pin_8)                                //定义IIC_SCL_L()函数为将RES(PB10)置低电平        
 
-  
 
- #define IIC_SDA_H() GPIO_SetBits(GPIOB,GPIO_Pin_9)                                        //定义IIC_SDA_H()函数为将RES(PB11)置高电平        
 
- #define IIC_SDA_L() GPIO_ResetBits(GPIOB,GPIO_Pin_9)                                //定义IIC_SDA_L()函数为将RES(PB11)置低电平        
 
-  
 
-  
 
-  //最后读取到的时间数据将赋值到下面这几个变量
 
- u8 RTC_Sec,RTC_Min,RTC_Hour,RTC_Week,RTC_Date,RTC_Month;   
 
- u16 RTC_Year;
 
-  
 
-  
 
- void IIC2_SoftInit(void)
 
- {
 
-     GPIO_InitTypeDef GPIO_InitStructure;
 
-         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
 
-     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_9;                         //10--SCL   11--SDA;PB10 PB11
 
-     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 
-     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
 
-         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                        //OD开漏
 
-         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                        //上拉
 
-     GPIO_Init(GPIOB, &GPIO_InitStructure);
 
- }
 
-  
 
- /******* 设置SDA为输出*******/
 
-  
 
- void SDA_OUT(void)
 
- {
 
-     GPIO_InitTypeDef GPIO_InitStructure;
 
-     GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
 
-     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 
-     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;        //推挽输出
 
-         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                        //OD开漏
 
-         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;                        //上拉
 
-     GPIO_Init(GPIOB, &GPIO_InitStructure);
 
- }
 
-  
 
- /******* 设置SDA为输入*******/
 
-  
 
- void SDA_IN(void)
 
- {
 
-     GPIO_InitTypeDef GPIO_InitStructure;
 
-     GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
 
-     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 
-     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;                //上拉输入
 
-         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                        //OD开漏
 
-         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;                        //上拉
 
-         GPIO_Init(GPIOB, &GPIO_InitStructure);
 
- }
 
-  
 
-  
 
-  
 
-  void IIC_Start(void)                        //起始信号
 
- {
 
-     SDA_OUT();                        //把SDA作为输出,初始化为推挽输出
 
-     IIC_SDA_H();                //SDA输出高电平
 
-     IIC_SCL_H();                //SCL输出高电平
 
-     Delay_us(2);
 
-     IIC_SDA_L();                //SDA输出低点评
 
-     Delay_us(2);
 
-     IIC_SCL_L();                //SCL输出低电平
 
-     Delay_us(2);
 
- }
 
-  
 
- void IIC_Stop(void)                //停止信号
 
- {
 
-     IIC_SCL_H();                //SCL输出高电平
 
-     IIC_SDA_L();                //SDA输出低点评
 
-     Delay_us(2);
 
-     IIC_SDA_H();                //SDA输出高电平
 
-     Delay_us(2);
 
- }
 
-  
 
-  
 
- u8 IIC_Wait_Ask(void)                //等待应答信号
 
- {
 
-     u8 count;
 
-     IIC_SDA_H();
 
-         Delay_us(2);
 
-         SDA_IN();
 
-         Delay_us(2);
 
-     IIC_SCL_H();
 
-     Delay_us(2);
 
-     while(Read_IIC_SDA)
 
-     {
 
-         count++;
 
-         if(count>250)
 
-         {
 
-             IIC_Stop();                                //如果长时间无应答,则认为从站故障,终止数据传输,并返回1
 
-             return 1;
 
-         }   
 
-     }
 
-     IIC_SCL_L();
 
-     Delay_us(1);
 
-     return 0;
 
- }
 
-  
 
-  
 
-  
 
- void IIC_Ack(void)                //应答信号
 
- {
 
-     IIC_SCL_L();
 
-     SDA_OUT();
 
-     IIC_SDA_L();
 
-     Delay_us(2);
 
-     IIC_SCL_H();
 
-     Delay_us(2);
 
-     IIC_SCL_L();
 
- }
 
-  
 
- void IIC_NAck(void)                //主机不产生应答信号NACK
 
- {
 
-     IIC_SCL_L();
 
-     SDA_OUT();
 
-     IIC_SDA_H();
 
-     Delay_us(2);
 
-     IIC_SCL_H();
 
-     Delay_us(2);
 
-     IIC_SCL_L();
 
- }
 
-  
 
-  
 
-  
 
- void IIC_WriteByte(u8 data)                        //写1Byte数据,每个数据都是以写1Byte作为基本单位
 
- {
 
-     u8 i;
 
-     SDA_OUT();                                                //SDA切换到数据输出模式
 
-         Delay_us(2);
 
-     for(i=0;i<8;i++)                                //循环传输1Byte数据,即8bit
 
-     {
 
-         IIC_SCL_L();                                //SCL置低电平,为下个Bit数据做准备
 
-                 Delay_us(2);
 
-         if(data & 0x80)                     //MSB,如果date的第八位为1
 
-             IIC_SDA_H();                        //则SDA置高
 
-         else
 
-             IIC_SDA_L();                        //否则置低
 
-                 Delay_us(1);
 
-         IIC_SCL_H();                                //SCL拉高,产生一个时钟信号,从机读取SDA状态
 
-         Delay_us(2);                                //延时,丛机在这段时间读取SDA状态
 
-         IIC_SCL_L();                                //延时后拉低SCL,为下个Bit数据做准备
 
-         data<<=1;                                        //date左移1位,下一bit变成第八位
 
-     }
 
- }
 
-  
 
- //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
 
-  
 
-  
 
-  
 
- u8 IIC_Read_Byte(const unsigned char ack)
 
- {
 
-         u8 i,receive=0;
 
-         SDA_IN();                        //SDA设置为输入
 
-         Delay_us(2);
 
-     for(i=0;i<8;i++ )
 
-         {
 
-                 IIC_SCL_L(); 
 
-                 Delay_us(2);
 
-                 IIC_SCL_H();
 
-         receive<<=1;
 
-                 Delay_us(2);
 
-         if(Read_IIC_SDA)
 
-                         receive++;   
 
-                 Delay_us(2); 
 
-     }                                         
 
-     if (!ack)
 
-         IIC_NAck();                //发送nACK
 
-     else
 
-         IIC_Ack();                 //发送ACK   
 
-     return receive;
 
- }
 
-  
 
-  
 
- void IIC_DS3231_ByteWrite(u8 WriteAddr,u8 date)
 
- {
 
-         IIC_Start();                //起始信号
 
-         IIC_WriteByte(DS3231_ADDRESS_Write);                //DS3231设备地址,写
 
-         IIC_Wait_Ask();                                //等待应答
 
-         IIC_WriteByte(WriteAddr);        //寄存器地址
 
-         IIC_Wait_Ask();                                //等待应答
 
-         IIC_WriteByte(date);                //写入数据
 
-         IIC_Wait_Ask();                                //等待应答
 
-         IIC_Stop();                                        //结束信号
 
- }
 
-  
 
- u8 IIC_DS3231_ByteRead(u8 ReadAddr)
 
- {
 
-         u8 data = 0;
 
-         IIC_Start();                                                                                //产生起始位
 
-         IIC_WriteByte(DS3231_ADDRESS_Write);                                 //发送从机地址(写模式D0)
 
-         IIC_Wait_Ask();                                //等待应答
 
-         IIC_WriteByte(ReadAddr);                                                        //发送寄存器地址
 
-         IIC_Wait_Ask();                                //等待应答
 
-         IIC_Start();                                                                                //重复起始信号
 
-         IIC_WriteByte(DS3231_ADDRESS_Read);                //发送从机地址(读模式)
 
-         IIC_Wait_Ask();                                                        //等待应答
 
-         data = IIC_Read_Byte(0);                                //读取数据,参数设为0 --- NACK
 
-         IIC_Stop();
 
-         return data;
 
- }
 
-  
 
- void IIC_DS3231_ReadAll(void)                //读取所有时间数据并转换
 
- {
 
-         u8 Data_Sec,Data_Min,Data_Hour,Data_Week,Data_Date,Data_Month,Data_Year;
 
-         u8 Low,High;
 
-         
 
-         Data_Sec= IIC_DS3231_ByteRead(DS3231_SEC);                        //读取数据秒
 
-         Data_Min = IIC_DS3231_ByteRead(DS3231_MIN);                        //读取数据分
 
-         Data_Hour = IIC_DS3231_ByteRead(DS3231_HOUR);                //读取数据时
 
-         Data_Week = IIC_DS3231_ByteRead(DS3231_WEEK);                //读取数据周
 
-         Data_Date = IIC_DS3231_ByteRead(DS3231_DATE);                        //读取数据日
 
-         Data_Month = IIC_DS3231_ByteRead(DS3231_MONTH);                //读取数据月
 
-         Data_Year = IIC_DS3231_ByteRead(DS3231_YEAR);                //读取数据年
 
-         
 
-         Low=Data_Sec&0x0f;                                                //取低四位
 
-         High=(( Data_Sec& 0xf0) >> 4);                        //取高四位
 
-         RTC_Sec=High*10+Low;                                        //转换秒(高四位*10+低四位)
 
-         
 
-         Low=Data_Min&0x0f;
 
-         High=(( Data_Min& 0xf0) >> 4);
 
-         RTC_Min=High*10+Low;                                        //转换分
 
-         
 
-         Low=Data_Hour&0x0f;
 
-         High=(( Data_Hour& 0x30) >> 4);
 
-         RTC_Hour=High*10+Low;                                        //转换时(高两位*10+低四位)
 
-  
 
-         RTC_Week=Data_Week;                                                //转换周(不需要转换)
 
-         
 
-         Low=Data_Date&0x0f;
 
-         High=(( Data_Date& 0xf0) >> 4);
 
-         RTC_Date=High*10+Low;                                        //转换日
 
-         
 
-         Low=Data_Month&0x0f;
 
-         High=(( Data_Month& 0x10) >> 4);
 
-         RTC_Month=High*10+Low;                                        //转换月
 
-         
 
-         Low=Data_Year&0x0f;
 
-         High=(( Data_Year& 0xf0) >> 4);
 
-         RTC_Year=((Data_Month>>7)+20)*100+High*10+Low;        //转换年(世纪*100+高四位*10+低四位)                
 
- }
 
-  
 
- void IIC_DS3231_WriteAll(u16 Year,u8 Month,u8 Date,u8 Week,u8 Hour,u8 Min,u8 Sec)
 
- {        
 
-         u8 Sec_Date,Min_Date,Hour_Date,Week_Date,Date_Date,Month_Date,Year_Date;
 
-         u8 H_Bit,L_Bit;
 
-         
 
-         H_Bit=(Sec/10)<<4;                        //取高四位
 
-         L_Bit=Sec%10;                                //取低四位
 
-         Sec_Date=H_Bit|L_Bit;                //合并成八位
 
-         
 
-         H_Bit=(Min/10)<<4;
 
-         L_Bit=Min%10;
 
-         Min_Date=H_Bit|L_Bit;
 
-         
 
-         H_Bit=Hour/10;
 
-         L_Bit=Hour%10;
 
-         Hour_Date=(H_Bit<<4)|L_Bit;
 
-                 
 
-         Week_Date=Week;
 
-         
 
-         H_Bit=Date/10;
 
-         L_Bit=Date%10;
 
-         Date_Date=(H_Bit<<4)|L_Bit;
 
-         
 
-         if(Year/100==20)
 
-         {        
 
-                 H_Bit=Month/10;
 
-                 L_Bit=Month%10;
 
-                 Month_Date=(H_Bit<<4)|L_Bit;
 
-                 
 
-                 H_Bit=(Year-2000)/10;
 
-                 L_Bit=(Year-2000)%10;
 
-                 Year_Date=(H_Bit<<4)|L_Bit;
 
-                 
 
-         }
 
-         else
 
-         {
 
-                 H_Bit=Month/10+8;                //05h第8位如果是1,则为22世纪
 
-                 L_Bit=Month%10;
 
-                 Month_Date=(H_Bit<<4)|L_Bit;
 
-                 
 
-                 H_Bit=(Year-2100)/10;
 
-                 L_Bit=(Year-2100)%10;
 
-                 Year_Date=(H_Bit<<4)|L_Bit;
 
-         }
 
-         IIC_DS3231_ByteWrite(DS3231_YEAR,Year_Date);        
 
-         IIC_DS3231_ByteWrite(DS3231_MONTH,Month_Date);
 
-         IIC_DS3231_ByteWrite(DS3231_DATE,Date_Date);
 
-         IIC_DS3231_ByteWrite(DS3231_WEEK,Week_Date);
 
-         IIC_DS3231_ByteWrite(DS3231_HOUR,Hour_Date);
 
-         IIC_DS3231_ByteWrite(DS3231_MIN,Min_Date);
 
-         IIC_DS3231_ByteWrite(DS3231_SEC,Sec_Date);
 
-         
 
- }
 
-  
 
- void DS3231_Init(void)                //DS3231初始化
 
- {
 
-         IIC_DS3231_ByteWrite(0x0E,0x40);                //使能1Hz方波,使能振荡器        
 
-         IIC_DS3231_ByteWrite(0x0F,0x00);                //启动振荡器
 
-         Delay_ms(100);    //延时等待完全起振
 
- }