Controller Area Network library for NUCLEO boards equipped with CAN peripheral.

Dependents:   Nucleo-Courtois CANBLE CANnucleo_Hello3 Nucleo_Serialprintf ... more

Controller Area Network library for the NUCLEO and DISCOVERY boards equipped with CAN peripheral


Information

Because CAN support has been finally implemented into the mbed library also for the ST boards there is no need to use the CANnucleo library anymore (however you may if you want). The CAN_Hello example is trying to demonstrate the mbed built-in CAN API with NUCLEO boards.


Provides CAN support for the following boards:

with the following features:

  • Easy to use. Delete the mbed library from your project and import the latest mbed-dev and CANnucleo libraries. In the mbed-dev library open the device.h file associated with the selected target board and add #undef DEVICE_CAN as follows:

device.h

#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H

//=======================================
#define DEVICE_ID_LENGTH       24

#undef DEVICE_CAN

#include "objects.h"

#endif

See the CANnucleo_Hello demo for more details.

  • Automatic recovery from bus-off state can be enabled/disabled in the constructor (defaults to ENABLE).
  • Up to 14 filters (0 - 13) are available for the application to set up for message filtering performed by hardware.
    For more details see below or have a look at the comments in CANnucleo.cpp.
  • One CAN channel per NUCLEO board is supported. The CAN peripheral can be connected either to pins PA_11, PA_12 (Receiver, Transmitter) or to pins PB_8, PB_9 (Receiver, Transmitter). This is configured when creating a CAN instance.
  • Simplifies adding/getting data to/from a CAN message by using the << (append) and the >> (extract) operators.

Import programCANnucleo_Hello

Using CAN bus with NUCLEO boards (Demo for the CANnucleo library).



Filtering performed by the built-in CAN controller without disturbing the CPU

CANnucleo supports only mask mode and 32-bit filter scale. Identifier list mode filtering and 16-bit filter scale are not supported. There are 14 filters available (0 - 13) for the application to set up. Each filter is a 32-bit filter defined by a filter ID and a filter mask. If no filter is set up then no CAN message is accepted! That's why filter #0 is set up in the constructor to accept all CAN messages by default. On reception of a message it is compared with filter #0. If there is a match, the message is accepted and stored. If there is no match, the incoming identifier is then compared with the next filter. If the received identifier does not match any of the identifiers configured in the filters, the message is discarded by hardware without disturbing the software.

CAN filter function - designed to setup a CAN filter

int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle)

Parameters

id - 'Filter ID' defines the bit values to be compared with the corresponding received bits.

Mapping of 32-bits (4-bytes) :

STID[10:3]STID[2:0] EXID[17:13]EXID[12:5]EXID[4:0] IDE RTR 0
  • STID - Stardard Identifier bits
  • EXID - Extended Identifier bits
  • [x:y]- bit range
  • IDE - Identifier Extension bit (0 -> Standard Identifier, 1 -> Extended Identifier)
  • RTR - Remote Transmission Request bit (0 -> Remote Transmission Request, 1 -> Standard message)

mask - 'Filter mask' defines which bits of the 'Filter ID' are compared with the received bits and which are disregarded.
Mapping of 32-bits (4-bytes) :

STID[10:3]STID[2:0] EXID[17:13]EXID[12:5]EXID[4:0] IDE RTR 0
  • STID - Stardard Identifier bits
  • EXID - Extended Identifier bits
  • [x:y]- bit range
  • IDE - Identifier Extension bit
  • RTR - Remote Transmission Request bit
  • 1 -> bit is considered
  • 0 -> bit is disregarded

format - This parameter must be CANAny
handle - Selects the filter. This parameter must be a number between 0 and 13.
retval - 0 - successful, 1 - error, 2 - busy, 3 - time out

Example of filter set up and filtering

Let's assume we would like to accept only messages with standard identifier 0x207:

STID[15:0] = 0x207 = 00000010 00000111


We map the STID to filter ID by shifting the bits adequately:

Filter ID = STID << (16 + (15 - 10)) = STID << 21 = 01000000 11100000 00000000 00000000


To compare only the bits representing STID we set the filter mask appropriately:

Filter mask = 11111111 11100000 00000000 00000100 = 0xFFE00004
              |||||||| |||                    |
              -------- ---                    |
                  |     |                     |
           STID[10:3]  STID[2:0]             IDE


Recall that filter #0 has been set up in the constructor to accept all CAN messages by default. So we have to reconfigure it. If we were set up filter #1 here then filter #0 would accept all the messages and no message would reach filter #1!
To reconfigure (set up) filter #0 we call:

can.filter(0x207 << 21, 0xFFE00004, CANAny, 0);


            Only these bits of 'Filter id' (set to 1 here in 'Filter mask') are compared 
            with the corresponding bits of received message (the others are disregarded)
                                |
                 ---------------------------------
                 |||||||| |||                    |
   Filter mask = 11111111 11100000 00000000 00000100 (= 0xFFE00004)
   Filter id   = 01000000 11100000 00000000 00000000 (= 0x40E00000)
                 |||||||| |||                    |
                 ---------------------------------
                                |
            To accept the message the values of these bits must match.
            Otherwise the message is passed to the next filter or
            discarded if this was the last active filter.
                                |
                 ---------------------------------
                 |||||||| |||                    |
   Received id = 01000000 11100000 00000000 00000010 (= 0x40E00002)
                             ||||| |||||||| ||||| ||
                             -----------------------
                                         |
                          These bits (set to 0 in 'Filter mask') are disregarded (masked).
                          They can have arbitrary values.


NOTE: For the meaning of individual bits see the mapping of 32-bits explained above.

We can use the filter function to setup more (up to 14) CAN filters for example as follows:

can.filter(0x207 << 21, 0xFFE00004, CANAny, 0);    // filter #0
can.filter(0x251 << 21, 0xFFE00004, CANAny, 1);    // filter #1
can.filter(0x304 << 21, 0xFFE00004, CANAny, 2);    // filter #2
...
Committer:
hudakz
Date:
Sun May 28 09:18:54 2017 +0000
Revision:
29:cebc6f21046e
Parent:
27:eed6929956ea
Updated.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:e29bc8e0dddd 1 /* mbed Microcontroller Library
hudakz 0:e29bc8e0dddd 2 * Copyright (c) 2006-2013 ARM Limited
hudakz 0:e29bc8e0dddd 3 *
hudakz 0:e29bc8e0dddd 4 * Licensed under the Apache License, Version 2.0 (the "License");
hudakz 0:e29bc8e0dddd 5 * you may not use this file except in compliance with the License.
hudakz 0:e29bc8e0dddd 6 * You may obtain a copy of the License at
hudakz 0:e29bc8e0dddd 7 *
hudakz 0:e29bc8e0dddd 8 * http://www.apache.org/licenses/LICENSE-2.0
hudakz 0:e29bc8e0dddd 9 *
hudakz 0:e29bc8e0dddd 10 * Unless required by applicable law or agreed to in writing, software
hudakz 0:e29bc8e0dddd 11 * distributed under the License is distributed on an "AS IS" BASIS,
hudakz 0:e29bc8e0dddd 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
hudakz 0:e29bc8e0dddd 13 * See the License for the specific language governing permissions and
hudakz 0:e29bc8e0dddd 14 * limitations under the License.
hudakz 0:e29bc8e0dddd 15 *
hudakz 27:eed6929956ea 16 * Modified by Zoltan Hudak <hudakz@outlook.com>
hudakz 0:e29bc8e0dddd 17 *
hudakz 0:e29bc8e0dddd 18 */
hudakz 23:c5d348e65e24 19 #ifndef CANNUCLEO_API_H
hudakz 23:c5d348e65e24 20 #define CANNUCLEO_API_H
hudakz 0:e29bc8e0dddd 21
hudakz 0:e29bc8e0dddd 22 #include "device.h"
hudakz 0:e29bc8e0dddd 23 #include "PinNames.h"
hudakz 0:e29bc8e0dddd 24 #include "PeripheralNames.h"
hudakz 0:e29bc8e0dddd 25 #include "can_helper.h"
hudakz 0:e29bc8e0dddd 26
hudakz 16:f4c8f45bded9 27 #if defined(TARGET_NUCLEO_F072RB) || \
hudakz 16:f4c8f45bded9 28 defined(TARGET_NUCLEO_F091RC)
hudakz 16:f4c8f45bded9 29 #include "stm32f0xx_hal_msp.h"
hudakz 16:f4c8f45bded9 30 #elif defined(TARGET_NUCLEO_F103RB)
hudakz 14:0344705e6fb8 31 #include "stm32f1xx_hal_msp.h"
hudakz 14:0344705e6fb8 32 #elif defined(TARGET_NUCLEO_F302R8) || \
hudakz 14:0344705e6fb8 33 defined(TARGET_NUCLEO_F303RE) || \
hudakz 14:0344705e6fb8 34 defined(TARGET_NUCLEO_F303K8) || \
hudakz 14:0344705e6fb8 35 defined(TARGET_NUCLEO_F334R8) || \
hudakz 14:0344705e6fb8 36 defined(TARGET_DISCO_F334C8)
hudakz 14:0344705e6fb8 37 #include "stm32f3xx_hal_msp.h"
hudakz 16:f4c8f45bded9 38 #elif defined(TARGET_NUCLEO_F446RE)
hudakz 16:f4c8f45bded9 39 #include "stm32f4xx_hal_msp.h"
hudakz 14:0344705e6fb8 40 #endif
hudakz 5:b53e5ee15315 41
hudakz 0:e29bc8e0dddd 42 #ifdef __cplusplus
hudakz 0:e29bc8e0dddd 43 extern "C" {
hudakz 0:e29bc8e0dddd 44 #endif
hudakz 0:e29bc8e0dddd 45
hudakz 0:e29bc8e0dddd 46 typedef enum {
hudakz 0:e29bc8e0dddd 47 IRQ_RX,
hudakz 0:e29bc8e0dddd 48 IRQ_TX,
hudakz 0:e29bc8e0dddd 49 IRQ_ERROR,
hudakz 0:e29bc8e0dddd 50 IRQ_OVERRUN,
hudakz 0:e29bc8e0dddd 51 IRQ_WAKEUP,
hudakz 0:e29bc8e0dddd 52 IRQ_PASSIVE,
hudakz 0:e29bc8e0dddd 53 IRQ_ARB,
hudakz 0:e29bc8e0dddd 54 IRQ_BUS,
hudakz 0:e29bc8e0dddd 55 IRQ_READY
hudakz 0:e29bc8e0dddd 56 } CanIrqType;
hudakz 0:e29bc8e0dddd 57
hudakz 0:e29bc8e0dddd 58
hudakz 0:e29bc8e0dddd 59 typedef enum {
hudakz 0:e29bc8e0dddd 60 MODE_RESET,
hudakz 0:e29bc8e0dddd 61 MODE_NORMAL,
hudakz 0:e29bc8e0dddd 62 MODE_SILENT,
hudakz 0:e29bc8e0dddd 63 MODE_TEST_GLOBAL,
hudakz 0:e29bc8e0dddd 64 MODE_TEST_LOCAL,
hudakz 0:e29bc8e0dddd 65 MODE_TEST_SILENT
hudakz 0:e29bc8e0dddd 66 } CanMode;
hudakz 0:e29bc8e0dddd 67
hudakz 0:e29bc8e0dddd 68 typedef void (*can_irq_handler)(uint32_t id, CanIrqType type);
hudakz 0:e29bc8e0dddd 69
hudakz 20:bcd8161f8f6c 70 void can_init (PinName rd, PinName td, FunctionalState abom);
hudakz 20:bcd8161f8f6c 71 void can_free (void);
hudakz 20:bcd8161f8f6c 72 int can_frequency(int hz);
hudakz 20:bcd8161f8f6c 73 void can_irq_init (uint32_t id, can_irq_handler handler);
hudakz 20:bcd8161f8f6c 74 void can_irq_free (void);
hudakz 20:bcd8161f8f6c 75 int can_write (CAN_Message, int cc);
hudakz 20:bcd8161f8f6c 76 int can_read (CAN_Message *msg, int handle);
hudakz 20:bcd8161f8f6c 77 int can_mode (CanMode mode);
hudakz 20:bcd8161f8f6c 78 int can_filter (uint32_t id, uint32_t mask, CANFormat format, int32_t handle);
hudakz 20:bcd8161f8f6c 79 void can_reset (void);
hudakz 20:bcd8161f8f6c 80 unsigned char can_rderror (void);
hudakz 20:bcd8161f8f6c 81 unsigned char can_tderror (void);
hudakz 20:bcd8161f8f6c 82 void can_monitor (int silent);
hudakz 20:bcd8161f8f6c 83 void can_callback (void);
hudakz 0:e29bc8e0dddd 84
hudakz 0:e29bc8e0dddd 85 #ifdef __cplusplus
hudakz 0:e29bc8e0dddd 86 };
hudakz 0:e29bc8e0dddd 87 #endif
hudakz 0:e29bc8e0dddd 88
hudakz 6:c5a40d5fd9f1 89 #endif // MBED_CAN_API_H
hudakz 14:0344705e6fb8 90
hudakz 16:f4c8f45bded9 91
hudakz 27:eed6929956ea 92
hudakz 27:eed6929956ea 93