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 Jul 19 09:06:26 2015 +0000
Revision:
0:e29bc8e0dddd
Child:
1:eb04f7f0478d
rev 00

Who changed what in which revision?

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