stm32 smbus上不可靠的PEC

stm32 smbus上不可靠的PEC,c,stm32,smbus,C,Stm32,Smbus,STM32 SMBUS上的PEC有问题,我用它从MLX90614红外温度计读取数据。当我启动设备时,所有传输都会设置并继续设置PECERR标志,即使红外温度计的数据似乎是正确的。或者从未设置PECERR,红外温度计的所有数据仍然正确 当我研究示波器上的数据时,我看不到PECERR设置与否时信号之间的差异。如前所述,无论哪种方式,数据似乎都是好的 我当然可以忽略PECERR标志,但我希望能够过滤掉任何最终的乱码传输。有人知道我做错了什么吗 void I2C_SMBUS_Initialize(I2C

STM32 SMBUS上的PEC有问题,我用它从MLX90614红外温度计读取数据。当我启动设备时,所有传输都会设置并继续设置PECERR标志,即使红外温度计的数据似乎是正确的。或者从未设置PECERR,红外温度计的所有数据仍然正确

当我研究示波器上的数据时,我看不到PECERR设置与否时信号之间的差异。如前所述,无论哪种方式,数据似乎都是好的

我当然可以忽略PECERR标志,但我希望能够过滤掉任何最终的乱码传输。有人知道我做错了什么吗

void I2C_SMBUS_Initialize(I2C_TypeDef *h) {
h->CR2 &= ~I2C_CR2_FREQ;                // Clear frequency part of register
h->CR2 |= 0x8;                          // Clock speed in Mhz
h->OAR1 = 0x4000;

h->CCR = 0;
h->CCR &= ~I2C_CCR_DUTY;
h->CCR |= 0x190;

h->TRISE &= ~I2C_TRISE_TRISE;           // Clear TRISE bits
h->TRISE |= 0x9;                        // Set TRISE

h->CR1 |= I2C_CR1_ENPEC;                // Enable packet error check

h->CR1 |= I2C_CR1_SMBTYPE;              // SMBUS host
h->CR1 |= I2C_CR1_SMBUS;                // SMBUS Mode

h->CR1 |= I2C_CR1_PE;  // Start i2c
}

uint16_t I2C_SMBUS_ReadWord(I2C_TypeDef*h,uint8_t设备地址,uint8_t命令){

static const uint16\u t ERROR\u code=0x3BFF;
//静态常数8_t设备地址=0x5A;
静态常数8_t超时=100;
uint16温度=0;
h->CR1&=~I2C\U CR1\U位置;
//生成起始位
sendStartBit(h);
//等待开始位设置
如果(!waitFlag((&h->SR1),I2C_SR1_SB,位设置,超时)){
DEBUG_PUTS(“等待开始位设置时超时”);
返回错误代码;
}
//地址字节。7位。移位一位
发送地址(h,设备地址,I2C_写入);
//等待地址位设置
如果(!waitFlag((&h->SR1),I2C_SR1_ADDR,BIT_SET,timeout)){
DEBUG_PUTS(“等待地址位设置时超时”);
返回错误代码;
}
//清除地址位
clearAddressFlag(h);
sendData(h,命令);
//等待发送缓冲区为空
如果(!waitFlag((&h->SR1),I2C_SR1_TXE,位设置,超时)){
DEBUG_PUTS(“等待缓冲区清空时超时”);
返回错误代码;
}   
uint8_t长度=3;
uint8_t tmpBuffer[长度+1];
memset(tmpBuffer,0x00,4);
//启用自动确认生成
enableAutomaticACK(h);
//生成起始位
sendStartBit(h);
//等待开始位设置
如果(!waitFlag((&h->SR1),I2C_SR1_SB,位设置,超时)){
DEBUG_PUTS(“等待重复启动位设置时超时”);
返回错误代码;
}
//将读取命令发送到从属地址
发送地址(h,设备地址,I2C_读取);
//等待地址位设置
if(!waitFlag((&h->SR1),I2C_SR1_ADDR,位设置,超时)){
DEBUG_PUTS(“等待地址位设置时超时”);
返回错误代码;
}
//通过读取状态寄存器清除ADDR位
clearAddressFlag(h);
//现在我们必须从从从机读取数据
如果(长度>2){
//接收前n-2个字节
对于(uint8_t i=0;iSR1),I2C_SR1_BTF,位_重置,超时)){
DEBUG_PUTS(“等待字节传输准备就绪时超时”);
返回错误代码;
} 
tmpBuffer[i]=h->DR;
//等待字节传输完成
如果(!waitFlag((&h->SR1),I2C_SR1_BTF,位设置,超时)){
DEBUG_PUTS(“等待字节传输完成时超时”);
返回错误代码;
}
}                                                                           
//等待字节传输就绪
如果(!waitFlag((&h->SR1),I2C_SR1_BTF,位_重置,超时)){
DEBUG_PUTS(“等待字节传输准备就绪时超时”);
返回错误代码;
} 
//禁用自动确认生成
失能自动控制(h);
//读取最后的第二个字节
tmpBuffer[length-1]=h->DR;
//发送停止位
发送停止位(h);
//启用数据包错误检查
h->CR1 |=I2C_CR1_PEC;
//读取最后一个字节
tmpBuffer[length]=h->DR;
temp=tmpBuffer[3]*256+tmpBuffer[2];
uint8_t pec=h->SR2&=I2C_SR2_pec_Msk;
如果((h->SR1和I2C_SR1_PECERR)!=0){
看跌期权(“PEC错误”);
}
}
返回温度;

}找到了错误。PECERR必须由软件清除。通电后的第一次传输偶尔会出现故障

    if ((h->SR1 & I2C_SR1_PECERR) != 0) {
        DEBUG_PUTS("PEC ERROR");
        h->SR1 &= ~I2C_SR1_PECERR;
        return ERROR_CODE;
    }
    if ((h->SR1 & I2C_SR1_PECERR) != 0) {
        DEBUG_PUTS("PEC ERROR");
        h->SR1 &= ~I2C_SR1_PECERR;
        return ERROR_CODE;
    }