pic单片机iic的通讯_两个单片机之间的通信

pic单片机iic的通讯_两个单片机之间的通信IIC通信  IIC是一种只需要2根数据线就可以实现数据通信的总线式结构

IIC通信

  IIC是一种只需要2根数据线就可以实现数据通信的总线式结构。IIC采用主从式通信方式,通信过程完全由主设备决定。完整的通信流程是主设备发送起始信号给从设备,再发送地址来选中从设备,然后就可以开始进行数据传输,当传输结束后由主设备发送结束信号告知从设备通信结束。

(示例代码中,PORTA为所用单片机的8位引脚对应的寄存器名称,采用PORTA<7>作为数据位SDA、PORTA<6>作为时钟位SCL)

image-20210915200730739

起始信号

  起始信号由两个下降沿组成,SDA信号先从1置0,然后SCL再从1置0,由此告知从设备要开始通信了。代码如下:

/************************************************************* 启动总线函数 函数原型: void start_i2c(); Function: start on the I2C bus *************************************************************/
void start_i2c()
{ 
   
    PORTA |= 0b10000000; //SDA=1,发送启始条件的数据信号
    delay_10us();
    PORTA |= 0b01000000; //SCL=1
    delay_10us();
    PORTA &= 0b01111111; //SDA=0,发送起始信号
    delay_10us();
    PORTA &= 0b10111111; //SCL=0,钳住I2C总线,准备发送数据或接收数据
    delay_10us();
}

 

终止信号

  起始信号由两个上升沿,SCL信号先从0置1,然后SDA再从0置1,由此告知从设备要结束通信。代码如下:

/************************************************************* 停止总线函数 函数原型: void stop_i2c(); Function: stop the I2C bus **************************************************************/
void stop_i2c()
{ 
   
    PORTA &= 0b01111111; //SDA=0,发送结束条件的数据信号
    delay_10us();
    PORTA |= 0b01000000; //SCL=1
    delay_10us();
    PORTA |= 0b10000000; //SDA=1
    delay_10us();
}

 

发送8位数据

  无论发送地址还是数据,都是通过相同方式一位一位地发送,并且要从高位开始。首先是将时钟线SCL置0,意味着数据线SDA要开始准备信息来发送。

  在每一位数据发送前时钟线都要有一段低电平。当数据线SDA置为要发送的电平后SCl置1,从设备读取此时SDA电平值作为一个bit,随后SCL置0,SDA置为下一个待发送位,重复上述步骤,循环8次即完成一次8bit数据传输。

/*==================================================== 字节数据传送函数 函数原型: void send_byte(uchar c); Function: 将数据C发送出去,可以是地址,也可以是数据,发完后等待回应,并对此状态 位进行操作(不应答或非应答都使ack=0 ),发送数据正常,ack=1;ack=0 表示被控器无应答或损坏。 ====================================================*/
void send_byte(uint8_t c)
{ 
   
    uint8_t bit_count;
    for (bit_count = 0; bit_count < 8; bit_count++)
    { 
   
        if (c & 0x80)
        { 
   
            PORTA |= 0b10000000; //SDA=1
        }
        else
        { 
   
            PORTA &= 0b01111111; //SDA=0
        }
        delay_10us();
        PORTA |= 0b01000000; //SCL=1
        delay_10us();
        PORTA &= 0b10111111; //SCL=0
        c <<= 1;

        delay_10us();
    }
}

 

等待应答

  为了确保从设备收到了主设备发送来的数据,每次发送后主设备都要等待从设备回复ACK信号才能进行后续通话。

  在等待ACK的过程中,主设备要先释放总线SDA,将总线权限交给从设备,即SDA置1。后续如果检测到SDA被置0了就说明从设备答复了ACK信号。

/*==================================================== 等待从设备应答函数 函数原型: void wait_ack(); Function: 等待从设备对主设备发送行为的应答 ====================================================*/
uint8_t wait_ack()
{ 
   
    uint8_t re = 0;

    PORTA |= 0b10000000; //SDA=1,释放总线,将总线权限交给从设备
    delay_10us();
    PORTA |= 0b01000000; //SCL=1
    TRISA = 0b10000000;
    delay_10us();

    if ((PORTA & 0b10000000) == 0)
    { 
   
        re = 1; //ACK
    }
    else
    { 
   
        re = 0; //NACK
    }

    TRISA &= 0b01111111;
    PORTA &= 0b10111111; //SCL=0
    delay_10us();
    return re;
}

 

发送ACK

  主设备发送完数据需要从设备答复ACK信号,而从设备发送给主设备数据后同样需要主设备给其答复ACK信号以确保收到。

/*==================================================== 给从设备发送应答函数 函数原型: void wait_ack(); Function: 给从设备对主设备发送成功接收的应答 ====================================================*/
void send_ack()
{ 
   
    PORTA &= 0b01111111; //SDA=0;
    delay_10us();
    PORTA |= 0b01000000; //SCL=1
    delay_10us();
    PORTA &= 0b10111111; //SCL=0
    delay_10us();
}

 

接收8位数据

  与发送数据时相同,SCL置1表示读取此时SDA电平值作为一个bit,循环8次得到8位数据值。

/*================================================ 字节数据接收函数 函数原型:uchar receive_byte(); FUNCTION: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数。 ====================================================*/
uint8_t receive_byte()
{ 
   
    uint8_t retc = 0;
    PORTA |= 0b10000000; //SDA=1,释放总线,将总线权限交给从设备
    TRISA |= 0b10000000;
    delay_10us();

    uint8_t bit_count;
    for (bit_count = 0; bit_count < 8; bit_count++)
    { 
   
        retc = retc * 2;     //retc<<1
        PORTA &= 0b10111111; //SCL=0
        delay_10us();
        PORTA |= 0b01000000; //SCL=1
        delay_10us();

        if (PORTA & 0b10000000)
        { 
   
            retc++;
        }
        delay_10us();
    }

    TRISA &= 0b01111111;
    PORTA &= 0b10111111; //SCL=0
    delay_10us();

    return (retc);
}

 

通话总程序

  开启通信——>等待应答——>发送地址和传输方向(前7bit为地址,后1bit表示数据方向)——>发送传感器器件配置信息——>等待应答——>再次开启通信——>发送地址和传输方向——>等待应答——>接收数据——>回复ACK——>结束通信

/*==================================================== IIC通话函数 函数原型: void iic_sensor(void); Function: 以IIC协议与温度传感器进行通话,获取温度数据 ====================================================*/
void iic_sensor()
{ 
   
    start_i2c();
    send_byte(0b10010010); //发送地址值,并且设置为输入
    wait_ack();
    send_byte(0x00); //发送配置信息
    wait_ack();

    start_i2c();
    send_byte(0b10010011); //发送地址值,并且设置为输出
    wait_ack();
    temp[1] = receive_byte();
    send_ack();
    temp[0] = receive_byte();
    send_ack();

    stop_i2c(); //通话结束
}

今天的文章pic单片机iic的通讯_两个单片机之间的通信分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/64376.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注