CRC в Si7021
- Войдите на сайт для отправки комментариев
Вс, 14/07/2019 - 00:51
Читаю данные из HTU21D(F) Старший байт, Младший байт, СRС. При пересчете CRC выявляется несовпадение суммы.
В прямую считывал с логического анализатора данные, брал из ДШ, ничего совпадает.
К примеру 0x683A, CRC=0x7C, по ДШ. В реальности
Bout[0]=104; Bout[1]=58;Bout[3]=OneWire::crc8(Bout,2);
Serial.print("CRC2 = ");Serial.println(Bout[3], DEC); CRC2 = 236! Должно быть 124! Полином далассовский... Целый день думаю, чего лыжи не едут. Сталкивался кто нибудь с этим?
А почему Bout[3] если длина данных 2 байта?
В Bout[3] записывается CRC предыдущих двух байт.
Пример из интернетов - чтение влажности, температуры и расчет CRC8 для датчика si7021
/* Measurement of relative humidity and temperature using Si7021 */ #include <Wire.h> #define ADDRESS_SI7021 0x40 #define MEASURE_RH_HOLD 0xE5 #define READ_T_FROM_PRE_RH_MEASUREMENT 0xE0 byte buffer[] = {0, 0, 0}; byte crcHumi; word outHumi = 0; int outTemp = 0; unsigned long a, b; void setup(){ Wire.begin(); //TWBR = 12;//400 kHz Serial.begin(9600); } void loop(){ //perform a RH measurement and read back the RH value a = micros(); Wire.beginTransmission(ADDRESS_SI7021); Wire.write(MEASURE_RH_HOLD); Wire.endTransmission(); Wire.requestFrom(ADDRESS_SI7021, 3); if(Wire.available() >= 3){ buffer[0] = Wire.read(); //high byte buffer[1] = Wire.read(); //low byte buffer[2] = Wire.read(); //crc } outHumi = (buffer[0]<<8) | buffer[1]; crcHumi = CRC8(outHumi, buffer[2]); outHumi = word(12500Ul *outHumi /65536 - 600);//целое в сотых % //read temperature from previous RH measurement Wire.beginTransmission(ADDRESS_SI7021); Wire.write(READ_T_FROM_PRE_RH_MEASUREMENT); Wire.endTransmission(); Wire.requestFrom(ADDRESS_SI7021, 2); if(Wire.available() >= 2){ buffer[0] = Wire.read(); //high byte buffer[1] = Wire.read(); //low byte; no crc } outTemp = (buffer[0]<<8) | buffer[1]; outTemp = int(17572L *outTemp /65536 - 4685);//целое в сотых *С //valueHumi = 125.0*outHumi/65536 - 6;//float //valueTemp = 175.72*outTemp/65536 - 46.85;//float b = micros(); Serial.print(float(outHumi) /100); Serial.print(" \%RH\t"); Serial.print(float(outTemp) /100); Serial.println(" C"); Serial.print(buffer[2]);Serial.print(" CRC "); Serial.println(buffer[2],BIN); Serial.print(crcHumi); Serial.print(" crc ");Serial.println(crcHumi, BIN); Serial.println(); // if (crcHumi == 0 && outHumi != 0 && outTemp != 0){ // Serial.println("CRC checked."); // Serial.println(b-a);//19 msec // } // else{ // Serial.println("Error!"); // } delay(1000); } //==HTU21D Humidity Sensor Library By: Nathan Seidle SparkFun Electronics byte CRC8(uint16_t message_from_sensor, uint8_t check_value_from_sensor){ uint32_t remainder = (uint32_t)message_from_sensor << 8; //Pad with 8 bits because we have to add in the check value remainder |= check_value_from_sensor; //Add on the check value uint32_t divsor = (uint32_t)0x988000; for (int i = 0 ; i < 16 ; i++){ //Operate on only 16 positions of max 24. //The remaining 8 are our remainder and should be zero when we're done. if( remainder & (uint32_t)1<<(23 - i) ) //Check if there is a one in the left position remainder ^= divsor; divsor >>= 1; //Rotate the divsor max 16 times so that we have 8 bits left of a remainder } return (byte)remainder; }Спасибо! Как раз такой скетч искал! Сейчас посмотрим, что там в третьем байте пересылается.
Проверил - суммы совпадают, значит, ошибка в моей программе на АСМе. Спасибо!
В Bout[3] записывается CRC предыдущих двух байт.
третий байт массива - это Bout[2], а не Bout[3]
Ага! Рассеянность... Сути несовпадения сумм это не меняет. Запустил прогу - CRC высчитанное и полученное не совпадают. Совпало только в одном месте, именно в него и уткнулся на радостях. CRC считал другой библиотекой.
команда 0xE0 считывает температуру, при которой производилось последнее измерение влажности
Понятно.
Железо -ОК! Может CRC считается как то по другому? Примеры из ДШ тоже не совпадают.
Где читать об остальных командах, не представленных в ДШ?
Все таки косяк в проге на АСМ.
На вход подаётся массив, выловленный из Wire (3 байта) Возвращаемый результат равен нулю при корректном CRC.
#define SHIFTED_DIVISOR 0x988000UL static uint8_t calcSHT2xCRC(uint8_t* _src) { uint32_t remainder = ((uint32_t) _src[0x00] << 16) | ((uint16_t) _src[0x01] << 8) | _src[0x02]); uint32_t divisor = (uint32_t) SHIFTED_DIVISOR; for (uint8_t i = 0x00 ; 0x10 > i ; i++) { if (remainder & ((uint32_t) 0x01 << (0x17 - i))) { remainder ^= divisor; } divisor >>= 1; } //Serial.print("CRC: "); Serial.println((uint8_t) remainder); return (uint8_t) remainder; }Спасибо! Я тоже исследовал, где накосячил. Пишу на АСМе, поэтому Си, немного не в тему, но подход - тот же! необходимо суммировать все ТРИ байта. Буду переделывать. Проверял вручную 100110001 и XOR. На определенных шагах вычислений получался 0.