软件模拟I2C

硬件电路

1、设备的SCL SDA均设置成开漏输出模式(高:断开,低:接地)(防止在SDA线上一个输出高电平,一个输出低电平导致短路)

2、SCL与SDA各添加上拉电阻(弱上拉)

//开漏输出模式需要输入时,先输出1,再读取输入寄存器就可以了。

函数改写:

#define PORT_SCL GPIOB
#define PIN_SCL GPIO_Pin_10
#define PORT_SDA GPIOB
#define PIN_SDA GPIO_Pin_11
void SCL_W(uint8_t Bitvalue){
    GPIO_WriteBit(PORT_SCL ,PIN_SCL ,(BitAction)Bitvalue);
    Delay_us(10);//此处延时时长看具体挂载外设而定
}
void SDA_W(uint8_t Bitvalue){
    GPIO_WriteBit(PORT_SDA ,PIN_SDA ,(BitAction)Bitvalue);
    Delay_us(10);
}
uint8_t SDA_R(void){
    uint8_t Bitvalue;
    Bitvalue = GPIO_ReadInputDataBit(PORT_SDA ,PIN_SDA );
    Delay_us(10);
    return Bitvalue;
}

待机状态:

SCL与SDA都处于高电平(即处于断开状态)

起始终止条件:

SCL处于高电平期间,SDA的电平发生变化,(起始:高->低,终止:低->高),

起始终止代码:

void I2C_Start_rw(void){
    SDA_W(1);
    SCL_W(1);
    SDA_W(0); //SCL处于高电平时,SDA由高->低
    SCL_W(0); //这一步的作用是让除了起始和终止条件,每个时序都是让SCL以低电平开始,低电平结束。
}
void I2C_Stop_rw(void){
    SDA_W(0);
    SCL_W(1);
    SDA_W(1); //SCL处于高电平时,SDA由低->高
}

发送一个字节:

在SCL低电平期间,主机以高位先行的形式依次将数据发送到SDA数据线上,从机在SCL高电平期间读取数据位(一般在其上升沿期间读取)

void I2C_SendByte_rw(uint8_t Byte){
    uint8_t i;
    for(i=0;i<8;i++){
        SDA_W(Byte & (0x80>>i));
        SCL_W(1);
        SCL_W(0);}
}

接收一个字节:

主机在接收之前,释放SDA(即SDA_W(1)),在SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),主机在SCL高电平期间读取数据位。

uint8_t I2C_ReceiveByte_rw(void){
    uint8_t i;
    uint8_t Byte = 0;
    for(i=7;i>=0;i--){    
        SDA_W(1);
        SCL_W(1);
        Byte |= (SDA_R()<<i);
        SCL_W(0);}
    return Byte;
}

发送应答与接收应答

发送应答:主机接收完一个字节后,在下一个时钟发送单个数据,0表示应答,1表示非应答。

void I2C_SendAck_rw(uint8_t AckBit){
    SDA_W(AckBit);
    SCL_W(1);
    SCL_W(0);
}
uint8_t  I2C_ReceiveAck_rw(void){
    uint8_t AckBit = 0; 
    SDA_W(1);
    SCL_W(1);
    AckBit = SDA_R();
    SCL_W(0);
    return AckBit;
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值