STM32-I2C基础代码原理介绍

在之前我们已经编写了关于SPI, I2C, CAN等通信方式的笔记,在此就不再次单独介绍I2C的通讯原理了,参考链接如下:

http://t.csdn.cn/bz9c1

--------------------------------------------------------------------------------------------------------------

简单介绍起始信号和结束信号发送原理:当时钟线处于高电平的时候,把数据线从空闲状态的高电平(由上拉电阻造成)拉低,形成一个下降沿触发信号,这就是起始信号;反之,当时钟线处于高电平的时候,把数据线从忙时的低电平信号拉高,形成一个上升沿触发信号,这就是结束信号。

首先是我们的起始信号和停止信号函数:

void iic_start(void){
    //SCL为高电平时,SDA从高电平向低电平跳变,制造起始信号
    IIC_SDA(1);
    IIC_SCL(1);
    delay_ms();
    IIC_SDA(0);
    delay_ms();
    IIC_SCL(0);
    delay_ms();//钳住总线,准备发送或者接受数据
}

void iic_stop(void){
    //SCL为高电平的适合,SDA从低电平向高电平跳变,制造停止信号
    IIC_SDA(0);
    delay_ms();
    IIC_SCL(1);
    delay_ms();
    IIC_SDA(1);
    delay_ms();
}

简单介绍ACK的应答信号原理:主机数据线拉高,表示一个高电平的状态,而此时如果从机发送一个低电平信号时,主机的高电平就会被导入到从机的低电平中,从而使得主机得数据线读取PIN值的函数读取到的是低电平,表示收到ACK应答信号,继续传输数据;反之,如果从机继续发送上拉电阻的高电平,则主机的数据线将保持高电平状态,主机数据线PIN值读取函数读取到的是高电平,表示读取到的是NACK非应答信号,不再发送数据,发送结束信号结束此次IIC通讯传输。

接下来对应答信号做出相应反应的函数:

uint8_t iic_wait_ack(void){ //主机检测应答信号

    IIC_SDA(1); //主机释放SDA线
    delay_ms();
    IIC_SCL(1); //从机返回ACK
    delay_ms();

    if(IIC_READ_SDA){ //SDA高电平表示读取到高电平,从机未作出应答,由于上拉电阻有高电平阻塞效果,表示读取到非应答信号
        iic_stop();
        return 1;
    }

    IIC_SCL(0);
    delay_ms();
    return 0;
}

void iic_ack(void){ //从机发送低电平应答信号,将主机发送的高电平信号导入至此,使主机的数据线检测函数得到的是低电平,继续要求数据

    IIC_SCL(0);
    delay_ms();
    IIC_SDA(0);
    delay_ms();
    IIC_SCL(1);
    delay_ms();
}

void iic_nack(void){ //从机发送非应答信号,不再要求数据

    IIC_SCL(0);
    delay_ms();
    IIC_SDA(1);
    delay_ms();
    IIC_SCL(1);
    delay_ms();
}

接下来简单介绍数据发送的原理:由于I2C通讯是MSB first通讯,先发送最高位的数据,于是我们可以通过左移位移操作来实现数据的不断读取。

void iic_send_byte(uint8_t data){
    for(uint8_t t = 0; t < 8; t++){
        //高位先发
        IIC_SDA((data & 0x80) >> 7);
        IIC_SCL(1);
        delay_ms();
        IIC_SCL(0);
        data <<= 1; //左移一位,进行下一次发送
    }
    IIC_SDA(1); //完成后,释放数据线,进行应答检测
}

uint8_t iic_read_byte(uint8_t ack){
    uint8_t receive = 0;

    for(uint8_t i = 0; t < 8; t++){
        //高位先被输入,左移以腾空右边的位置给下一低位数据
        receive <<= 1;
        IIC_SCL(1);
        delay_ms();
        if(IIC_READ_SDA) receive++;
        IIC_SCL(0);
        delay_ms();
    }
    if(!ack) iic_nack();
    else iic_ack();
    return receive;
}

以上就是I2C通讯方式中比较基础的一些操作。

你可能感兴趣的:(stm32,stm32,单片机,嵌入式硬件)