[CAN waveform analysis] trip time waveform analysis of CAN

Prepare

CAN communication protocol used for some time, but they are based on the use of the software level, for the waveform is not very understanding, just this time more leisure, it's time to replenish hard knowledge.

Before you begin, tell us about the device:

  • Salted scouring antique level oscilloscope GDS-2202.200MHz, data record length is 12500 points (each point 40ns, the total record length is 500us)

  • EK-LM4F120XL development board. Which it is now EK-TM4C123GXL, onboard MCU is TM4C1233H6PM, corresponding to the original old model LM4F120H5QR

 

 

  • CAN transceiver, TJA1050 module

 

 Ongoing

Software ready

Introducing TI CAN driver library provided with CCS9.0, sending a CAN message every 1 second:

  • Baud rate: 500 kb / s
  • ID(Normal): 0x220
  • Information length: 4 bytes
  • Data: 0x12, 0x34, 0x56, 0x78
  1 int main(void)
  2 {
  3     tCANMsgObject sCANMessage;
  4     unsigned char ucMsgData[4];
  5 
  6     //
  7     // Set the clocking to run directly from the external crystal/oscillator.
  8     // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
  9     // crystal on your board.
 10     //
 11     SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
 12                    SYSCTL_XTAL_16MHZ);
 13 
 14     //
 15     // Set up the serial console to use for displaying messages.  This is
 16     // just for this example program and is not needed for CAN operation.
 17     //
 18     InitConsole();
 19 
 20     //
 21     // For this example CAN0 is used with RX and TX pins on port D0 and D1.
 22     // The actual port and pins used may be different on your part, consult
 23     // the data sheet for more information.
 24     // GPIO port D needs to be enabled so these pins can be used.
 25     // TODO: change this to whichever GPIO port you are using
 26     //
 27     SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
 28 
 29     //
 30     // Configure the GPIO pin muxing to select CAN0 functions for these pins.
 31     // This step selects which alternate function is available for these pins.
 32     // This is necessary if your part supports GPIO pin function muxing.
 33     // Consult the data sheet to see which functions are allocated per pin.
 34     // TODO: change this to select the port/pin you are using
 35     //
 36     GPIOPinConfigure(GPIO_PE4_CAN0RX);
 37     GPIOPinConfigure(GPIO_PE5_CAN0TX);
 38 
 39     //
 40     // Enable the alternate function on the GPIO pins.  The above step selects
 41     // which alternate function is available.  This step actually enables the
 42     // alternate function instead of GPIO for these pins.
 43     // TODO: change this to match the port/pin you are using
 44     //
 45     GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
 46 
 47     //
 48     // The GPIO port and pins have been set up for CAN.  The CAN peripheral
 49     // must be enabled.
 50     //
 51     SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
 52 
 53     //
 54     // Initialize the CAN controller
 55     //
 56     CANInit(CAN0_BASE);
 57 
 58     //
 59     // Set up the bit rate for the CAN bus.  This function sets up the CAN
 60     // bus timing for a nominal configuration.  You can achieve more control
 61     // over the CAN bus timing by using the function CANBitTimingSet() instead
 62     // of this one, if needed.
 63     // In this example, the CAN bus is set to 500 kHz.  In the function below,
 64     // the call to SysCtlClockGet() is used to determine the clock rate that
 65     // is used for clocking the CAN peripheral.  This can be replaced with a
 66     // fixed value if you know the value of the system clock, saving the extra
 67     // function call.  For some parts, the CAN peripheral is clocked by a fixed
 68     // 8 MHz regardless of the system clock in which case the call to
 69     // SysCtlClockGet() should be replaced with 8000000.  Consult the data
 70     // sheet for more information about CAN peripheral clocking.
 71     //
 72 
 73     sysclk = SysCtlClockGet();
 74     CANBitRateSet(CAN0_BASE, sysclk, 500000);
 75 
 76     //
 77     // Enable interrupts on the CAN peripheral.  This example uses static
 78     // allocation of interrupt handlers which means the name of the handler
 79     // is in the vector table of startup code.  If you want to use dynamic
 80     // allocation of the vector table, then you must also call CANIntRegister()
 81     // here.
 82     //
 83     // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors
 84     //
 85     CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
 86 
 87     CANRetrySet(CAN0_BASE, false);
 88     //
 89     // Enable the CAN interrupt on the processor (NVIC).
 90     //
 91     IntEnable(INT_CAN0);
 92 
 93     //
 94     // Enable the CAN for operation.
 95     //
 96     CANEnable(CAN0_BASE);
 97 
 98     //
 99     // Initialize the message object that will be used for sending CAN
100     // messages.  The message will be 4 bytes that will contain an incrementing
101     // value.  Initially it will be set to 0.
102     //
103     *(unsigned long *)ucMsgData = 0;
104     sCANMessage.ulMsgID = 0x220;                    // CAN message ID
105     sCANMessage.ulMsgIDMask = 0;                    // no mask needed for TX
106     sCANMessage.ulFlags = MSG_OBJ_TX_INT_ENABLE;    // enable interrupt on TX
107     sCANMessage.ulMsgLen = sizeof(ucMsgData);       // size of message is 4
108     sCANMessage.pucMsgData = ucMsgData;             // ptr to message content
109 
110     ucMsgData[0] = 0x12;
111     ucMsgData[1] = 0x34;
112     ucMsgData[2] = 0x56;
113     ucMsgData[3] = 0x78;
114     //
115     // Enter loop to send messages.  A new message will be sent once per
116     // second.  The 4 bytes of message content will be treated as an unsigned
117     // long and incremented by one each time.
118     //
119     for(;;)
120     {
121         //
122         // Print a message to the console showing the message count and the
123         // contents of the message being sent.
124         //
125         UARTprintf("Sending msg: 0x%02X %02X %02X %02X",
126                    ucMsgData[0], ucMsgData[1], ucMsgData[2], ucMsgData[3]);
127 
128         //
129         // Send the CAN message using object number 1 (not the same thing as
130         // CAN ID, which is also 1 in this example).  This function will cause
131         // the message to be transmitted right away.
132         //
133         CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
134 
135         //
136         // Now wait 1 second before continuing
137         //
138         SimpleDelay();
139 
140         //
141         // Check the error flag to see if errors occurred
142         //
143         if(g_bErrFlag)
144         {
145             UARTprintf(" error - cable connected?\n");
146         }
147         else
148         {
149             //
150             // If no errors then print the count of message sent
151             //
152             UARTprintf(" total count = %u\n", g_ulMsgCount);
153         }
154 
155         //
156         // Increment the value in the message data.
157         //
158         //(*(unsigned long *)ucMsgData)++;
159     }
160 
161     //
162     // Return no errors
163     //
164     return(0);
165 }

 

Compiler, debugger download the code through the onboard reset run the code.

Hardware preparation

CANH oscilloscope probe pins connected TJA1050 the CH1, CH2 probe connected to GND CANL pin, with the development board is connected, edge-triggered mode using capture waveforms:

analysis

For analytical purposes, the waveform stored in CSV format. The CSV file records waveform information and data, starting at line 17, that is, waveform data, as shown below:

 

Use Matplotlib import CSV, line graph, as follows:

. 1  Import CSV
 2  Import matplotlib
 . 3  Import matplotlib.pyplot AS PLT
 . 4  Import matplotlib.collections AS Collections
 . 5  from matplotlib.ticker Import MultipleLocator
 . 6  Import numpy AS NP
 . 7  Import PANDAS AS PD
 . 8  
. 9 AX = plt.subplot ()
 10  # x to the main scale 125 is set to a multiple label 
. 11 xmajorLocator = MultipleLocator (125 ) 
 12 is  ax.xaxis.set_major_locator (xmajorLocator)
 13 is  # Y-axis data 
14 raw_canh = pd.read_csv("canh.csv")
15 raw_canl = pd.read_csv("canl.csv")
16 #x轴数据
17 t = np.arange(130, 12000, 1)
18 ax.plot(t, raw_canh[130:12000], raw_canl[130:12000])
19 ax.xaxis.grid(True)
20 
21 plt.show()

 

Run, the effect is as follows,

 

Partially enlarged waveform diagram,

 

 The next job is a PS, the reference CAN2.0B Spec, find the definition of each bit. First, define the entire data frame (Data Frame), and

 

 

 

Further refinement of each field (Field):

 

 

The differential signal is converted to the actual binary value, hexadecimal value. It should be added that the relationship between knowledge, CAN signal voltage and the actual logic, good memory, the waveform like the mouth open (O), represents a logical 0 (display); another said logic 1 (recessive). As shown below:

 

Based on the above information, we can further get the following data,

 

If you are very careful look at the above chart, you will find a problem, some hex Why are there nine? Because there is a stuff bit (Bit Stuffing), CAN2.0 predetermined protocol, after 5 consecutive dominant / recessive level, to fill a recessive / dominant level. The figure above arbitration field (Arbitration Field), 5 consecutive '0' after filling a '1'.

 Post

Analysis here draws to a close, there is a doubt, the CRC check is how come it? Spec CAN2.0 learned from the values ​​of the CRC calculation starts from the SOF to the data field (Data Field), the polynomial:

                                          P(x) = x15+ x14+ x10+ x8+ x7+ x4+ x3+ 1

 By computing CRC online site, enter our data to calculate the value of the CRC:

 

 As we expected, CRC value calculation is correct!

 -----------------------------------------------------------------------------------END

[References]

Guess you like

Origin www.cnblogs.com/mr-bike/p/11644578.html