DS3231时钟芯片,驱动时序图,
使用STM32的IIC驱动程序,总是出现读死的情况,改为模拟IIC,需要注意的细节:关于读写的方向的控制位,0读,1写,这一位R/W(1bit)跟slave_address(7bit)组成一个8位数,我开始还纳闷,参考其他人的IIC驱动,怎么没看到单独的控制读写方向的函数,原来合二为一了。哈哈
百度上找的一个程序,稍微改了一点:
#define I2C_SLAVE_ADDRESS_WRITE 0xD0
#define I2C_SLAVE_ADDRESS_READ 0xD1
#define SCL_H GPIO_SetBits(GPIOB, GPIO_Pin_6)
#define SCL_L GPIO_ResetBits(GPIOB, GPIO_Pin_6)
#define SDA_H GPIO_SetBits(GPIOB, GPIO_Pin_7)
#define SDA_L GPIO_ResetBits(GPIOB, GPIO_Pin_7)
#define SCL_read GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6)
#define SDA_read GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)
void I2C_delay(void)
{
u8 i=150; //这里可以优化速度 ,经测试最低到5还能写入
while(i)
{
i--;
}
}
bool I2C_Start(void)
{
SDA_H;
SCL_H;
I2C_delay();
if(!SDA_read)return FALSE; //SDA线为低电平则总线忙,退出
SDA_L;
I2C_delay();
if(SDA_read) return FALSE; //SDA线为高电平则总线出错,退出
SDA_L;
I2C_delay();
return TRUE;
}
void I2C_Stop(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
}
void I2C_Ack(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
void I2C_NoAck(void)
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
bool I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
SCL_L;
return FALSE;
}
SCL_L;
return TRUE;
}
void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
u8 i=8;
while(i--)
{
SCL_L;
I2C_delay();
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
I2C_delay();
SCL_H;
I2C_delay();
}
SCL_L;
}
u8 I2C_ReceiveByte(void) //数据从高位到低位//
{
u8 i=8;
u8 ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
ReceiveByte|=0x01;
}
}
SCL_L;
return ReceiveByte;
}
void I2C_DS3232_ByteWrite(u8 Data, u8 WriteAddr)
{
I2C_Start();
I2C_SendByte(I2C_SLAVE_ADDRESS_WRITE); //ADDRESS
I2C_WaitAck();
I2C_SendByte(WriteAddr); //ADDRESS
I2C_WaitAck();
I2C_SendByte(Data); //ADDRESS
I2C_WaitAck();
I2C_Stop();
}
u8 I2C_DS3232_ByteRead(u8 addr)
{
u8 RTC_data;
I2C_Start();
I2C_SendByte(I2C_SLAVE_ADDRESS_WRITE); //ADDRESS
I2C_WaitAck();
I2C_SendByte(addr); //ADDRESS
I2C_WaitAck();
I2C_Start();
I2C_SendByte(I2C_SLAVE_ADDRESS_READ); //ADDRESS
I2C_WaitAck();
RTC_data=I2C_ReceiveByte();
I2C_NoAck();
I2C_Stop();
return RTC_data;
}
|