使用430F5418,通过IO模拟IIC来驱动SHT20温湿度传感器。一直返回不了数据。各位有用过模拟IIC的吗?
#define SHT20ADDR 0x80
#define SHT20_ACK 0
#define SHT20_NACK 1
#define IIC_SDA_OUT P3DIR |= BIT7 //输出模式#define IIC_SDA_IN P3DIR &= ~BIT7 //输入模式
#define IIC_SCL_OUT P5DIR |= BIT4
#define IIC_SCL_IN P5DIR &= ~BIT4
#define IIC_SDA_HIGH P3OUT |= BIT7
#define IIC_SDA_LOW P3OUT &= ~BIT7
#define IIC_SCL_HIGH P5OUT |= BIT4
#define IIC_SCL_LOW P5OUT &= ~BIT4
#define IIC_SDA_READ P3IN&0x80
#define IIC_SCL_READ P5IN&0x10
void delay(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++)
{for(j=0;j<200;j++)
{;}}
}
void I2CInit(void)
{
IIC_SDA_OUT;
IIC_SCL_OUT; IIC_SDA_LOW;
IIC_SCL_LOW;
__delay_cycles(10);
IIC_SDA_HIGH;
IIC_SCL_HIGH;
__delay_cycles(80);
}
void I2CStart(void)
{ IIC_SDA_OUT;
IIC_SCL_OUT; IIC_SDA_HIGH; //发送起始条件的数据信号
IIC_SCL_HIGH;
IIC_SDA_LOW; //发送起始信号
__delay_cycles(5); //起始条件锁定时间大于4μs
IIC_SCL_LOW; //钳住I2C总线,准备发送或接收数据
__delay_cycles(5);}
void I2CStop(void)
{ IIC_SDA_OUT;
IIC_SCL_OUT;
IIC_SDA_LOW; //发送结束条件的数据信号–ZLG
IIC_SCL_LOW;
IIC_SCL_HIGH; //发送结束条件的时钟信号–ZLG
__delay_cycles(5); //结束条件建立时间大于4μs–ZLG
IIC_SDA_HIGH; //发送I2C总线结束信号–ZLG
__delay_cycles(5);
}
unsigned char I2C_Read_Byte(unsigned char ack)
{
unsigned char mask,RDByte=0;
IIC_SDA_OUT;
IIC_SCL_OUT; IIC_SDA_HIGH; for(mask=0x80; mask>0; mask>>=1) { IIC_SCL_HIGH; __delay_cycles(4);
IIC_SDA_IN;
if(IIC_SDA_READ == 1) {
RDByte = RDByte|mask;
}
IIC_SCL_LOW;
__delay_cycles(1);
} IIC_SDA_OUT;
if(ack ==1){
IIC_SDA_HIGH;
}else{
IIC_SDA_LOW;
}
__delay_cycles(1);
IIC_SCL_HIGH; __delay_cycles(5);
IIC_SCL_LOW;
IIC_SDA_HIGH;
__delay_cycles(20);
return RDByte;
}
unsigned char I2C_Write_Byte(unsigned char byte){
unsigned char mask,error=0; IIC_SDA_OUT;
IIC_SCL_OUT;
for(mask=0x80; mask>0; mask>>=1) { if(mask&0x80) {
IIC_SDA_HIGH; }
else
{
IIC_SDA_LOW;
}
__delay_cycles(1); IIC_SCL_HIGH; __delay_cycles(5); IIC_SCL_LOW;
__delay_cycles(1);
} IIC_SDA_HIGH;
IIC_SCL_HIGH; __delay_cycles(1);
IIC_SDA_IN; if(IIC_SDA_READ == 1) error= 1; IIC_SCL_LOW;
__delay_cycles(20);
return error;
}
void SET_Resolution(void){
I2CStart(); //Start I2C if(I2C_Write_Byte(SHT20ADDR&0xfe)==0) //I2C address + write + ACK
{
if(I2C_Write_Byte(0xe6)==0) //写用户寄存器
{ if(I2C_Write_Byte(0x83)==0); //设置分辨率 11bit RH% 测量时间:12ms(typ.) & 11bit T℃ 测量时间:9ms(typ.) }
}
I2CStop(); //Stop I2C}
float SHT2x_MeasureTempHM(void)
{
float TEMP;
unsigned char tmp1, tmp2;
unsigned int ST,i;
IIC_SCL_OUT;
I2CStart(); I2C_Write_Byte(0x80);
I2C_Write_Byte(0xE3);
I2CStart();
I2C_Write_Byte(0x81);
IIC_SCL_HIGH;
IIC_SCL_IN;
for(i=0;i<1000;i++)
{
__delay_cycles(10);
if(IIC_SCL_READ==1)break;
}
tmp1 = I2C_Read_Byte(0);
tmp2 = I2C_Read_Byte(0);
I2CStop();
ST = (tmp1 << 8) | (tmp2 << 0);
ST &= ~0x0003;
TEMP = ((float)ST * 0.00268127) – 46.85;
IIC_SCL_OUT;
return (TEMP);}
Maka Luo:
__delay_cycles(5); //起始条件锁定时间大于4μs
这个是Delay 5时钟周期,主频跑多少,可能这个延时不够。
Tony Lii:
回复 Maka Luo:
修改了延时,能正常工作了。多谢!!
灰小子:
回复 Maka Luo:
调试这类通讯的时候,建议用逻辑分析仪或者示波器抓取时序,与手册里要求的时序对比。这让会比较容易调
tenghui zhang:
楼主怎么解决的?求帮
灰小子:
回复 tenghui zhang:
hi tenghui zhang,
楼主调整的通讯时序