kl3m3n's blog

Community Browser
cancel
Showing results for 
Search instead for 
Did you mean: 

Re: Serial data send with CRC (cyclic redundancy check) - Labview and Arduino/ARM

Klemen
Active Participant

Hello,

today I am posting a full example on how to receive data in Labview that is sent from a microcontroller. The microcontroller I used for testing was Arduino Uno (the posted code reflects this), but in case anyone wants to use ARM based microcontroller (STM32 line, ARM Cortex-M) please let me know and I will update the code.

The microcontroler sends random byte data to the serial port and also calculates a 2 byte CRC which is appended after the end of each data package. Of course, the data sent can be anything - for example, the data read from an arbitrary sensor. You can modifiy the number of bytes sent and the number of bytes that are used to signal the data end (for explanation, see the full code below):


class GenerateAndSend {

  public:

    uint8_t data;

    uint16_t crc_16;

    static const uint8_t streamEnd;

  public:

    GenerateAndSend(void);

    ~GenerateAndSend(void);

    void Reset(void);

    void GenerateDataAndSend(uint8_t downLimit, uint8_t upLimit);

    void SendEnd(void);

    void SendCRC(void);

    void CalculateCRC(uint16_t *pcrc, uint8_t *pdata);

};

const uint8_t GenerateAndSend::streamEnd(255);

GenerateAndSend::GenerateAndSend(void) { 

}

GenerateAndSend::~GenerateAndSend(void) {

}

void GenerateAndSend::Reset(void) {

  crc_16 = 0xFFFF; 

}

void GenerateAndSend::GenerateDataAndSend(uint8_t downLimit, uint8_t upLimit) {

  data = (byte) random(downLimit, upLimit);

  Serial.write(data);

}

void GenerateAndSend::SendEnd(void) {

   Serial.write(streamEnd); 

}

void GenerateAndSend::SendCRC(void) {

  uint8_t *pcrc_16 = (uint8_t*) &crc_16;

  for(uint16_t i=0;i<2;i++,pcrc_16++) {

    Serial.write((*pcrc_16));

  }

}

void GenerateAndSend::CalculateCRC(uint16_t *pcrc, uint8_t *pdata) {

  // Fast (LUT) CRC16 calculation update (one call, one byte)

  // Byte table 0xA001 polynomial   

  static const uint16_t crc16_tbl[] = {0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,

                       0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,

                       0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,

                       0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,

                       0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,

                       0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,

                       0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,

                            0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,

                       0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,

                       0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,

                       0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,

                       0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,

                       0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,

                       0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,

                       0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,

                       0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,

                       0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,

                       0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,

                       0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,

                       0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,

                       0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,

                       0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,

                           0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,

                       0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,

                       0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,

                       0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,

                       0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,

                       0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,

                       0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,

                       0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,

                       0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,

                       0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};   

  (*pcrc) = ( (*pcrc) >> 8 ) ^ crc16_tbl[( (*pcrc) & 0xFF ) ^ (*pdata)]; // Process 8-bits at a time   

}

GenerateAndSend streamData; // Object

void setup() {

  Serial.begin(115200);

}

void loop() {

  streamData.Reset();

  for(uint16_t i=0;i<5;i++) { // Data

    streamData.GenerateDataAndSend(0, 255);

    streamData.CalculateCRC(&streamData.crc_16, &streamData.data);

  }

  for(uint16_t i=0;i<3;i++) { // Send End (number of times must be synchronized with the receiver)

    streamData.SendEnd();

    streamData.CalculateCRC(&streamData.crc_16, (uint8_t*) &streamData.streamEnd);   

  }

  streamData.SendCRC(); // Send calculated CRC

  delay(100); // Delay

}

I tend to separate the class declaration and members definition in different files (.h and .cpp), but this example is simple and more readable this way.

The Labview code uses a producer, consumer structure. The producer loop reads one byte at a time and checks for data package end. When the data package end is recognized, two additional bytes are read (the CRC). The consumer loop then performs the CRC check and outputs the data stream.

readCOMdatastream_BD.png

The Labview code could be made more readable by packing some portions into subvi's, but  it seemed simpler to present the example in this manner.

I am also attaching the C++ code for Arduino as a .txt/.ino file and the Labview code saved for version 2013. Again, if someone needs the ARM code, please let me know and I will update the post.

Best regards,

K


https://decibel.ni.com/content/blogs/kl3m3n



"Kudos: Users may give one another Kudos on the forums for posts that they found particularly helpful or insightful."
Comments
Infinityd
Member

Hello, i have to do diploma work with Olimexino A-13 StarterKit (A13 Cortex A8 processor at 1GHz, 3D Mali400 GPU) + MLX mlx90620. My idea is to make just like your project using LabView to show graphically the results. Can u update this code for this processor and I will be very grateful if u can give me some advices or some kind of guide how to do it (I am new with this things). Sorry for my english and thank you

Klemen
Active Participant

Hello,

I have only used ARM Cortex-M3/4 arhitecture so I really don't know anything about the efforts in porting the code from Cortex M to A.

Best regards,

K


https://decibel.ni.com/content/blogs/kl3m3n



"Kudos: Users may give one another Kudos on the forums for posts that they found particularly helpful or insightful."
Leif_A
Member

Hi Klemen,

Would you please upload a 2012 compatible version? Thank you for the great work!

Best,

Leif

Klemen
Active Participant

Hello,

I have uploaded a 2012 compatible version.

Regards,

K


https://decibel.ni.com/content/blogs/kl3m3n



"Kudos: Users may give one another Kudos on the forums for posts that they found particularly helpful or insightful."
Leif_A
Member

Thanks!

hungth91
Member

Hi Klemen,

Would you mind uploading a 2011 compatible version ? Thank you for your great work!

Best regrads,

Huu Hung Tran

Klemen
Active Participant

Hello,

I've uploaded the 8.6 version.

Best regards,

K


https://decibel.ni.com/content/blogs/kl3m3n



"Kudos: Users may give one another Kudos on the forums for posts that they found particularly helpful or insightful."
xiaowei1983
Member

Would you mind providing a ARM code?

Aaatif
Member

I am using FDRM-K64F mcu.

I already have the C program written i am having difficulty starting with visualizing data on LView. Could you please help me with this ?