Files
TXH1.0/User/DS1307/DS1307.c
T
2026-04-27 16:55:02 +08:00

243 lines
7.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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时,读之后发送ACKack=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(); //产生一个停止条件
}