anywill 发表于 2016-10-21 13:50:29

ARM®mbed OS入门开发 STM32内置CRC模块的使用 十进制转二进制

本帖最后由 anywill 于 2016-10-21 13:52 编辑

所有的STM32芯片都内置了一个硬件的CRC计算模块,可以很方便地应用到需要进行通信的程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式:
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1
写成16进制就是:0x04C11DB7

使用这个内置CRC模块的方法非常简单,







用四个开关表示十进制转二进制:
#include "mbed.h"
/*

Last chage:    21-03-2014

Project Name:NUCLEO-F070R-DigIN-CRC-DEC to BIN

By:            www.emcu.it - Enrico Marinoni

NOTE: see here: http://www.emcu.it/NUCLEOevaBoards/NUCLEOevaBoards.html#Tutorial


    This program show this functionality:
      USART2 (Virtual Com for debug)
      USART1
      DigitalIn
      Decimal to Binary conversion//十进制转二进制
      CRC calculation
    NOTE:
      A jumper must be present from PB_6 to PA_10 (USART1)
      More detailsare available here:
      http://www.emcu.it/NUCLEOevaBoards/mBed/QSG-Mbed-Library.pdf


VARIABLEs

IO Status -> variable name is: IOStatus
      Name    Bit DirectionsNote
      Din1    0   IN          PB_8
      Din2    1   IN          PB_9
      Din3    2   IN          PA_6 - Not used in this release of FW
      Din4    3   IN          PA_7    "       "       "       "   
      RL1   4   OUT         PA_8 Optional 4 Relay shield from SEED STUDIO - Not used in this release of FW
      RL2   5   OUT         PB_10    "       "       "       "       "    -   "       "       "       "   
      RL3   6   OUT         PB_4   "       "       "       "       "    -   "       "       "       "   
      RL4   7   OUT         PB_5   "       "       "       "       "    -   "       "       "       "   

ADC Status - Not used in this release of FW
      Name   Variable NameNote
      Ain0      ValAin0   PA_0 - Not used in this release of FW
      Ain1      ValAin1   PA_1      "       "       "       "   
      Ain2      ValAin2   PA_4      "       "       "       "   
      Ain3      ValAin3   PB_0      "       "       "       "   
      Ain4      ValAin4   PC_1      "       "       "       "   


USART2 (RX==D0 - PA_3, TX==D1 - PA2) it is used for debug (connected to the PC) using TeraTerm.
USART1 (RX==D2 - PA_10 , TX==D10 - PB_6) it is used for show the way to use another USART.
Both USART are used in RX Interrupt mode.
The USART parameters are:
    Baud Rate: 1200
    Data: 8
    Parity: NONE
    Stop: 1
    Flow Control: NONE      

*/         

Serial pc(SERIAL_TX, SERIAL_RX);    // This is USART2 tx, rx
                                    //      It is used for Debug via VirtualCOM
                                    //   
Serial Serial1(PB_6, PA_10);      // This is USART1 tx, rx暂时无用

DigitalOut myled(LED1);             // This LED is on NUCLEO-F070R

DigitalIn BlueButton(USER_BUTTON);// This is Blue-Button and is on NUCLEO-F070R
// Digital InPut - from the field
DigitalIn Din1(PB_8);
DigitalIn Din2(PB_9);
DigitalIn Din3(PA_6);
DigitalIn Din4(PA_7);

#define Pressed 0
#define NotPressed 1
#define Enable 1
#define Disable 0
#define POLYNOMIAL 0xD8/* Is for CRC calculation - 11011 followed by 0's */

int Car='\0';
int CarSerial1='\0';
int n=0;
int DinStatus = 0;
int ValCRC = 0;



// Functions -----------------------------------------------------------------------
void SendToPCtheDinStatusAndCRC(void);

int ReadIO(void);       // Read and return the Din1...4 status

void ConvDecToBin(int); // Convert Decimal number in Binary and send the result
                        //      to the PC

uint8_t crcNaive(uint8_t const);

void callback2() // PC - USART2 used for Debug
    {
    // Note: you need to actually read from the serial to clear the RX interrupt
    Car = pc.getc();
    }

void USART1_INT() // USART1
    {
    // Note: you need to actually read from the serial to clear the RX interrupt
    CarSerial1 = Serial1.getc();
    }

// Interrupt used for flashing the Green Led
Timeout to1;
#define ON 1
#define OFF 0
#define DLYFlash 0.5
int ONOFF_Flashing = ON;
void IntFlash(void);


// MAIN program ---------------------------------------------------------------------
int main() {

    // Define the USART ports
    Serial1.attach(&USART1_INT);
    pc.attach(&callback2);

    // SetUp the baud rate
    pc.baud(1200);
    Serial1.baud(1200);   


    // Set PullUp on Digital Input Pins (Din1...4)
    Din1.mode(PullUp);
    Din2.mode(PullUp);
    Din3.mode(PullUp);
    Din4.mode(PullUp);

    // Start flashing the Green Led
    ONOFF_Flashing = ON;            // Enabling flashing flag
    to1.attach(&IntFlash, DLYFlash);// Enabling flashing Interrupt


    pc.printf("\n\r\n\r START MAIN - NucleoF334R8-DigIN-CRC-DECtoBIN\n\r");

    while(1) // Main infinite loop --------------------------------------------------
    {

    // Test the Blue Button
    if (BlueButton == Pressed)
      {
      while(BlueButton == Pressed)
            {
            if (n == 0)
                pc.printf("Please release the BLUE Button\n\r");
            n++;
            }
      n = 0;
      pc.printf("The Digital Input status are:\n\r");
      DinStatus = ReadIO();
      pc.printf("DinStatus == %x\n\r", DinStatus);
      pc.printf("Din4 Din3 Din2 Din1\n\r");
      ConvDecToBin(DinStatus);            

      // CRC calculation
      ValCRC = crcNaive(DinStatus);
      pc.printf("CRC == %d\n\r", ValCRC);

      ONOFF_Flashing = OFF;   // Disable Interrupt of Green LED

      // Start flashing the Green Led (enable Interrupt)
      ONOFF_Flashing = ON;            // Enabling flashing flag
      to1.attach(&IntFlash, DLYFlash);// Enabling flashing Interrupt

      }


    // Test the char. received from PC - USART2 that is USB Virtual COM
    if (Car == 'E')
      {
            pc.printf("\n\r - Send char. E (received from USB_VirtualCOM PC-USART2) to USART1\n\r");
            pc.printf(" - If there is a jumper from PB_6 to PA_10, you will see the Din4...1 status + CRC\n\r");
            Serial1.putc('E');// Send char. E to USART1
            Car = '\0';
      }


    if (Car == '?')
      {
            // Send to PC the status of Digital Inputs Din1...4
            SendToPCtheDinStatusAndCRC();   
            Car = '\0';
      }      


    // Test the char. received from AUREL (USART1)
    if (CarSerial1 == 'E')
      {
            pc.printf("RX char. E from USART1\n\r");
            // Send to PC the status of Digital Inputs Din1...4
            SendToPCtheDinStatusAndCRC();
            CarSerial1 = '\0';         
      }
    }
    // END Main infinite loop -------------------------------------------------------
}


void SendToPCtheDinStatusAndCRC(void)
{
    ONOFF_Flashing = OFF;   // Disable Interrupt of Green LED
    pc.printf("\n\r- PC request, to know the Digital Inputs Status\n\r");
    DinStatus = ReadIO();
    pc.printf("DinStatus == %x\n\r", DinStatus);
    pc.printf("Din4 Din3 Din2 Din1\n\r");
    ConvDecToBin(DinStatus);   
    // CRC calculation
    ValCRC = crcNaive(DinStatus);
    pc.printf("CRC related to Din4...1 == %d\n\r", ValCRC);                  
    Car = '\0';
    // Start flashing the Green Led (enable Interrupt)
    ONOFF_Flashing = ON;            // Enabling flashing flag
    to1.attach(&IntFlash, DLYFlash);// Enabling flashing Interrupt
}


int ReadIO(void)
{
    DigitalIn Din1(PB_8);
    int DinValue=255;

    /* Read all the Digital Inputs (Din1...4) and return a DinValue

      DinValue (bit)             Note
            0               Din1 - 1 == OPEN, 0 == CLOSE
            1               Din2 -   "         "
            2               Din3 -   "         "
            3               Din4 -   "         "
    */

    // Test Din1 status
    if (Din1 == 0)
      DinValue = DinValue & 254; // 0
    else
      DinValue = DinValue & 255; // 1

    // Test Din2 status
    if (Din2 == 0)
      DinValue = DinValue & 253; // 0
    else
      DinValue = DinValue & 255; // 1

    // Test Din3 status
    if (Din3 == 0)
      DinValue = DinValue & 251; // 0
    else
      DinValue = DinValue & 255; // 1

    // Test Din4 status
    if (Din4 == 0)
      DinValue = DinValue & 247; // 0
    else
      DinValue = DinValue & 255; // 1

    return DinValue;
}

//
// Function that convert a Decimal number in Binary
// the original function is here:
// http://www.programmingsimplified ... t-decimal-to-binary
//
void ConvDecToBin(int n)
{
    int c, k;
    for (c = 3; c >= 0; c--)
    {
      k = n >> c;

      if (k & 1)
            pc.printf("1");
      else
            pc.printf("0");
    }
    pc.printf("\n\r");
}


//
// Function that flashing the Green Led
//   
void IntFlash(void)
{
    if (ONOFF_Flashing == ON)
      myled = !myled;
    else
      myled = 0;
    to1.detach();
    to1.attach(&IntFlash, DLYFlash); // this line reload Interrupt
}


//
// CRC calculation
// Original code is gere: http://www.barrgroup.com/Embedde ... -Calculation-C-Code
//
uint8_t crcNaive(uint8_t const message)
{
    uint8_tremainder;


    /*
   * Initially, the dividend is the remainder.
   */
    remainder = message;

    /*
   * For each bit position in the message....
   */
    for (uint8_t bit = 8; bit > 0; --bit)
    {
      /*
         * If the uppermost bit is a 1...
         */
      if (remainder & 0x80)
      {
            /*
             * XOR the previous remainder with the divisor.
             */
            remainder ^= POLYNOMIAL;
      }

      /*
         * Shift the next bit of the message into the remainder.
         */
      remainder = (remainder << 1);
    }

    /*
   * Return only the relevant bits of the remainder as CRC.
   */
    return (remainder >> 4);

}




anywill 发表于 2016-10-21 13:52:22

占楼备用:)

zhangdaijin 发表于 2016-10-21 14:16:35

:):):)谢谢分享

xyx365 发表于 2016-10-21 18:23:35

谢谢分享

slotg 发表于 2016-10-21 21:29:47

以前没留意过这项功能,感谢分享。

lising 发表于 2016-10-22 09:18:17

谢谢分享!

哈佛祖安智 发表于 2016-10-22 12:50:06

:)
页: [1]
查看完整版本: ARM®mbed OS入门开发 STM32内置CRC模块的使用 十进制转二进制