IIC输出是开漏输出,所以在SCL和SDA两个引脚上必须接上上拉电阻
IIC总线需要在发送了地址之后必须发送
模拟发送数据函数如下:
void iic_sendid(uint8_t id,IIC_DIRECTION direction){
uint8_t m;
uint8_t j;
id<<=1;
for(j=0;j<7;j++)
{
m=id;
GPIO_Pin_Clear(iic_SCLK);
m=m&0x80;
if(m==0x80)
{
GPIO_Pin_Set(iic_SDA);
}
else
{
GPIO_Pin_Clear(iic_SDA);
}
id=id<<1;
GPIO_Pin_Set(iic_SCLK);
}
GPIO_Pin_Clear(iic_SCLK);
if(direction==iic_write) GPIO_Pin_Clear(iic_SDA);
else GPIO_Pin_Set(iic_SDA);
GPIO_Pin_Set(iic_SCLK);
GPIO_Pin_Clear(iic_SCLK); //应答
GPIO_Pin_Set(iic_SDA); //可以查看有没有应答
GPIO_Pin_Set(iic_SCLK);
GPIO_Pin_Clear(iic_SCLK); //注意这里必须要再次清除掉SCLK 否则的话设备就会认为还没有到响应结束,那么就造成了当再次开始时第一个时钟就会被认为是应答结束时钟
}
注意上面的注释,很关键
/*
IIC开始函数 时序开始 产生停止位
*/
void start(void)
{
GPIO_Pin_Set(iic_SDA);
GPIO_Pin_Set(iic_SCLK);
GPIO_Pin_Clear(iic_SDA);
GPIO_Pin_Clear(iic_SCLK);
}
/*
IIC停止函数 产生停止位
*/
void stop(void)
{
GPIO_Pin_Clear(iic_SCLK);
GPIO_Pin_Clear(iic_SDA);
GPIO_Pin_Set(iic_SCLK);
GPIO_Pin_Set(iic_SDA);
}
注意开始函数和停止函数的顺序,很关键
硬件IIC要求从设备必须有应答能力
如果从设备没有应答能力,也可以说硬件IIC必须要有负载设备,那么IIC硬件将会在传输完第一个直接(设备地址)后断开传输:
IIC在多字节的读取的时候必须要正确的给出应答
IIC在多字节的读取也就是主机作为数据的接收端,这时候从设备要判断发送的数据时候正确,所以主机在完全接收到一个字节之后必须要给予正确的应答,比如KX022的手册要求的时序如下:
当在接收到一个data(第一个DATA)后如果主机不给应答,那么通讯很有可能会出现错误,造成的现象有可能是在接下来的传输里,从机一直拉低SDA数据线