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:
Wed Dec 30 08:39:54 2015 +0000
Revision:
17:1fd35431ee8e
Parent:
16:f4c8f45bded9
Child:
20:bcd8161f8f6c
Added support for NUCLEO-F072RB, NUCLEO-F091RC and NUCLEO446RE.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:e29bc8e0dddd 1 /*
hudakz 5:b53e5ee15315 2 ******************************************************************************
hudakz 5:b53e5ee15315 3 * @file can_api.c
hudakz 5:b53e5ee15315 4 * @author Zoltan Hudak
hudakz 5:b53e5ee15315 5 * @version
hudakz 5:b53e5ee15315 6 * @date 04-August-2015
hudakz 5:b53e5ee15315 7 * @brief CAN api for NUCLEO-F103RB platform
hudakz 5:b53e5ee15315 8 ******************************************************************************
hudakz 5:b53e5ee15315 9 * @attention
hudakz 5:b53e5ee15315 10 *
hudakz 5:b53e5ee15315 11 * <h2><center>&copy; COPYRIGHT(c) 2015 Zoltan Hudak <hudakz@inbox.com>
hudakz 5:b53e5ee15315 12 *
hudakz 5:b53e5ee15315 13 * All rights reserved.
hudakz 0:e29bc8e0dddd 14
hudakz 0:e29bc8e0dddd 15 This program is free software: you can redistribute it and/or modify
hudakz 0:e29bc8e0dddd 16 it under the terms of the GNU General Public License as published by
hudakz 0:e29bc8e0dddd 17 the Free Software Foundation, either version 3 of the License, or
hudakz 0:e29bc8e0dddd 18 (at your option) any later version.
hudakz 0:e29bc8e0dddd 19
hudakz 0:e29bc8e0dddd 20 This program is distributed in the hope that it will be useful,
hudakz 0:e29bc8e0dddd 21 but WITHOUT ANY WARRANTY; without even the implied warranty of
hudakz 0:e29bc8e0dddd 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
hudakz 0:e29bc8e0dddd 23 GNU General Public License for more details.
hudakz 0:e29bc8e0dddd 24
hudakz 0:e29bc8e0dddd 25 You should have received a copy of the GNU General Public License
hudakz 0:e29bc8e0dddd 26 along with this program. If not, see <http://www.gnu.org/licenses/>.
hudakz 0:e29bc8e0dddd 27 */
hudakz 0:e29bc8e0dddd 28 #include "can_api.h"
hudakz 0:e29bc8e0dddd 29 #include "can_helper.h"
hudakz 0:e29bc8e0dddd 30 #include "pinmap.h"
hudakz 0:e29bc8e0dddd 31
hudakz 0:e29bc8e0dddd 32 extern void (*rxCompleteCallback) (void);
hudakz 0:e29bc8e0dddd 33 extern CAN_HandleTypeDef _canHandle;
hudakz 0:e29bc8e0dddd 34
hudakz 0:e29bc8e0dddd 35 /**
hudakz 0:e29bc8e0dddd 36 * @brief
hudakz 0:e29bc8e0dddd 37 * @note
hudakz 0:e29bc8e0dddd 38 * @param
hudakz 0:e29bc8e0dddd 39 * @retval
hudakz 0:e29bc8e0dddd 40 */
hudakz 6:c5a40d5fd9f1 41 void can_init(can_t* obj, PinName rd, PinName td, FunctionalState abom) {
hudakz 6:c5a40d5fd9f1 42 initCAN(obj, rd, td, abom);
hudakz 0:e29bc8e0dddd 43 can_filter(obj, 0, 0, CANAny, 0);
hudakz 0:e29bc8e0dddd 44 }
hudakz 0:e29bc8e0dddd 45
hudakz 0:e29bc8e0dddd 46 /**
hudakz 0:e29bc8e0dddd 47 * @brief
hudakz 0:e29bc8e0dddd 48 * @note
hudakz 0:e29bc8e0dddd 49 * @param
hudakz 0:e29bc8e0dddd 50 * @retval
hudakz 0:e29bc8e0dddd 51 */
hudakz 0:e29bc8e0dddd 52 void can_free(can_t* obj) {
hudakz 15:5123ead7b002 53 HAL_CAN_MspDeInit(&_canHandle);
hudakz 0:e29bc8e0dddd 54 }
hudakz 0:e29bc8e0dddd 55
hudakz 0:e29bc8e0dddd 56 /**
hudakz 0:e29bc8e0dddd 57 * @brief
hudakz 0:e29bc8e0dddd 58 * @note
hudakz 0:e29bc8e0dddd 59 * @param
hudakz 0:e29bc8e0dddd 60 * @retval
hudakz 0:e29bc8e0dddd 61 */
hudakz 0:e29bc8e0dddd 62 int can_frequency(can_t* obj, int hz) {
hudakz 15:5123ead7b002 63 HAL_NVIC_DisableIRQ(CAN_IRQ);
hudakz 16:f4c8f45bded9 64
hudakz 16:f4c8f45bded9 65 #if defined(TARGET_NUCLEO_F072RB) || \
hudakz 16:f4c8f45bded9 66 defined(TARGET_NUCLEO_F091RC)
hudakz 16:f4c8f45bded9 67
hudakz 16:f4c8f45bded9 68 // APB1 peripheral clock = 48000000Hz
hudakz 16:f4c8f45bded9 69
hudakz 16:f4c8f45bded9 70 switch(hz) {
hudakz 16:f4c8f45bded9 71 case 1000000:
hudakz 16:f4c8f45bded9 72 // 1000kbps bit rate
hudakz 16:f4c8f45bded9 73 _canHandle.Init.Prescaler = 4; // number of time quanta = 48000000/4/1000000 = 12
hudakz 16:f4c8f45bded9 74 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 75 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 16:f4c8f45bded9 76 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 16:f4c8f45bded9 77 break;
hudakz 16:f4c8f45bded9 78
hudakz 16:f4c8f45bded9 79 case 500000:
hudakz 16:f4c8f45bded9 80 // 500kbps bit rate
hudakz 16:f4c8f45bded9 81 _canHandle.Init.Prescaler = 8; // number of time quanta = 48000000/8/500000 = 12
hudakz 16:f4c8f45bded9 82 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 83 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 16:f4c8f45bded9 84 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 16:f4c8f45bded9 85 break;
hudakz 16:f4c8f45bded9 86
hudakz 16:f4c8f45bded9 87 case 250000:
hudakz 16:f4c8f45bded9 88 // 250kbps
hudakz 16:f4c8f45bded9 89 _canHandle.Init.Prescaler = 12; // number of time quanta = 48000000/12/250000 = 16
hudakz 16:f4c8f45bded9 90 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 91 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 16:f4c8f45bded9 92 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 16:f4c8f45bded9 93 break;
hudakz 16:f4c8f45bded9 94
hudakz 16:f4c8f45bded9 95 case 125000:
hudakz 16:f4c8f45bded9 96 // 125kbps
hudakz 16:f4c8f45bded9 97 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16
hudakz 16:f4c8f45bded9 98 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 99 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 16:f4c8f45bded9 100 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 16:f4c8f45bded9 101 break;
hudakz 16:f4c8f45bded9 102
hudakz 16:f4c8f45bded9 103 default:
hudakz 16:f4c8f45bded9 104 // 125kbps (default)
hudakz 16:f4c8f45bded9 105 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16
hudakz 16:f4c8f45bded9 106 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 107 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 16:f4c8f45bded9 108 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 16:f4c8f45bded9 109 }
hudakz 0:e29bc8e0dddd 110
hudakz 16:f4c8f45bded9 111 #elif defined(TARGET_NUCLEO_F103RB) || \
hudakz 16:f4c8f45bded9 112 defined(TARGET_NUCLEO_F303RE) || \
hudakz 16:f4c8f45bded9 113 defined(TARGET_NUCLEO_F303K8) || \
hudakz 16:f4c8f45bded9 114 defined(TARGET_NUCLEO_F334R8) || \
hudakz 16:f4c8f45bded9 115 defined(TARGET_DISCO_F334C8)
hudakz 16:f4c8f45bded9 116
hudakz 5:b53e5ee15315 117 // APB1 peripheral clock = 36000000Hz
hudakz 0:e29bc8e0dddd 118
hudakz 0:e29bc8e0dddd 119 switch(hz) {
hudakz 0:e29bc8e0dddd 120 case 1000000:
hudakz 0:e29bc8e0dddd 121 // 1000kbps bit rate
hudakz 0:e29bc8e0dddd 122 _canHandle.Init.Prescaler = 3; // number of time quanta = 36000000/3/1000000 = 12
hudakz 0:e29bc8e0dddd 123 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 0:e29bc8e0dddd 124 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 0:e29bc8e0dddd 125 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 0:e29bc8e0dddd 126 break;
hudakz 0:e29bc8e0dddd 127
hudakz 0:e29bc8e0dddd 128 case 500000:
hudakz 0:e29bc8e0dddd 129 // 500kbps bit rate
hudakz 0:e29bc8e0dddd 130 _canHandle.Init.Prescaler = 6; // number of time quanta = 36000000/6/500000 = 12
hudakz 0:e29bc8e0dddd 131 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 0:e29bc8e0dddd 132 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 0:e29bc8e0dddd 133 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 0:e29bc8e0dddd 134 break;
hudakz 0:e29bc8e0dddd 135
hudakz 0:e29bc8e0dddd 136 case 250000:
hudakz 0:e29bc8e0dddd 137 // 250kbps
hudakz 0:e29bc8e0dddd 138 _canHandle.Init.Prescaler = 9; // number of time quanta = 36000000/9/250000 = 16
hudakz 0:e29bc8e0dddd 139 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 0:e29bc8e0dddd 140 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 0:e29bc8e0dddd 141 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 0:e29bc8e0dddd 142 break;
hudakz 0:e29bc8e0dddd 143
hudakz 0:e29bc8e0dddd 144 case 125000:
hudakz 0:e29bc8e0dddd 145 // 125kbps
hudakz 0:e29bc8e0dddd 146 _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16
hudakz 0:e29bc8e0dddd 147 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 0:e29bc8e0dddd 148 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 0:e29bc8e0dddd 149 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 0:e29bc8e0dddd 150 break;
hudakz 0:e29bc8e0dddd 151
hudakz 0:e29bc8e0dddd 152 default:
hudakz 0:e29bc8e0dddd 153 // 125kbps (default)
hudakz 5:b53e5ee15315 154 #if DEBUG
hudakz 0:e29bc8e0dddd 155 printf("Unknown frequency specified!\r\n");
hudakz 0:e29bc8e0dddd 156 printf("Using default 125kbps\r\n");
hudakz 5:b53e5ee15315 157 #endif
hudakz 17:1fd35431ee8e 158 _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16
hudakz 16:f4c8f45bded9 159 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 17:1fd35431ee8e 160 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 16:f4c8f45bded9 161 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 16:f4c8f45bded9 162 }
hudakz 16:f4c8f45bded9 163
hudakz 16:f4c8f45bded9 164 #elif defined(TARGET_NUCLEO_F446RE)
hudakz 16:f4c8f45bded9 165
hudakz 16:f4c8f45bded9 166 // APB1 peripheral clock = 45000000Hz
hudakz 16:f4c8f45bded9 167
hudakz 16:f4c8f45bded9 168 switch(hz) {
hudakz 16:f4c8f45bded9 169 case 1000000:
hudakz 16:f4c8f45bded9 170 // 1000kbps bit rate
hudakz 16:f4c8f45bded9 171 _canHandle.Init.Prescaler = 5; // number of time quanta = 45000000/5/1000000 = 9
hudakz 16:f4c8f45bded9 172 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 173 _canHandle.Init.BS1 = CAN_BS1_6TQ; // sample point at: (1 + 6) / 9 * 100 = 77.78%
hudakz 16:f4c8f45bded9 174 _canHandle.Init.BS2 = CAN_BS2_2TQ;
hudakz 16:f4c8f45bded9 175 break;
hudakz 16:f4c8f45bded9 176
hudakz 16:f4c8f45bded9 177 case 500000:
hudakz 16:f4c8f45bded9 178 // 500kbps bit rate
hudakz 16:f4c8f45bded9 179 _canHandle.Init.Prescaler = 10; // number of time quanta = 45000000/10/500000 = 9
hudakz 16:f4c8f45bded9 180 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 181 _canHandle.Init.BS1 = CAN_BS1_6TQ; // sample point at: (1 + 6) / 9 * 100 = 77.78%
hudakz 16:f4c8f45bded9 182 _canHandle.Init.BS2 = CAN_BS2_2TQ;
hudakz 16:f4c8f45bded9 183 break;
hudakz 16:f4c8f45bded9 184
hudakz 16:f4c8f45bded9 185 case 250000:
hudakz 16:f4c8f45bded9 186 // 250kbps
hudakz 16:f4c8f45bded9 187 _canHandle.Init.Prescaler = 15; // number of time quanta = 45000000/15/250000 = 12
hudakz 16:f4c8f45bded9 188 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 189 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 16:f4c8f45bded9 190 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 16:f4c8f45bded9 191 break;
hudakz 16:f4c8f45bded9 192
hudakz 16:f4c8f45bded9 193 case 125000:
hudakz 16:f4c8f45bded9 194 // 125kbps
hudakz 16:f4c8f45bded9 195 _canHandle.Init.Prescaler = 30; // number of time quanta = 45000000/30/125000 = 12
hudakz 16:f4c8f45bded9 196 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 197 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 16:f4c8f45bded9 198 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 16:f4c8f45bded9 199 break;
hudakz 16:f4c8f45bded9 200
hudakz 16:f4c8f45bded9 201 default:
hudakz 16:f4c8f45bded9 202 // 125kbps (default)
hudakz 16:f4c8f45bded9 203 #if DEBUG
hudakz 16:f4c8f45bded9 204 printf("Unknown frequency specified!\r\n");
hudakz 16:f4c8f45bded9 205 printf("Using default 125kbps\r\n");
hudakz 16:f4c8f45bded9 206 #endif
hudakz 17:1fd35431ee8e 207 _canHandle.Init.Prescaler = 30; // number of time quanta = 45000000/30/125000 = 12
hudakz 0:e29bc8e0dddd 208 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 17:1fd35431ee8e 209 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
hudakz 17:1fd35431ee8e 210 _canHandle.Init.BS2 = CAN_BS2_3TQ;
hudakz 0:e29bc8e0dddd 211 }
hudakz 16:f4c8f45bded9 212
hudakz 16:f4c8f45bded9 213 #endif
hudakz 0:e29bc8e0dddd 214
hudakz 0:e29bc8e0dddd 215 HAL_CAN_Init(&_canHandle);
hudakz 15:5123ead7b002 216 HAL_NVIC_EnableIRQ(CAN_IRQ);
hudakz 11:439f3a34c42e 217
hudakz 5:b53e5ee15315 218 return 1;
hudakz 0:e29bc8e0dddd 219 }
hudakz 0:e29bc8e0dddd 220
hudakz 0:e29bc8e0dddd 221 /**
hudakz 0:e29bc8e0dddd 222 * @brief
hudakz 0:e29bc8e0dddd 223 * @note
hudakz 0:e29bc8e0dddd 224 * @param
hudakz 0:e29bc8e0dddd 225 * @retval
hudakz 0:e29bc8e0dddd 226 */
hudakz 0:e29bc8e0dddd 227 void can_irq_init(can_t* obj, can_irq_handler handler, uint32_t id) {
hudakz 0:e29bc8e0dddd 228 if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) {
hudakz 5:b53e5ee15315 229 #ifdef DEBUG
hudakz 0:e29bc8e0dddd 230 printf("CAN reception initialization error\r\n");
hudakz 5:b53e5ee15315 231 #endif
hudakz 0:e29bc8e0dddd 232 }
hudakz 0:e29bc8e0dddd 233 }
hudakz 0:e29bc8e0dddd 234
hudakz 0:e29bc8e0dddd 235 /**
hudakz 0:e29bc8e0dddd 236 * @brief
hudakz 0:e29bc8e0dddd 237 * @note
hudakz 0:e29bc8e0dddd 238 * @param
hudakz 0:e29bc8e0dddd 239 * @retval
hudakz 0:e29bc8e0dddd 240 */
hudakz 0:e29bc8e0dddd 241 void can_irq_free(can_t* obj) {
hudakz 11:439f3a34c42e 242 rxCompleteCallback = 0;
hudakz 0:e29bc8e0dddd 243 }
hudakz 0:e29bc8e0dddd 244
hudakz 0:e29bc8e0dddd 245 /**
hudakz 0:e29bc8e0dddd 246 * @brief
hudakz 0:e29bc8e0dddd 247 * @note
hudakz 0:e29bc8e0dddd 248 * @param
hudakz 0:e29bc8e0dddd 249 * @retval
hudakz 0:e29bc8e0dddd 250 */
hudakz 0:e29bc8e0dddd 251 void can_irq_set(void (*fptr) (void)) {
hudakz 0:e29bc8e0dddd 252 rxCompleteCallback = fptr;
hudakz 0:e29bc8e0dddd 253 }
hudakz 0:e29bc8e0dddd 254
hudakz 0:e29bc8e0dddd 255 /**
hudakz 0:e29bc8e0dddd 256 * @brief
hudakz 0:e29bc8e0dddd 257 * @note
hudakz 0:e29bc8e0dddd 258 * @param
hudakz 0:e29bc8e0dddd 259 * @retval
hudakz 0:e29bc8e0dddd 260 */
hudakz 0:e29bc8e0dddd 261 int can_write(can_t* obj, CAN_Message msg, int cc) {
hudakz 0:e29bc8e0dddd 262 int i = 0;
hudakz 0:e29bc8e0dddd 263
hudakz 0:e29bc8e0dddd 264 if(msg.format == CANStandard) {
hudakz 0:e29bc8e0dddd 265 _canHandle.pTxMsg->StdId = msg.id;
hudakz 0:e29bc8e0dddd 266 _canHandle.pTxMsg->ExtId = 0x00;
hudakz 0:e29bc8e0dddd 267 }
hudakz 0:e29bc8e0dddd 268 else {
hudakz 0:e29bc8e0dddd 269 _canHandle.pTxMsg->StdId = 0x00;
hudakz 0:e29bc8e0dddd 270 _canHandle.pTxMsg->ExtId = msg.id;
hudakz 0:e29bc8e0dddd 271 }
hudakz 0:e29bc8e0dddd 272
hudakz 0:e29bc8e0dddd 273 _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE;
hudakz 0:e29bc8e0dddd 274 _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT;
hudakz 0:e29bc8e0dddd 275 _canHandle.pTxMsg->DLC = msg.len;
hudakz 0:e29bc8e0dddd 276
hudakz 0:e29bc8e0dddd 277 for(i = 0; i < msg.len; i++)
hudakz 0:e29bc8e0dddd 278 _canHandle.pTxMsg->Data[i] = msg.data[i];
hudakz 0:e29bc8e0dddd 279
hudakz 0:e29bc8e0dddd 280 if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) {
hudakz 5:b53e5ee15315 281 #ifdef DEBUG
hudakz 0:e29bc8e0dddd 282 printf("Transmission error\r\n");
hudakz 5:b53e5ee15315 283 #endif
hudakz 5:b53e5ee15315 284 return 0;
hudakz 0:e29bc8e0dddd 285 }
hudakz 5:b53e5ee15315 286 else
hudakz 5:b53e5ee15315 287 return 1;
hudakz 0:e29bc8e0dddd 288 }
hudakz 0:e29bc8e0dddd 289
hudakz 0:e29bc8e0dddd 290 /**
hudakz 0:e29bc8e0dddd 291 * @brief
hudakz 0:e29bc8e0dddd 292 * @note
hudakz 0:e29bc8e0dddd 293 * @param
hudakz 0:e29bc8e0dddd 294 * @retval
hudakz 0:e29bc8e0dddd 295 */
hudakz 0:e29bc8e0dddd 296 int can_read(can_t* obj, CAN_Message* msg, int handle) {
hudakz 10:227a455d0f9f 297 int i;
hudakz 0:e29bc8e0dddd 298 msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId;
hudakz 0:e29bc8e0dddd 299 msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote;
hudakz 0:e29bc8e0dddd 300 msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended;
hudakz 0:e29bc8e0dddd 301 msg->len = _canHandle.pRxMsg->DLC;
hudakz 10:227a455d0f9f 302 for(i = 0; i < msg->len; i++)
hudakz 0:e29bc8e0dddd 303 msg->data[i] = _canHandle.pRxMsg->Data[i];
hudakz 5:b53e5ee15315 304
hudakz 5:b53e5ee15315 305 return msg->len;
hudakz 0:e29bc8e0dddd 306 }
hudakz 0:e29bc8e0dddd 307
hudakz 0:e29bc8e0dddd 308 /**
hudakz 0:e29bc8e0dddd 309 * @brief
hudakz 0:e29bc8e0dddd 310 * @note
hudakz 0:e29bc8e0dddd 311 * @param
hudakz 0:e29bc8e0dddd 312 * @retval
hudakz 0:e29bc8e0dddd 313 */
hudakz 0:e29bc8e0dddd 314 int can_mode(can_t* obj, CanMode mode) {
hudakz 0:e29bc8e0dddd 315 switch(mode) {
hudakz 0:e29bc8e0dddd 316 case MODE_RESET:
hudakz 0:e29bc8e0dddd 317 return HAL_ERROR;
hudakz 0:e29bc8e0dddd 318
hudakz 0:e29bc8e0dddd 319 case MODE_NORMAL:
hudakz 0:e29bc8e0dddd 320 _canHandle.Init.Mode = CAN_MODE_NORMAL;
hudakz 0:e29bc8e0dddd 321 break;
hudakz 0:e29bc8e0dddd 322
hudakz 0:e29bc8e0dddd 323 case MODE_SILENT:
hudakz 0:e29bc8e0dddd 324 _canHandle.Init.Mode = CAN_MODE_SILENT;
hudakz 0:e29bc8e0dddd 325 break;
hudakz 0:e29bc8e0dddd 326
hudakz 0:e29bc8e0dddd 327 case MODE_TEST_GLOBAL:
hudakz 0:e29bc8e0dddd 328 _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
hudakz 0:e29bc8e0dddd 329 break;
hudakz 0:e29bc8e0dddd 330
hudakz 0:e29bc8e0dddd 331 case MODE_TEST_LOCAL:
hudakz 0:e29bc8e0dddd 332 _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
hudakz 0:e29bc8e0dddd 333 break;
hudakz 0:e29bc8e0dddd 334
hudakz 0:e29bc8e0dddd 335 case MODE_TEST_SILENT:
hudakz 0:e29bc8e0dddd 336 _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
hudakz 0:e29bc8e0dddd 337 break;
hudakz 0:e29bc8e0dddd 338 }
hudakz 0:e29bc8e0dddd 339
hudakz 3:0fae6b54a2ee 340 return HAL_CAN_Init(&_canHandle);
hudakz 0:e29bc8e0dddd 341 }
hudakz 0:e29bc8e0dddd 342
hudakz 0:e29bc8e0dddd 343 /**
hudakz 0:e29bc8e0dddd 344 * @brief
hudakz 0:e29bc8e0dddd 345 * @note
hudakz 0:e29bc8e0dddd 346 * @param
hudakz 0:e29bc8e0dddd 347 * @retval
hudakz 0:e29bc8e0dddd 348 */
hudakz 0:e29bc8e0dddd 349 int can_filter(can_t* obj, uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) {
hudakz 0:e29bc8e0dddd 350 CAN_FilterConfTypeDef sFilterConfig;
hudakz 0:e29bc8e0dddd 351
hudakz 8:5c90d6b9a382 352 sFilterConfig.FilterNumber = handle; // Specifies the filter number (must be a number between 0 and 13 at 32-bit filter scale)
hudakz 0:e29bc8e0dddd 353 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
hudakz 0:e29bc8e0dddd 354 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
hudakz 0:e29bc8e0dddd 355 sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF);
hudakz 0:e29bc8e0dddd 356 sFilterConfig.FilterIdLow = ((id) & 0xFFFF);
hudakz 0:e29bc8e0dddd 357 sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF);
hudakz 0:e29bc8e0dddd 358 sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF);
hudakz 0:e29bc8e0dddd 359 sFilterConfig.FilterFIFOAssignment = 0;
hudakz 0:e29bc8e0dddd 360 sFilterConfig.FilterActivation = ENABLE;
hudakz 8:5c90d6b9a382 361 sFilterConfig.BankNumber = 0; // Selects the start bank filter
hudakz 8:5c90d6b9a382 362 return HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig);
hudakz 0:e29bc8e0dddd 363 }
hudakz 0:e29bc8e0dddd 364
hudakz 0:e29bc8e0dddd 365 /**
hudakz 0:e29bc8e0dddd 366 * @brief
hudakz 0:e29bc8e0dddd 367 * @note
hudakz 0:e29bc8e0dddd 368 * @param
hudakz 0:e29bc8e0dddd 369 * @retval
hudakz 0:e29bc8e0dddd 370 */
hudakz 0:e29bc8e0dddd 371 void can_reset(can_t* obj) {
hudakz 0:e29bc8e0dddd 372 __HAL_CAN_RESET_HANDLE_STATE(&_canHandle);
hudakz 0:e29bc8e0dddd 373 }
hudakz 0:e29bc8e0dddd 374
hudakz 0:e29bc8e0dddd 375 /**
hudakz 0:e29bc8e0dddd 376 * @brief
hudakz 0:e29bc8e0dddd 377 * @note
hudakz 0:e29bc8e0dddd 378 * @param
hudakz 0:e29bc8e0dddd 379 * @retval
hudakz 0:e29bc8e0dddd 380 */
hudakz 0:e29bc8e0dddd 381 unsigned char can_rderror(can_t* obj) {
hudakz 0:e29bc8e0dddd 382 return HAL_CAN_GetError(&_canHandle);
hudakz 0:e29bc8e0dddd 383 }
hudakz 0:e29bc8e0dddd 384
hudakz 0:e29bc8e0dddd 385 /**
hudakz 0:e29bc8e0dddd 386 * @brief
hudakz 0:e29bc8e0dddd 387 * @note
hudakz 0:e29bc8e0dddd 388 * @param
hudakz 0:e29bc8e0dddd 389 * @retval
hudakz 0:e29bc8e0dddd 390 */
hudakz 0:e29bc8e0dddd 391 unsigned char can_tderror(can_t* obj) {
hudakz 0:e29bc8e0dddd 392 return HAL_CAN_GetError(&_canHandle);
hudakz 0:e29bc8e0dddd 393 }
hudakz 0:e29bc8e0dddd 394
hudakz 0:e29bc8e0dddd 395 /**
hudakz 0:e29bc8e0dddd 396 * @brief
hudakz 0:e29bc8e0dddd 397 * @note
hudakz 0:e29bc8e0dddd 398 * @param
hudakz 0:e29bc8e0dddd 399 * @retval
hudakz 0:e29bc8e0dddd 400 */
hudakz 0:e29bc8e0dddd 401 void can_monitor(can_t* obj, int silent) {
hudakz 0:e29bc8e0dddd 402
hudakz 0:e29bc8e0dddd 403 // not implemented
hudakz 0:e29bc8e0dddd 404 }
hudakz 1:eb04f7f0478d 405
hudakz 5:b53e5ee15315 406
hudakz 6:c5a40d5fd9f1 407
hudakz 11:439f3a34c42e 408
hudakz 12:c45310ff2233 409