IIC通信
IIC是一种只需要2根数据线就可以实现数据通信的总线式结构。IIC采用主从式通信方式,通信过程完全由主设备决定。完整的通信流程是主设备发送起始信号给从设备,再发送地址来选中从设备,然后就可以开始进行数据传输,当传输结束后由主设备发送结束信号告知从设备通信结束。
(示例代码中,PORTA为所用单片机的8位引脚对应的寄存器名称,采用PORTA<7>作为数据位SDA、PORTA<6>作为时钟位SCL)
起始信号
起始信号由两个下降沿组成,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