标题 STM32 模拟IIC驱动MS5607调试记录
因项目需求,需使用MS5607的作为检测气压,再此写下自己遇见的问题以及调试记录。
硬件原理图如下:
IIC接口总线使用了气压传感器,SHT35温度传感器,调试MS5607硬件的7位地址是0X76。所以写的地址是0xEC,读操作的地址是0XED.
在第一次写数据的时候MCU无法得到ACK回应,最后查到的问题是地址错误导致的无回馈信号,在发送正确的时序图如下:
MS5607操作指令:
复位指令:
void MS5607BA_Reset(void)//复位
{
u8 err=0;
IIC_Start();
IIC_Send_Byte(MS5607BA_ADR_Write);
err = IIC_Wait_Ack();
IIC_Send_Byte(MS5607BA_RESET);//Send Reset CMD
err = IIC_Wait_Ack();
IIC_Stop();
delay_ms(200);
}
获得ADC读取的数字的值
void MS5607_Send_CMD(u8 command)
{
u8 err=0;
IIC_Start();
IIC_Send_Byte(MS5607BA_ADR_Write);//发送器件地址
err = IIC_Wait_Ack();
IIC_Send_Byte(command);//Prom Read CMD
err = IIC_Wait_Ack();
IIC_Stop();
}
void MS5607_ADC_Answer(u8 *Data)
{
u8 err=0;
IIC_Start();
IIC_Send_Byte(MS5607BA_ADR_Read);//发送器件地址
err = IIC_Wait_Ack();
*Data++=IIC_Read_Byte(1);
*Data++=IIC_Read_Byte(1);
*Data=IIC_Read_Byte(0);
IIC_Stop();
}
读取PRPM 0xa0 —0xae
void MS5607BA_readPROM(void)
{
uint16_t value=0;u8 Promdata[2]={0};
u8 i;
u8 err=0;
u8 Read_CMD=Prom_Read_CMD;
for(i=0;i<8;i++)
{
/*********CMD to read Memory address****************/
IIC_Start();
IIC_Send_Byte(MS5607BA_ADR_Write);//发送器件地址
err = IIC_Wait_Ack();
IIC_Send_Byte(Read_CMD);//Prom Read CMD
err = IIC_Wait_Ack();
IIC_Stop();
/*****Answer from MS5607-02********/
IIC_Start();
IIC_Send_Byte(MS5607BA_ADR_Read);//发送器件地址
err = IIC_Wait_Ack();
Promdata[0] = IIC_Read_Byte(1);
Promdata[1] = IIC_Read_Byte(0);
IIC_Stop();
Cal_C[i]=Promdata[0]<<8|Promdata[1];//Read PromData Storage Value Cal_C
Read_CMD+=2; //Read Next Promdata CMD
}
printf("\n The MS561101BA is reading PROM : \r\n"); // printf("\r\nC1 = %d\r\nC2 = %d\r\nC3 = %d\r\nC4 = %d\r\nC5 = %d\r\nC6 = %d\r\n",temp1[1],temp1[2],temp1[3],temp1[4],temp1[5],temp1[6]);
}
读取D1值
u32 MS5607BA_Conversion_GetPressure(void)
{
u8 Press_Temp[3]={0};
u32 D1_PessTmp=0;
MS5607_Send_CMD(MS5607BA_D1_OSR_4096);
delay_ms(50);
MS5607_Send_CMD(MS5607BA_ADC_READ);
delay_ms(50);
MS5607_ADC_Answer(Press_Temp);
delay_ms(50);
D1_PessTmp= Press_Temp[0]<<16| Press_Temp[1]<<8|Press_Temp[2];
return D1_PessTmp;
}
读取D2 温度的数字值
u32 MS5607BA_Conversion_Temp(void)
{
u8 Tempbuf[3]={0};
u32 D2_Data;
MS5607_Send_CMD(MS5607BA_D2_OSR_4096);
delay_ms(50);
MS5607_Send_CMD(MS5607BA_ADC_READ);
delay_ms(50);
MS5607_ADC_Answer(Tempbuf);
delay_ms(50);
D2_Data= Tempbuf[0]<<16| Tempbuf[1]<<8|Tempbuf[2];
return D2_Data;
}
计算温度
char MS5607_GetTemperature (void) //计算温度
{
D2_Temp = MS5607BA_Conversion_Temp(); //循环读取 温度
if(D2_Temp == 0)
return 0;
delay_ms ( 20 );
if(D2_Temp > ( ( uint32_t ) Cal_C[5] * (0x00000001 << 8) ))
dT = D2_Temp - ( ( uint32_t ) Cal_C[5] * (0x00000001 << 8) ); //公式 dT = D2 - TREF = D2 - C5 * 2^8
else
{
dT = ( ( uint32_t ) Cal_C[5] * (0x00000001 << 8) ) - D2_Temp;
dT *= -1;
}
Temperature = 2000 + (( dT * Cal_C[6] ) / (0x00000001 << 23)); //算出温度值的100倍,2001表示20.01° 公式TEMP =20°C + dT * TEMPSENS =2000 + dT * C6 / 2^23
if(Temperature<-4000) Temperature=-4000;
if(Temperature>8500) Temperature=8500;
return 1;
}
计算温度补偿压力
char MS5607_GetPressure (void) //计算温度补偿压力
{
D1_Pess = MS5607BA_Conversion_GetPressure(); //循环读取 D1 D2
if(D1_Pess == 0)
return 0;
delay_ms ( 20 );
OFF = ( ( float)Cal_C[2] * (0x00000001 << 17) ) + ( ( float ) Cal_C[4] * dT ) / 64.0; //公式 OFF = OFFT1 + TCO *dT = C2 *2^17 +(C4 *dT )/ 2^6
SENS = ( ( float ) Cal_C[1] * (0x00000001 << 16) ) + ( ( float ) Cal_C[3] * dT ) / 128.0; //公式SENS = SENST1 + TCS* dT= C1 * 2^16 + (C3 * dT )/ 2^7
//温度补偿部分 逻辑看芯片手册
if ( Temperature < 2000 ) // second order temperature compensation when under 20 degrees C
{
T2 = ( dT * dT ) / (( u32 )0x0000000001 << 31);
OFF2 = 61 * (( Temperature - 2000 ) * ( Temperature - 2000 )) / 16;
SENS2 = 2 * (( Temperature - 2000 ) * ( Temperature - 2000 )) ;
if ( Temperature < -1500 )
{
OFF2 = OFF2 + 15 * (( Temperature + 1500 ) * ( Temperature + 1500 )) ;
SENS2 = SENS2 + 8 * (( Temperature + 1500 ) * ( Temperature + 1500 )) ;
}
}
else //(Temperature > 2000)
{
T2 = 0;
OFF2 = 0;
SENS2 = 0;
}
Temperature = Temperature - T2;
OFF = OFF - OFF2;
SENS = SENS - SENS2;
Press = ( D1_Pess * SENS / (0x00000001 << 21) - OFF ) / (0x00000001 << 15); //公式 P = D1 * SENS - OFF = (D1 * SENS / 2^21 - OFF) / 2^15
MS5607TempPress.Pressure=(float)Press/100;//单位 mbar
MS5607TempPress.Temperature=(float)Temperature/100;//单位 ℃
if(MS5607TempPress.Temperature<-40)MS5607TempPress.Temperature=-40;
if(MS5607TempPress.Temperature>85) MS5607TempPress.Temperature=85;
if(MS5607TempPress.Pressure<10) MS5607TempPress.Pressure=10;
if(MS5607TempPress.Pressure>1200) MS5607TempPress.Pressure=1200;
return 1;
}
开始的时候全速运行的时候读数有问题,最后发现两个命令之间时间太短没有延迟时间,单步调试时好的。在进行修改了延迟时间后全速运行是可行的,在折腾了一天后终于可以检测到温度压力以及湿度的值。
温湿度以及气压的值如下变量的所示: