打印

STM32模拟IIC驱动时钟程序

[复制链接]
2394|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
TataJen|  楼主 | 2014-9-28 16:34 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式




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;
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

126

帖子

6

粉丝