Page 1 of 1

Trying to use CAN on the STM32F3Discovery board

Posted: Wed Mar 19, 2014 4:48 pm
by expoman
Hi all,

as the title implies, I want to use the CAN interface on the STM32F3Discovery board :-)
I started with the demo-project(demos/ARMCM4-STM32F303-DISCOVERY) and copied the testhal functions for the CAN module.
The internal loopback had no problems, so I connected a SN65HVD233 transceiver to the CAN Pins and tried to extend the loopback, as the SN65HVD233 also has an internal loopback(LBKM->High)
PA11(CAN_RX) <-> Pin R at SN65...
PA12(CAN_TX) <-> Pin T at SN65...
Then I turned the alternative functions on the pins on.
But nothing happens. When I attach an oscilloscope to th CAN_TX line, I see nothing.
I have no idea, what to do now.

Below is my code. Could someone look at it and tell me, if I did something wrong or give me a hint for further investigation.

Thanks a lot

Code: Select all

#include "ch.h"
#include "hal.h"

/*
 * Internal loopback mode, 500KBaud, automatic wakeup, automatic recover
 * from abort mode.
 */
static const CANConfig cancfg = {
  CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
  CAN_BTR_SJW(0) | CAN_BTR_TS2(1) |
  CAN_BTR_TS1(8) | CAN_BTR_BRP(6)
};

/*
 * Receiver thread.
 */
static WORKING_AREA(can_rx_wa, 256);
static msg_t can_rx(void *p) {
  EventListener el;
  CANRxFrame rxmsg;

  (void)p;
  chRegSetThreadName("receiver");
  chEvtRegister(&CAND1.rxfull_event, &el, 0);
  while(!chThdShouldTerminate()) {
    if (chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(100)) == 0)
      continue;
    while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == RDY_OK) {
      /* Process message.*/
      if(rxmsg.EID == 0x01234567){
         palTogglePad(GPIOE, GPIOE_LED6_GREEN);
      }
    }
  }
  chEvtUnregister(&CAND1.rxfull_event, &el);
  return 0;
}

/*
 * Transmitter thread.
 */
static WORKING_AREA(can_tx_wa, 256);
static msg_t can_tx(void * p) {
  CANTxFrame txmsg;


  (void)p;
  chRegSetThreadName("transmitter");
  txmsg.IDE = CAN_IDE_EXT;
  txmsg.EID = 0x01234567;
  //txmsg.RTR = CAN_RTR_DATA;
  txmsg.RTR = CAN_RTR_DATA;
  txmsg.DLC = 8;
  txmsg.data32[0] = 0x55AA55AA;
  txmsg.data32[1] = 0x00FF00FF;

  while (!chThdShouldTerminate()) {
    canTransmit(&CAND1, CAN_ANY_MAILBOX, &txmsg, MS2ST(100));
    chThdSleepMilliseconds(1000);
    palTogglePad(GPIOE, GPIOE_LED3_RED);
  }
  return 0;
}
/*
 * This is a periodic thread that does absolutely nothing except flashing LEDs.
 */
static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {

  (void)arg;
  chRegSetThreadName("blinker");
  while (TRUE) {
    //palSetPad(GPIOE, GPIOE_LED3_RED);
    //chThdSleepMilliseconds(125);
    //palClearPad(GPIOE, GPIOE_LED3_RED);
    palSetPad(GPIOE, GPIOE_LED5_ORANGE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED5_ORANGE);
    palSetPad(GPIOE, GPIOE_LED7_GREEN);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED7_GREEN);
    palSetPad(GPIOE, GPIOE_LED9_BLUE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED9_BLUE);
    palSetPad(GPIOE, GPIOE_LED10_RED);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED10_RED);
    palSetPad(GPIOE, GPIOE_LED8_ORANGE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED8_ORANGE);
    //palSetPad(GPIOE, GPIOE_LED6_GREEN);
    //chThdSleepMilliseconds(125);
    //palClearPad(GPIOE, GPIOE_LED6_GREEN);
    //palSetPad(GPIOE, GPIOE_LED4_BLUE);
    //chThdSleepMilliseconds(125);
    //palClearPad(GPIOE, GPIOE_LED4_BLUE);
  }
}

/*
 * Application entry point.
 */
int main(void) {

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the serial driver 1 using the driver default configuration.
   * PA9(TX) and PA10(RX) are routed to USART1.
   */
  sdStart(&SD1, NULL);
  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7));
  palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7));

  /*
   * Activates the CAN driver 1.
   */
  //Use PA11(CAN_RX) and PA12(CAN_TX)
  palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(9) | PAL_STM32_OSPEED_HIGHEST  | PAL_STM32_OTYPE_OPENDRAIN);
  palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(9) | PAL_STM32_OSPEED_HIGHEST  | PAL_STM32_OTYPE_OPENDRAIN);
  canStart(&CAND1, &cancfg);

  /*
   * Starting the transmitter and receiver threads.
   */
  chThdCreateStatic(can_rx_wa, sizeof(can_rx_wa), NORMALPRIO + 7, can_rx, NULL);
  chThdCreateStatic(can_tx_wa, sizeof(can_tx_wa), NORMALPRIO + 7, can_tx, NULL);

  /*
   * Creates the example thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);

  /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop and check the button state, when the button is
   * pressed the test procedure is launched.
   */
  while (TRUE) {
    if (palReadPad(GPIOA, GPIOA_BUTTON))
       palTogglePad(GPIOE, GPIOE_LED4_BLUE);
    chThdSleepMilliseconds(500);
  }
}

Re: Trying to use CAN on the STM32F3Discovery board

Posted: Wed Mar 19, 2014 5:12 pm
by Giovanni
Hi,

PA11 and PA12 are wired as USB on the board, probably this is your problem. You may remap on PD0 and PD1.

BTW: CAN_MCR_AWUM is no more supported, I have to remove it from the demos.

Giovanni

Re: Trying to use CAN on the STM32F3Discovery board

Posted: Tue Apr 08, 2014 10:29 pm
by expoman
Sorry guys to bring this topic up again :|

I changed the pins to PD0 and PD1. But the loopback through the can transceiver still doesn't work.
At the pins CanRX and CanTX I can see the signal and from my point of view it looks good.

In the rx-thread is an extra eventlistener, to check for a cand1.error_event.
This flag is always on, regardless what I do.
What does this error mean?
Can you give me a hint where to look into?

Thanks

Here is the rx-thread code:

Code: Select all

static msg_t can_rx(void *p) {
  EventListener el;
  EventListener el2;
  eventmask_t mask;
  CANRxFrame rxmsg;

  (void)p;
  chRegSetThreadName("receiver");
  chEvtRegister(&CAND1.rxfull_event, &el, 0);
  chEvtRegister(&CAND1.error_event, &el2, 1);
  while(!chThdShouldTerminate()) {
   palTogglePad(GPIOE, GPIOE_LED7_GREEN);
    if ((mask = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(100))) == 0)
      continue;
    if(mask & EVENT_MASK(0)){
    palTogglePad(GPIOE, GPIOE_LED9_BLUE);
   
    while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == RDY_OK) {
      /* Process message.*/
      palTogglePad(GPIOE, GPIOE_LED5_ORANGE);
      if(rxmsg.EID == 0x01234567){
         palTogglePad(GPIOE, GPIOE_LED6_GREEN);
      }
    }
    }
    if(mask & EVENT_MASK(1)){
       palTogglePad(GPIOE, GPIOE_LED10_RED);
       errors |= chEvtGetAndClearFlags(&el2);
    }
  }
  chEvtUnregister(&CAND1.rxfull_event, &el);
  chEvtUnregister(&CAND1.error_event, &el2);
  return 0;
}

Re: Trying to use CAN on the STM32F3Discovery board

Posted: Wed Apr 09, 2014 9:17 am
by Giovanni
I don't know if it is possible to do a loopback through the transceiver, are you sure about that?

Giovanni

Re: Trying to use CAN on the STM32F3Discovery board

Posted: Wed Apr 09, 2014 11:40 am
by expoman
Yes, I'm sure. That's why I have choosen this chip in the first place, because of this feature.
I double checked the datasheet and the chip marks to use the right type.

One of my tests was to watch the signal at the CANRX pin, then remove the connection of the CANTX pin with the transceiver, the signal on the CANRX pin was then gone.
When I established the connection again, the signal is back. So the STM32F3 must see the signal.
I mean, he has to receive something. Why would he throw the error event, if he wouldn't receive a packet?

Expoman

Re: Trying to use CAN on the STM32F3Discovery board

Posted: Wed Apr 09, 2014 12:28 pm
by Giovanni
Verify if pins are both programmed correctly (alternate) and the remap is done.

Giovanni