Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of CANnucleo by
can_api.c
00001 /* 00002 ****************************************************************************** 00003 * @file can_api.c 00004 * @author Zoltan Hudak 00005 * @version 00006 * @date 04-August-2015 00007 * @brief CAN api for NUCLEO-F103RB platform 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2015 Zoltan Hudak <hudakz@inbox.com> 00012 * 00013 * All rights reserved. 00014 00015 This program is free software: you can redistribute it and/or modify 00016 it under the terms of the GNU General Public License as published by 00017 the Free Software Foundation, either version 3 of the License, or 00018 (at your option) any later version. 00019 00020 This program is distributed in the hope that it will be useful, 00021 but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 GNU General Public License for more details. 00024 00025 You should have received a copy of the GNU General Public License 00026 along with this program. If not, see <http://www.gnu.org/licenses/>. 00027 */ 00028 #include "can_api.h" 00029 #include "can_helper.h" 00030 #include "pinmap.h" 00031 00032 extern void (*rxCompleteCallback) (void); 00033 extern CAN_HandleTypeDef _canHandle; 00034 00035 /** 00036 * @brief 00037 * @note 00038 * @param 00039 * @retval 00040 */ 00041 void can_init(can_t* obj, PinName rd, PinName td, FunctionalState abom) { 00042 initCAN(obj, rd, td, abom); 00043 can_filter(obj, 0, 0, CANAny, 0); 00044 } 00045 00046 /** 00047 * @brief 00048 * @note 00049 * @param 00050 * @retval 00051 */ 00052 void can_free(can_t* obj) { 00053 HAL_CAN_MspDeInit(&_canHandle); 00054 } 00055 00056 /** 00057 * @brief 00058 * @note 00059 * @param 00060 * @retval 00061 */ 00062 int can_frequency(can_t* obj, int hz) { 00063 HAL_NVIC_DisableIRQ(CAN_IRQ); 00064 00065 #if defined(TARGET_NUCLEO_F072RB) || \ 00066 defined(TARGET_NUCLEO_F091RC) 00067 00068 // APB1 peripheral clock = 48000000Hz 00069 00070 switch(hz) { 00071 case 1000000: 00072 // 1000kbps bit rate 00073 _canHandle.Init.Prescaler = 4; // number of time quanta = 48000000/4/1000000 = 12 00074 _canHandle.Init.SJW = CAN_SJW_1TQ; 00075 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00076 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00077 break; 00078 00079 case 500000: 00080 // 500kbps bit rate 00081 _canHandle.Init.Prescaler = 8; // number of time quanta = 48000000/8/500000 = 12 00082 _canHandle.Init.SJW = CAN_SJW_1TQ; 00083 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00084 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00085 break; 00086 00087 case 250000: 00088 // 250kbps 00089 _canHandle.Init.Prescaler = 12; // number of time quanta = 48000000/12/250000 = 16 00090 _canHandle.Init.SJW = CAN_SJW_1TQ; 00091 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00092 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00093 break; 00094 00095 case 125000: 00096 // 125kbps 00097 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 00098 _canHandle.Init.SJW = CAN_SJW_1TQ; 00099 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00100 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00101 break; 00102 00103 default: 00104 // 125kbps (default) 00105 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 00106 _canHandle.Init.SJW = CAN_SJW_1TQ; 00107 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00108 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00109 } 00110 00111 #elif defined(TARGET_NUCLEO_F103RB) || \ 00112 defined(TARGET_NUCLEO_F303RE) || \ 00113 defined(TARGET_NUCLEO_F303K8) || \ 00114 defined(TARGET_NUCLEO_F334R8) || \ 00115 defined(TARGET_DISCO_F334C8) 00116 00117 // APB1 peripheral clock = 36000000Hz 00118 00119 switch(hz) { 00120 case 1000000: 00121 // 1000kbps bit rate 00122 _canHandle.Init.Prescaler = 3; // number of time quanta = 36000000/3/1000000 = 12 00123 _canHandle.Init.SJW = CAN_SJW_1TQ; 00124 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00125 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00126 break; 00127 00128 case 500000: 00129 // 500kbps bit rate 00130 _canHandle.Init.Prescaler = 6; // number of time quanta = 36000000/6/500000 = 12 00131 _canHandle.Init.SJW = CAN_SJW_1TQ; 00132 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00133 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00134 break; 00135 00136 case 250000: 00137 // 250kbps 00138 _canHandle.Init.Prescaler = 9; // number of time quanta = 36000000/9/250000 = 16 00139 _canHandle.Init.SJW = CAN_SJW_1TQ; 00140 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00141 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00142 break; 00143 00144 case 125000: 00145 // 125kbps 00146 _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 00147 _canHandle.Init.SJW = CAN_SJW_1TQ; 00148 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00149 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00150 break; 00151 00152 default: 00153 // 125kbps (default) 00154 #if DEBUG 00155 printf("Unknown frequency specified!\r\n"); 00156 printf("Using default 125kbps\r\n"); 00157 #endif 00158 _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 00159 _canHandle.Init.SJW = CAN_SJW_1TQ; 00160 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00161 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00162 } 00163 00164 #elif defined(TARGET_NUCLEO_F446RE) 00165 00166 // APB1 peripheral clock = 45000000Hz 00167 00168 switch(hz) { 00169 case 1000000: 00170 // 1000kbps bit rate 00171 _canHandle.Init.Prescaler = 5; // number of time quanta = 45000000/5/1000000 = 9 00172 _canHandle.Init.SJW = CAN_SJW_1TQ; 00173 _canHandle.Init.BS1 = CAN_BS1_6TQ; // sample point at: (1 + 6) / 9 * 100 = 77.78% 00174 _canHandle.Init.BS2 = CAN_BS2_2TQ; 00175 break; 00176 00177 case 500000: 00178 // 500kbps bit rate 00179 _canHandle.Init.Prescaler = 10; // number of time quanta = 45000000/10/500000 = 9 00180 _canHandle.Init.SJW = CAN_SJW_1TQ; 00181 _canHandle.Init.BS1 = CAN_BS1_6TQ; // sample point at: (1 + 6) / 9 * 100 = 77.78% 00182 _canHandle.Init.BS2 = CAN_BS2_2TQ; 00183 break; 00184 00185 case 250000: 00186 // 250kbps 00187 _canHandle.Init.Prescaler = 15; // number of time quanta = 45000000/15/250000 = 12 00188 _canHandle.Init.SJW = CAN_SJW_1TQ; 00189 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00190 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00191 break; 00192 00193 case 125000: 00194 // 125kbps 00195 _canHandle.Init.Prescaler = 30; // number of time quanta = 45000000/30/125000 = 12 00196 _canHandle.Init.SJW = CAN_SJW_1TQ; 00197 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00198 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00199 break; 00200 00201 default: 00202 // 125kbps (default) 00203 #if DEBUG 00204 printf("Unknown frequency specified!\r\n"); 00205 printf("Using default 125kbps\r\n"); 00206 #endif 00207 _canHandle.Init.Prescaler = 30; // number of time quanta = 45000000/30/125000 = 12 00208 _canHandle.Init.SJW = CAN_SJW_1TQ; 00209 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00210 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00211 } 00212 00213 #endif 00214 00215 HAL_CAN_Init(&_canHandle); 00216 HAL_NVIC_EnableIRQ(CAN_IRQ); 00217 00218 return 1; 00219 } 00220 00221 /** 00222 * @brief 00223 * @note 00224 * @param 00225 * @retval 00226 */ 00227 void can_irq_init(can_t* obj, can_irq_handler handler, uint32_t id) { 00228 if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) { 00229 #ifdef DEBUG 00230 printf("CAN reception initialization error\r\n"); 00231 #endif 00232 } 00233 } 00234 00235 /** 00236 * @brief 00237 * @note 00238 * @param 00239 * @retval 00240 */ 00241 void can_irq_free(can_t* obj) { 00242 rxCompleteCallback = 0; 00243 } 00244 00245 /** 00246 * @brief 00247 * @note 00248 * @param 00249 * @retval 00250 */ 00251 void can_irq_set(void (*fptr) (void)) { 00252 rxCompleteCallback = fptr; 00253 } 00254 00255 /** 00256 * @brief 00257 * @note 00258 * @param 00259 * @retval 00260 */ 00261 int can_write(can_t* obj, CAN_Message msg, int cc) { 00262 int i = 0; 00263 00264 if(msg.format == CANStandard) { 00265 _canHandle.pTxMsg->StdId = msg.id; 00266 _canHandle.pTxMsg->ExtId = 0x00; 00267 } 00268 else { 00269 _canHandle.pTxMsg->StdId = 0x00; 00270 _canHandle.pTxMsg->ExtId = msg.id; 00271 } 00272 00273 _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE; 00274 _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT; 00275 _canHandle.pTxMsg->DLC = msg.len; 00276 00277 for(i = 0; i < msg.len; i++) 00278 _canHandle.pTxMsg->Data[i] = msg.data[i]; 00279 00280 if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) { 00281 #ifdef DEBUG 00282 printf("Transmission error\r\n"); 00283 #endif 00284 return 0; 00285 } 00286 else 00287 return 1; 00288 } 00289 00290 /** 00291 * @brief 00292 * @note 00293 * @param 00294 * @retval 00295 */ 00296 int can_read(can_t* obj, CAN_Message* msg, int handle) { 00297 int i; 00298 msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId; 00299 msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote; 00300 msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended; 00301 msg->len = _canHandle.pRxMsg->DLC; 00302 for(i = 0; i < msg->len; i++) 00303 msg->data[i] = _canHandle.pRxMsg->Data[i]; 00304 00305 return msg->len; 00306 } 00307 00308 /** 00309 * @brief 00310 * @note 00311 * @param 00312 * @retval 00313 */ 00314 int can_mode(can_t* obj, CanMode mode) { 00315 switch(mode) { 00316 case MODE_RESET: 00317 return HAL_ERROR; 00318 00319 case MODE_NORMAL: 00320 _canHandle.Init.Mode = CAN_MODE_NORMAL; 00321 break; 00322 00323 case MODE_SILENT: 00324 _canHandle.Init.Mode = CAN_MODE_SILENT; 00325 break; 00326 00327 case MODE_TEST_GLOBAL: 00328 _canHandle.Init.Mode = CAN_MODE_LOOPBACK; 00329 break; 00330 00331 case MODE_TEST_LOCAL: 00332 _canHandle.Init.Mode = CAN_MODE_LOOPBACK; 00333 break; 00334 00335 case MODE_TEST_SILENT: 00336 _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK; 00337 break; 00338 } 00339 00340 return HAL_CAN_Init(&_canHandle); 00341 } 00342 00343 /** 00344 * @brief 00345 * @note 00346 * @param 00347 * @retval 00348 */ 00349 int can_filter(can_t* obj, uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) { 00350 CAN_FilterConfTypeDef sFilterConfig; 00351 00352 sFilterConfig.FilterNumber = handle; // Specifies the filter number (must be a number between 0 and 13 at 32-bit filter scale) 00353 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; 00354 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; 00355 sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF); 00356 sFilterConfig.FilterIdLow = ((id) & 0xFFFF); 00357 sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF); 00358 sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF); 00359 sFilterConfig.FilterFIFOAssignment = 0; 00360 sFilterConfig.FilterActivation = ENABLE; 00361 sFilterConfig.BankNumber = 0; // Selects the start bank filter 00362 return HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig); 00363 } 00364 00365 /** 00366 * @brief 00367 * @note 00368 * @param 00369 * @retval 00370 */ 00371 void can_reset(can_t* obj) { 00372 __HAL_CAN_RESET_HANDLE_STATE(&_canHandle); 00373 } 00374 00375 /** 00376 * @brief 00377 * @note 00378 * @param 00379 * @retval 00380 */ 00381 unsigned char can_rderror(can_t* obj) { 00382 return HAL_CAN_GetError(&_canHandle); 00383 } 00384 00385 /** 00386 * @brief 00387 * @note 00388 * @param 00389 * @retval 00390 */ 00391 unsigned char can_tderror(can_t* obj) { 00392 return HAL_CAN_GetError(&_canHandle); 00393 } 00394 00395 /** 00396 * @brief 00397 * @note 00398 * @param 00399 * @retval 00400 */ 00401 void can_monitor(can_t* obj, int silent) { 00402 00403 // not implemented 00404 } 00405 00406 00407 00408 00409
Generated on Tue Jul 12 2022 20:03:31 by
1.7.2
