6 Replies Latest reply on May 2, 2018 1:18 AM by quantom3230

    CAN communication with GPIO

    100doraemon

      Hello

      I am trying to create a standalone program in C to use the CAN to send and receive messages and display them using the printf. I use the polled examples given by Xilinx :
      file:///C:/Xilinx/14.4/ISE_DS/EDK/sw/XilinxProcessorIPLib/drivers/canps_v1_01_a/examples/xcanps_polled_example.c

      The program just send a message to a CAN device using the JB3 PIN and wait for an answer on JB4 PIN to display it.
      Using oscilloscope I can see both send and receive on each PIN.
      The problem is that the program does'nt detect the receive message so it cannot display it (it is always waiting for a message). It is stuck at this instruction :
      while(XCanPs_IsRxEmpty(InstancePtr) == TRUE)

      I just changed the mode from LOOPBACK to NORMAL :
      XCanPs_EnterMode(CanInstPtr, XCANPS_MODE_NORMAL);
      while(XCanPs_GetMode(CanInstPtr) != XCANPS_MODE_NORMAL);

      I tried the interrupt example and it is the same problem to.

      Can someone help me ? Here is the source code :






      #include <stdio.h>
      #include "platform.h"



      /***************************** Include Files *********************************/

      #include "xcanps.h"
      #include "xparameters.h"
      #include "xil_printf.h"



      /************************** Constant Definitions *****************************/

      /*
      * The following constants map to the XPAR parameters created in the
      * xparameters.h file. They are defined here such that a user can easily
      * change all the needed parameters in one place.
      */
      #define CAN_DEVICE_IDtXPAR_XCANPS_0_DEVICE_ID

      /*
      * Maximum CAN frame length in words.
      */
      #define XCANPS_MAX_FRAME_SIZE_IN_WORDS (XCANPS_MAX_FRAME_SIZE / sizeof(u32))

      #define FRAME_DATA_LENGTH tt8  /* Frame Data field length */

      /*
      * Message Id Constant.
      */
      #define TEST_MESSAGE_IDttt2000

      /*
      * The Baud Rate Prescaler Register (BRPR) and Bit Timing Register (BTR)
      * are setup such that CAN baud rate equals 40Kbps, assuming that the
      * the CAN clock is 24MHz. The user needs to modify these values based on
      * the desired baud rate and the CAN clock frequency. For more information
      * see the CAN 2.0A, CAN 2.0B, ISO 11898-1 specifications.
      */

      /*
      * Timing parameters to be set in the Bit Timing Register (BTR).
      * These values are for a 40 Kbps baudrate assuming the CAN input clock
      frequency
      * is 24 MHz.
      */
      #define TEST_BTR_SYNCJUMPWIDTHtt1
      #define TEST_BTR_SECOND_TIMESEGMENTt3
      #define TEST_BTR_FIRST_TIMESEGMENTt8

      /*
      * The Baud rate Prescalar value in the Baud Rate Prescaler Register (BRPR)
      * needs to be set based on the input clock  frequency to the CAN core and
      * the desired CAN baud rate.
      * This value is for a 40 Kbps baudrate assuming the CAN input clock frequency
      * is 24 MHz.
      */
      #define TEST_BRPR_BAUD_PRESCALARt1



      /************************** Function Prototypes ******************************/

      int CanPsPolledExample(u16 DeviceId);
      static int SendFrame(XCanPs *InstancePtr);
      static int RecvFrame(XCanPs *InstancePtr);



      /************************** Variable Definitions *****************************/

      /*
      * Buffers to hold frames to send and receive. These are declared as global so
      * that they are not on the stack.
      * These buffers need to be 32-bit aligned
      */
      static u32 TxFrame[XCANPS_MAX_FRAME_SIZE_IN_WORDS];
      static u32 RxFrame[XCANPS_MAX_FRAME_SIZE_IN_WORDS];

      /* Driver instance */
      static XCanPs Can;




      int main()
      {
      tint Status;

      txil_printf("CAN Polled Mode Example Test r
      ");

      t/*
      t * Run the Can Polled example, specify the Device ID that is generated
      t * in xparameters.h .
      t */
      tStatus = CanPsPolledExample(CAN_DEVICE_ID);
      tif(Status != XST_SUCCESS){
      ttxil_printf("CAN Polled Mode Example Test Failedr
      ");
      ttreturn XST_FAILURE;
      t}

      txil_printf("Successfully ran CAN Polled Mode Example Testr
      ");
      treturn XST_SUCCESS;
      }










      /*****************************************************************************/
      /**
      *
      * The entry point for showing the XCanPs driver in polled mode. The example
      * configures the device for internal loop back mode, then sends a Can
      * frame, receives the same Can frame, and verifies the frame contents.
      *
      * @paramtDeviceId is the XPAR_<CANPS_instance>_DEVICE_ID value from
      *ttxparameters.h
      *
      * @returntXST_SUCCESS if successful, otherwise driver-specific error code.
      *
      * @note
      *
      * If the device is not working correctly, this function may enter an infinite
      * loop and will never return to the caller.
      *
      ******************************************************************************/
      int CanPsPolledExample(u16 DeviceId)
      {
      tint Status;
      tXCanPs *CanInstPtr = &Can;
      tXCanPs_Config *ConfigPtr;

      t/*
      t * Initialize the Can device.
      t */
      tConfigPtr = XCanPs_LookupConfig(DeviceId);
      tif(CanInstPtr == NULL){
      ttreturn XST_FAILURE;
      t}
      tStatus = XCanPs_CfgInitialize(CanInstPtr, ConfigPtr, ConfigPtr->BaseAddr);
      tif(Status != XST_SUCCESS){
      ttreturn XST_FAILURE;
      t}

      t/*
      t * Run self-test on the device, which verifies basic sanity of the
      t * device and the driver.
      t */
      tStatus = XCanPs_SelfTest(CanInstPtr);
      tif(Status != XST_SUCCESS){
      ttreturn XST_FAILURE;
      t}

      t/*
      t * Enter Configuration Mode so we can setup Baud Rate Prescaler
      t * Register (BRPR) and Bit Timing Register (BTR).
      t */
      tXCanPs_EnterMode(CanInstPtr, XCANPS_MODE_CONFIG);
      twhile(XCanPs_GetMode(CanInstPtr) != XCANPS_MODE_CONFIG);

      t/*
      t * Setup Baud Rate Prescaler Register (BRPR) and
      t * Bit Timing Register (BTR).
      t */
      tXCanPs_SetBaudRatePrescaler(CanInstPtr, TEST_BRPR_BAUD_PRESCALAR);
      tXCanPs_SetBitTiming(CanInstPtr, TEST_BTR_SYNCJUMPWIDTH, TEST_BTR_SECOND_TIMESEGMENT, TEST_BTR_FIRST_TIMESEGMENT);

      t/*
      t * Enter Loop Back Mode.
      t */
      tXCanPs_EnterMode(CanInstPtr, XCANPS_MODE_NORMAL);
      twhile(XCanPs_GetMode(CanInstPtr) != XCANPS_MODE_NORMAL);

      t/*
      t * Send a frame, receive the frame via the loop back and verify its
      t * contents.
      t */
      tStatus = SendFrame(CanInstPtr);
      tif(Status != XST_SUCCESS){
      ttreturn Status;
      t}

      tStatus = RecvFrame(CanInstPtr);

      treturn Status;
      }


      /*****************************************************************************/
      /**
      *
      * Send a CAN frame.
      *
      * @paramtInstancePtr is a pointer to the driver instance
      *
      * @returntXST_SUCCESS if successful, a driver-specific return code if not.
      *
      * @note
      *
      * This function waits until TX FIFO has room for at least one frame before
      * sending a frame. So this function may block if the hardware is not built
      * correctly.
      *
      ******************************************************************************/
      static int SendFrame(XCanPs *InstancePtr)
      {
      tu8 *FramePtr;
      tint Index;
      tint Status;

      t/*
      t * Create correct values for Identifier and Data Length Code Register.
      t */
      tTxFrame[0] = (u32)XCanPs_CreateIdValue((u32)TEST_MESSAGE_ID, 0, 0, 0, 0);
      tTxFrame[1] = (u32)XCanPs_CreateDlcValue((u32)FRAME_DATA_LENGTH);

      t/*
      t * Now fill in the data field with known values so we can verify them
      t * on receive.
      t */
      tFramePtr = (u8 *)(&TxFrame[2]);
      t//for (Index = 0; Index < FRAME_DATA_LENGTH; Index++) {
      t//t*FramePtr++ = (u8)Index;
      t//}
      tFramePtr[0] = (u8)31;
      tFramePtr[1] = (u8)32;
      tFramePtr[2] = (u8)33;
      tFramePtr[3] = (u8)34;
      tFramePtr[4] = (u8)35;
      tFramePtr[5] = (u8)36;
      tFramePtr[6] = (u8)37;
      tFramePtr[7] = (u8)38;
      tfor(Index=0 ; Index<FRAME_DATA_LENGTH ; Index++){
      ttxil_printf("send%d : %d
      r", Index, FramePtr[Index]);
      t}




      t/*
      t * Wait until TX FIFO has room.
      t */
      twhile(XCanPs_IsTxFifoFull(InstancePtr) == TRUE);

      t/*
      t * Now send the frame.
      t *
      t * Another way to send a frame is keep calling XCanPs_Send() until it
      t * returns XST_SUCCESS. No check on if TX FIFO is full is needed anymore
      t * in that case.
      t */
      tStatus = XCanPs_Send(InstancePtr, TxFrame);

      treturn Status;
      }


      /*****************************************************************************/
      /**
      *
      * This function receives a frame and verifies its contents.
      *
      * @paramtInstancePtr is a pointer to the driver instance.
      *
      * @returntXST_SUCCESS if successful, a driver-specific return code if not.
      *
      * @note
      *
      * This function waits until RX FIFO becomes not empty before reading a frame
      * from it. So this function may block if the hardware is not built
      * correctly.
      *
      ******************************************************************************/
      static int RecvFrame(XCanPs *InstancePtr)
      {
      tu8 *FramePtr;
      tint Status;
      tint Index;

      t/*
      t * Wait until a frame is received.
      t */
      twhile(XCanPs_IsRxEmpty(InstancePtr) == TRUE);

      t/*
      t * Receive a frame and verify its contents.
      t */
      tStatus = XCanPs_Recv(InstancePtr, RxFrame);
      tif(Status == XST_SUCCESS){
      tt/*
      tt * Verify Identifier and Data Length Code.
      tt */
      ttif (RxFrame[0] !=
      ttt(u32)XCanPs_CreateIdValue((u32)TEST_MESSAGE_ID, 0, 0, 0, 0))
      tttreturn XST_LOOPBACK_ERROR;

      ttif ((RxFrame[1] & ~XCANPS_DLCR_TIMESTAMP_MASK) != TxFrame[1])
      tttreturn XST_LOOPBACK_ERROR;

      tt/*
      tt * Verify Data field contents.
      tt */
      ttFramePtr = (u8 *)(&RxFrame[2]);
      tt//for (Index = 0; Index < FRAME_DATA_LENGTH; Index++) {
      tt//tif (*FramePtr++ != (u8)Index) {
      tt//ttreturn XST_LOOPBACK_ERROR;
      tt//t}
      tt//}
      ttfor (Index=0 ; Index<FRAME_DATA_LENGTH ; Index++){
      tttxil_printf("receive%d : %d
      r", Index, FramePtr[Index]);
      tt}

      t}

      treturn Status



      Thank you very much