CAN Rx , Tx pin name for STM32F103C8

I want to try example for the СAN bus.

There are only two STM32F103C8 controllers on the bus.
I only have free:
pa11 = usb_DM can_rx
pa12 = usb_ВЗ can_tx

But in example are indicated: PB_8, PB_9

CAN can(PB_8, PB_9); // CAN Rx pin name, CAN Tx pin name

Here you wrote:

“target_overrides” : {
“*” : {
“device_has_remove” : [ “USBDEVICE” ]

A similar problem, but the microcontroller is different.
I want to try to connect without transceivers. (distance 2 meters)
Your example for OS2. Is it possible for OS5?


  • Yes, you can use PA_11 and PA_12 for CAN bus communication
CAN can(PA_11, PA_12);

But then I do not recommend to power the board over the USB connector because inside some USB chargers the USB_DP and USB_DM lines are connected one another. When such USB charger is used the CAN RD and CAN TD pins become connected one another (because the USB_DP and USB_DM pins are connected to the PA_11, PA_12 pins, respectively) and the CAN bus fails to operate.

  • For short distances you can omit CAN transceivers as described here. But then you probably have to reduce the CAN speed (frequency) to 500 000 bps (or less). And also make sure the grounds of the CAN nodes are connected one another.
  • Mbed OS 5 does not allow to call printf in ISR context so you have to use polling:
void onCanReceived(void)
    pc.printf("CAN message received\r\n");
int main(void)
    pc.baud(9600);          // set serial speed
    can.frequency(500000); // set CAN bit rate to 500 000 bps
    can.filter(RX_ID, 0xFFF, CANStandard, 0); // set filter #0 to accept only standard messages with ID == RX_ID
    //can.attach(onCanReceived);  // polling is used (in main() ) rather than ISR
#if defined(BOARD1)
    led = ON;               // turn the LED on
    timer.start();          // start timer
    pc.printf("CAN_Hello board #1\r\n");
    led = OFF;      // turn LED off
    pc.printf("CAN_Hello board #2\r\n");
    while(1) {
        if(  // polling for CAN messages

        if(timer.read_ms() >= 2000) {    // check for timeout
            timer.stop();                // stop timer
            timer.reset();               // reset timer 

Здравствуйте Золтан.
Спасибо за ответ.
Ваши рекомендации мне очень помогли.
Я слабо владею английским, поэтому у меня просьба:
укажите что почитать на темы:

  • разница между OS2 и OS5;
  • как выбрать OS2 или OS5 в он-лайн компиляторе.
    Большое спасибо за Вашу хорошую работу и внимание к MBED.

С уважением, Орьев Павел.

Hello Zoltan.
Thanks for the answer.
Your recommendations helped me a lot.
I do not speak much English, so I have a request:
indicate what to read on the topics:

  • the difference between OS2 and OS5;
    • How to choose OS2 or OS5 in an online compiler.
      Thank you very much for your good work and attention to MBED.

Sincerely, Oryev Pavel.

Hello Pavel,

The difference between OS2 and OS5?

Mbed OS 2:

  • It is very similar to Arduino. The main difference is a timer interrupt running at 1 MHz (on most platforms, on some low end ones it’s slower) that is used for all of the Timers/Tickers/Timeouts to give a 1 us resolution.
  • RTOS isn’t available by default but can be added like a library.
  • Suitable for smaller target MCUs. However, more recent ones are not supported.
  • For more info have a look at the Mbed Cookbook
  • Not supported by Team Mbed anymore!

Mbed OS 5:

  • RTOS is on by default. For small targets (or if you don’t want to use it) you can turn it off by adding a mbed_app.json file with the following content to the project:
    "requires": ["bare-metal"]
  • The Mbed OS 5 documentation is available here.
  • Still supported by Mbed Team but about to be superceded by Mbed OS 6.

How to choose OS2 or OS5 in an online compiler?

  • Select your target board (using the top-right button).
  • Click on the New button to create a new program.
  • In the popup window:
    • Select the “Blinky LED Hello World” template to create a Mbed OS 2 program.
    • Select the “mbed OS Blinky LED Hello World” template to create a Mbed OS 5 program.

Thanks a lot, Zoltan!
For beginners and this will help me a lot.

Hello Pavel,

I have received a private message from you. But I’m not able to send a reply via the Mbed messaging system because it says “This user’s profile page is private”. So here is your question and my response:

In your library, lines 8-9, probably a typo? 8 #define MODE() output(); \ 9 mode(OpenDrain)

  • It is not a typo. It is valid only for STM targets where in Open Drain Mode a “0” in the Output register activates the N-MOS while a “1” in the output register leaves the port in Hi-Z (the P-MOS is never activated). A read access to the Input Data Register gets the I/O state in open drain mode.

I wanted to clarify what line 8 is, ends with symbol " \ " . It is right?

It defines a macro called MODE():

#define MODE()      output(); \

NOTE: The ‘\’ after the output(); tells the C-preprocessor that the macro continues on the following line
The MODE() macro is then used in OneWire.cpp :

OneWire::OneWire(PinName pin) :
    MODE(); // set mode to either OpenDrain for STM or PullUp for others

When the C-preprocessor is run it replaces the MODE() and the INIT_WAIT macros in accordance with their’s definition:

OneWire::OneWire(PinName pin) :
    mode(OpenDrain); // set mode to either OpenDrain for STM or PullUp for others
    ; // INIT_WAIT is replaced with empty text

Thank you and sorry for such questions.
I know circuitry better than programming.
I will learn.

Never mind! There are no wrong questions. I’m sure you’ll learn quickly.