2018-02-25 02:10 AM
Hello friend,
I have DS18B20. And I read his uniq ID with CRC.
And I know, that STM has crc calculator.
So I read data from DS18B20:
CRC 0x92
And I use internal calculator on this datas.
But result is wrong, because I get:
0x19
And you can see 0x92 is different from 0x19.
For example:
read ID with CRC.
uint8_t *p = ds18b20_read_serial_number();
And CRC calculation:
uint8_t test_crc = CRC_Calculate8(p, 8, 1);
Any idea, what is wrong?
Here is function to calc CRC in STM32F767zi.
uint32_t CRC_Calculate8(uint8_t* arr, uint32_t count, uint8_t reset)
{ /* Reset CRC data register if necessary */ if (reset) { /* Reset generator */ LL_CRC_ResetCRCCalculationUnit(CRC); //CRC->CR = CRC_CR_RESET; }/* Calculate CRC */
while (count--) { /* Set new value */ LL_CRC_FeedData8(CRC, *arr++); //CRC->DR = *arr++; }/* Return data */
return LL_CRC_ReadData8(CRC); //CRC->DR;}#crc2018-02-25 02:51 AM
They use a different polynomial, width or shift direction?
2018-02-25 02:53 AM
Ok. And can I recalculate to good value (for example some mask)?
Or I must sw calculating?2018-02-25 07:34 AM
The hardware might be able to do it, but you likely spend as much time setting things up as doing the computation.
Here is an efficient 4-bit table implementation in software
// Dallas 1-Wire CRC Test App -
mailto:sourcer32@gmail.com
// x^8 + x^5 + x^4 + 1 0x8C (0x131)
// Right Shift// Initialized to Zerouint8_t Crc8CQuick(uint8_t Crc, int Size, uint8_t *Buffer)
{ static const uint8_t CrcTable[] = { // Nibble table for polynomial 0x8C0x00,0x9D,0x23,0xBE,0x46,0xDB,0x65,0xF8, //
mailto:sourcer32@gmail.com
0x8C,0x11,0xAF,0x32,0xCA,0x57,0xE9,0x74 };while(Size--)
{ Crc ^= *Buffer++; // Apply Data Crc = (Crc >> 4) ^ CrcTable[Crc & 0x0F]; // Two rounds of 4-bits Crc = (Crc >> 4) ^ CrcTable[Crc & 0x0F]; }return(Crc);
}uint8_t Crc8CSlow(uint8_t Crc, int Size, uint8_t *Buffer)
{ int i;while(Size--)
{ Crc ^= *Buffer++; // Apply Data for (i=0; i<8; i++) // 1-bit at a time if (Crc & 0x01) Crc = (Crc >> 1) ^ 0x8C; // Polynomial used in Dallas 1-Wire else Crc = (Crc >> 1); }return(Crc);
}void test(void)
{ uint8_t data[] = { // Supplied Test Data Vector 0xab,0x01,0x4b,0x46,0x7f,0xff,0x05,0x10 }; // 0x92printf('%02X test\n', Crc8CQuick(0x00, sizeof(data), data));
printf('%02X test\n', Crc8CSlow(0x00, sizeof(data), data));}Sorry about the formatting, will post a formatted version below but it will sit in moderation for a while.
Edit: Pastes better in FireFox than Chrome, will try a LL implementation later
2018-02-25 07:41 AM
I thought so. So I calculate CRC with the same result with this function:
♯ define CRC8INIT 0x00
♯ define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0uint8_t ds18b20_crc8( uint8_t *data, uint16_t number_of_bytes_in_data )
{ uint8_t crc; uint16_t loop_count; uint8_t bit_counter; uint8_t b; uint8_t feedback_bit;crc = CRC8INIT;
for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++)
{ b = data[loop_count];bit_counter = 8;
do { feedback_bit = (crc ^ b) & 0x01;if ( feedback_bit == 0x01 )
{
crc = crc ^ CRC8POLY; } crc = (crc >> 1) & 0x7F; if ( feedback_bit == 0x01 ){
crc = crc | 0x80; }b = b >> 1;
bit_counter--;} while (bit_counter > 0);
}
return crc;
}2018-02-25 07:47 AM
I think my implementation will spank that for speed
Even the slower serial version I have will be faster and smaller
uint8_t Crc8CSlow(uint8_t Crc, int Size, uint8_t *Buffer)
{ int i;while(Size--)
{ Crc ^= *Buffer++; // Apply Data for (i=0; i<8; i++) // 1-bit at a time if (Crc & 0x01) Crc = (Crc >> 1) ^ 0x8C; // Polynomial used in Dallas 1-Wire else Crc = (Crc >> 1); }return(Crc);
}2018-02-25 07:55 AM
// Dallas 1-Wire CRC Test App - sourcer32@gmail.com
// x^8 + x^5 + x^4 + 1 0x8C (0x18C)// Right Shift// Initialized to Zerouint8_t Crc8CQuick(uint8_t Crc, int Size, uint8_t *Buffer){ static const uint8_t CrcTable[] = { // Nibble table for polynomial 0x8C 0x00,0x9D,0x23,0xBE,0x46,0xDB,0x65,0xF8, // sourcer32@gmail.com 0x8C,0x11,0xAF,0x32,0xCA,0x57,0xE9,0x74 }; while(Size--) { Crc ^= *Buffer++; // Apply Data Crc = (Crc >> 4) ^ CrcTable[Crc & 0x0F]; // Two rounds of 4-bits Crc = (Crc >> 4) ^ CrcTable[Crc & 0x0F]; } return(Crc);}uint8_t Crc8CSlow(uint8_t Crc, int Size, uint8_t *Buffer){ int i; while(Size--) { Crc ^= *Buffer++; // Apply Data for (i=0; i<8; i++) // 1-bit at a time if (Crc & 0x01) Crc = (Crc >> 1) ^ 0x8C; // Polynomial used in Dallas 1-Wire else Crc = (Crc >> 1); } return(Crc);}void test(void){ uint8_t data[] = { // Supplied Test Data Vector 0xab,0x01,0x4b,0x46,0x7f,0xff,0x05,0x10 }; // 0x92 printf('%02X test\n', Crc8CQuick(0x00, sizeof(data), data)); printf('%02X test\n', Crc8CSlow(0x00, sizeof(data), data));}�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
2018-02-25 08:04 AM
// Dallas 1-wire CRC using STM32 hardware on models supporting user defined settings
// Bit more hacky than I'd like, rough framework lifted from// STM32Cube_FW_F7_V1.8.0\Projects\STM32F767ZI-Nucleo\Examples_LL\CRC\CRC_UserDefinedPolynomial// CliveOne -
mailto:sourcer32@gmail.com
#include 'stm32f7xx_ll_bus.h'
#include 'stm32f7xx_ll_crc.h'#define CRC8_POLYNOMIAL_VALUE 0x31 // 0x8C poly reversed (STM32 left shifts)
/* Test vector */
static const uint8_t aDataBuffer[] = {
0xab,0x01,0x4b,0x46,0x7f,0xff,0x05,0x10 }; // 0x92/* Expected CRC Value */
uint8_t ubExpectedCRCValue = 0x92;/* Used for storing CRC Value */
uint8_t ubCRCValue = 0;/**
* @brief This function configures CRC Instance. * @note This function is used to : * -1- Enable peripheral clock for CRC. * -2- Configure CRC functional parameters. * @note Peripheral configuration is minimal configuration from reset values. * Thus, some useless LL unitary functions calls below are provided as * commented examples - setting is default configuration from reset. * @param None * @retval None */void Configure_CRC(void){ /* (1) Enable peripheral clock for CRC *********************/ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_CRC);/* (2) Configure CRC functional parameters ********************************/
/* Configure CRC calculation unit with user defined polynomial value, 8-bit long */
LL_CRC_SetPolynomialCoef(CRC, CRC8_POLYNOMIAL_VALUE); LL_CRC_SetPolynomialSize(CRC, LL_CRC_POLYLENGTH_8B); LL_CRC_SetInitialData(CRC, 0); // ZERO LL_CRC_SetInputDataReverseMode(CRC, LL_CRC_INDATA_REVERSE_WORD); // STM32 backward LL_CRC_SetOutputDataReverseMode(CRC, LL_CRC_OUTDATA_REVERSE_BIT); // reverse bit order on read}/**
* @brief This function performs CRC calculation on BufferSize bytes from input data buffer aDataBuffer. * @param BufferSize Nb of bytes to be processed for CRC calculation * @retval 8-bit CRC value computed on input data buffer */uint8_t Calculate_CRC(uint32_t BufferSize, uint8_t *Buffer){ register uint32_t data = 0; register uint32_t index = 0;/* Compute the CRC of Data Buffer array*/
for(index=0; index < (BufferSize / 4); index++) { data = (uint32_t)((Buffer[4 * index + 3] << 24) | (Buffer[4 * index + 2] << 16) | (Buffer[4 * index + 1] << 8) | Buffer[4 * index]); LL_CRC_FeedData32(CRC, data); }/* Last bytes specific handling */
if ((BufferSize % 4) != 0) { if (BufferSize % 4 == 1) { LL_CRC_FeedData8(CRC, Buffer[4 * index]); } if (BufferSize % 4 == 2) { LL_CRC_FeedData16(CRC, (uint16_t)((Buffer[4 * index + 1]<<8) | Buffer[4 * index])); } if (BufferSize % 4 == 3) { LL_CRC_FeedData16(CRC, (uint16_t)((Buffer[4 * index + 1]<<8) | Buffer[4 * index])); LL_CRC_FeedData8(CRC, Buffer[4 * index + 2]); } }/* Return computed CRC value */
return(LL_CRC_ReadData8(CRC));}/**
* @brief Check CRC computation result value. * @param None * @retval None */void CheckCRCResultValue(void){ printf('CRC:%02X (%02X)\n', ubCRCValue, ubExpectedCRCValue);/* Compare the CRC value to the Expected one */
if (ubCRCValue != ubExpectedCRCValue) puts('CRC **FAILED**'); else puts('CRC Passed');}void Test(void)
{ /* Configure CRC (CRC IP configuration using user-defined Polynomial value) */ Configure_CRC();/* Perform CRC calculation on data contained in aDataBuffer */
ubCRCValue = Calculate_CRC(sizeof(aDataBuffer), aDataBuffer);/* Check if CRC computed result value is equal to expected one */
CheckCRCResultValue();}2018-02-25 09:23 AM
It is look like fantastic.
I'm trying it tomorrow. Thank you.
i forgot to examples in CubeMX.
2018-02-25 09:36 AM
The HAL/Cube examples for the LL are pretty sparse. The above could be coded more efficiently.
I built the test framework on an STM32F746G-DISCO