pub
Fork of CANnucleo by
Embed:
(wiki syntax)
Show/hide line numbers
cannucleo_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@outlook.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 "cannucleo_api.h" 00029 #include "can_helper.h" 00030 #include "pinmap.h" 00031 00032 extern void (*rxCompleteCallback)(void); 00033 extern CAN_HandleTypeDef _canHandle; 00034 00035 static uint32_t irq_id = 0; 00036 static can_irq_handler irq_handler = 0; 00037 00038 /** 00039 * @brief 00040 * @note 00041 * @param 00042 * @retval 00043 */ 00044 void can_init(PinName rd, PinName td, FunctionalState abom) { 00045 initCAN(rd, td, abom); 00046 can_filter(0, 0, CANAny, 0); 00047 } 00048 00049 /** 00050 * @brief 00051 * @note 00052 * @param 00053 * @retval 00054 */ 00055 void can_free(void) { 00056 HAL_CAN_MspDeInit(&_canHandle); 00057 } 00058 00059 /** 00060 * @brief 00061 * @note 00062 * @param 00063 * @retval 00064 */ 00065 int can_frequency(int hz) { 00066 HAL_NVIC_DisableIRQ(CAN_IRQ); 00067 00068 #if defined(TARGET_NUCLEO_F072RB) || \ 00069 defined(TARGET_NUCLEO_F091RC) 00070 00071 // APB1 peripheral clock = 48000000Hz 00072 00073 switch(hz) { 00074 case 1000000: 00075 // 1000kbps bit rate 00076 _canHandle.Init.Prescaler = 4; // number of time quanta = 48000000/4/1000000 = 12 00077 _canHandle.Init.SJW = CAN_SJW_1TQ; 00078 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00079 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00080 break; 00081 00082 case 500000: 00083 // 500kbps bit rate 00084 _canHandle.Init.Prescaler = 8; // number of time quanta = 48000000/8/500000 = 12 00085 _canHandle.Init.SJW = CAN_SJW_1TQ; 00086 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00087 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00088 break; 00089 00090 case 250000: 00091 // 250kbps 00092 _canHandle.Init.Prescaler = 12; // number of time quanta = 48000000/12/250000 = 16 00093 _canHandle.Init.SJW = CAN_SJW_1TQ; 00094 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00095 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00096 break; 00097 00098 case 125000: 00099 // 125kbps 00100 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 00101 _canHandle.Init.SJW = CAN_SJW_1TQ; 00102 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00103 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00104 break; 00105 00106 default: 00107 // 125kbps (default) 00108 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 00109 _canHandle.Init.SJW = CAN_SJW_1TQ; 00110 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00111 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00112 } 00113 00114 #elif defined(TARGET_NUCLEO_F103RB) || \ 00115 defined(TARGET_NUCLEO_F303RE) || \ 00116 defined(TARGET_NUCLEO_F334R8) || \ 00117 defined(TARGET_DISCO_F334C8) 00118 00119 // APB1 peripheral clock = 36000000Hz 00120 00121 switch(hz) { 00122 case 1000000: 00123 // 1000kbps bit rate 00124 _canHandle.Init.Prescaler = 3; // number of time quanta = 36000000/3/1000000 = 12 00125 _canHandle.Init.SJW = CAN_SJW_1TQ; 00126 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00127 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00128 break; 00129 00130 case 500000: 00131 // 500kbps bit rate 00132 _canHandle.Init.Prescaler = 6; // number of time quanta = 36000000/6/500000 = 12 00133 _canHandle.Init.SJW = CAN_SJW_1TQ; 00134 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00135 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00136 break; 00137 00138 case 250000: 00139 // 250kbps 00140 _canHandle.Init.Prescaler = 9; // number of time quanta = 36000000/9/250000 = 16 00141 _canHandle.Init.SJW = CAN_SJW_1TQ; 00142 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00143 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00144 break; 00145 00146 case 125000: 00147 // 125kbps 00148 _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 00149 _canHandle.Init.SJW = CAN_SJW_1TQ; 00150 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00151 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00152 break; 00153 00154 default: 00155 // 125kbps (default) 00156 #if DEBUG 00157 printf("Unknown frequency specified!\r\n"); 00158 printf("Using default 125kbps\r\n"); 00159 #endif 00160 _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 00161 _canHandle.Init.SJW = CAN_SJW_1TQ; 00162 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00163 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00164 } 00165 00166 #elif defined(TARGET_NUCLEO_F303K8) 00167 00168 // APB1 peripheral clock = 32000000Hz 00169 00170 switch(hz) { 00171 case 1000000: 00172 // 1000kbps bit rate 00173 _canHandle.Init.Prescaler = 2; // number of time quanta = 32000000/2/1000000 = 16 00174 _canHandle.Init.SJW = CAN_SJW_1TQ; 00175 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00176 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00177 break; 00178 00179 case 500000: 00180 // 500kbps bit rate 00181 _canHandle.Init.Prescaler = 4; // number of time quanta = 32000000/4/500000 = 16 00182 _canHandle.Init.SJW = CAN_SJW_1TQ; 00183 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00184 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00185 break; 00186 00187 case 250000: 00188 // 250kbps 00189 _canHandle.Init.Prescaler = 8; // number of time quanta = 32000000/8/250000 = 16 00190 _canHandle.Init.SJW = CAN_SJW_1TQ; 00191 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00192 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00193 break; 00194 00195 case 125000: 00196 // 125kbps 00197 _canHandle.Init.Prescaler = 16; // number of time quanta = 32000000/16/125000 = 16 00198 _canHandle.Init.SJW = CAN_SJW_1TQ; 00199 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00200 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00201 break; 00202 00203 default: 00204 // 125kbps (default) 00205 #if DEBUG 00206 printf("Unknown frequency specified!\r\n"); 00207 printf("Using default 125kbps\r\n"); 00208 #endif 00209 _canHandle.Init.Prescaler = 16; // number of time quanta = 32000000/16/125000 = 16 00210 _canHandle.Init.SJW = CAN_SJW_1TQ; 00211 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% 00212 _canHandle.Init.BS2 = CAN_BS2_4TQ; 00213 } 00214 00215 #elif defined(TARGET_NUCLEO_F446RE) 00216 00217 // APB1 peripheral clock = 45000000Hz 00218 00219 switch(hz) { 00220 case 1000000: 00221 // 1000kbps bit rate 00222 _canHandle.Init.Prescaler = 5; // number of time quanta = 45000000/5/1000000 = 9 00223 _canHandle.Init.SJW = CAN_SJW_1TQ; 00224 _canHandle.Init.BS1 = CAN_BS1_6TQ; // sample point at: (1 + 6) / 9 * 100 = 77.78% 00225 _canHandle.Init.BS2 = CAN_BS2_2TQ; 00226 break; 00227 00228 case 500000: 00229 // 500kbps bit rate 00230 _canHandle.Init.Prescaler = 10; // number of time quanta = 45000000/10/500000 = 9 00231 _canHandle.Init.SJW = CAN_SJW_1TQ; 00232 _canHandle.Init.BS1 = CAN_BS1_6TQ; // sample point at: (1 + 6) / 9 * 100 = 77.78% 00233 _canHandle.Init.BS2 = CAN_BS2_2TQ; 00234 break; 00235 00236 case 250000: 00237 // 250kbps 00238 _canHandle.Init.Prescaler = 15; // number of time quanta = 45000000/15/250000 = 12 00239 _canHandle.Init.SJW = CAN_SJW_1TQ; 00240 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00241 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00242 break; 00243 00244 case 125000: 00245 // 125kbps 00246 _canHandle.Init.Prescaler = 30; // number of time quanta = 45000000/30/125000 = 12 00247 _canHandle.Init.SJW = CAN_SJW_1TQ; 00248 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00249 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00250 break; 00251 00252 default: 00253 // 125kbps (default) 00254 #if DEBUG 00255 printf("Unknown frequency specified!\r\n"); 00256 printf("Using default 125kbps\r\n"); 00257 #endif 00258 _canHandle.Init.Prescaler = 30; // number of time quanta = 45000000/30/125000 = 12 00259 _canHandle.Init.SJW = CAN_SJW_1TQ; 00260 _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% 00261 _canHandle.Init.BS2 = CAN_BS2_3TQ; 00262 } 00263 00264 #endif 00265 00266 HAL_CAN_Init(&_canHandle); 00267 HAL_NVIC_EnableIRQ(CAN_IRQ); 00268 00269 return 1; 00270 } 00271 00272 /** 00273 * @brief 00274 * @note 00275 * @param 00276 * @retval 00277 */ 00278 void can_callback(void) { 00279 irq_handler(irq_id, IRQ_RX); 00280 } 00281 00282 /** 00283 * @brief 00284 * @note 00285 * @param 00286 * @retval 00287 */ 00288 void can_irq_init(uint32_t id, can_irq_handler handler) { 00289 irq_id = id; 00290 irq_handler = handler; 00291 rxCompleteCallback = can_callback; 00292 00293 if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) { 00294 #ifdef DEBUG 00295 printf("CAN reception initialization error\r\n"); 00296 #endif 00297 } 00298 } 00299 00300 /** 00301 * @brief 00302 * @note 00303 * @param 00304 * @retval 00305 */ 00306 void can_irq_free(void) { 00307 rxCompleteCallback = 0; 00308 } 00309 00310 /** 00311 * @brief 00312 * @note 00313 * @param 00314 * @retval 00315 */ 00316 int can_write(CAN_Message msg, int cc) { 00317 int i = 0; 00318 00319 if(msg.format == CANStandard) { 00320 _canHandle.pTxMsg->StdId = msg.id; 00321 _canHandle.pTxMsg->ExtId = 0x00; 00322 } 00323 else { 00324 _canHandle.pTxMsg->StdId = 0x00; 00325 _canHandle.pTxMsg->ExtId = msg.id; 00326 } 00327 00328 _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE; 00329 _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT; 00330 _canHandle.pTxMsg->DLC = msg.len; 00331 00332 for(i = 0; i < msg.len; i++) 00333 _canHandle.pTxMsg->Data[i] = msg.data[i]; 00334 00335 if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) { 00336 #ifdef DEBUG 00337 printf("Transmission error\r\n"); 00338 #endif 00339 return 0; 00340 } 00341 else 00342 return 1; 00343 } 00344 00345 /** 00346 * @brief 00347 * @note 00348 * @param 00349 * @retval 00350 */ 00351 int can_read(CAN_Message* msg, int handle) { 00352 int i; 00353 msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId; 00354 msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote; 00355 msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended; 00356 msg->len = _canHandle.pRxMsg->DLC; 00357 for(i = 0; i < msg->len; i++) 00358 msg->data[i] = _canHandle.pRxMsg->Data[i]; 00359 00360 return msg->len; 00361 } 00362 00363 /** 00364 * @brief 00365 * @note 00366 * @param 00367 * @retval 00368 */ 00369 int can_mode(CanMode mode) { 00370 switch(mode) { 00371 case MODE_RESET: 00372 return HAL_ERROR; 00373 00374 case MODE_NORMAL: 00375 _canHandle.Init.Mode = CAN_MODE_NORMAL; 00376 break; 00377 00378 case MODE_SILENT: 00379 _canHandle.Init.Mode = CAN_MODE_SILENT; 00380 break; 00381 00382 case MODE_TEST_GLOBAL: 00383 _canHandle.Init.Mode = CAN_MODE_LOOPBACK; 00384 break; 00385 00386 case MODE_TEST_LOCAL: 00387 _canHandle.Init.Mode = CAN_MODE_LOOPBACK; 00388 break; 00389 00390 case MODE_TEST_SILENT: 00391 _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK; 00392 break; 00393 } 00394 00395 return HAL_CAN_Init(&_canHandle); 00396 } 00397 00398 /** 00399 * @brief 00400 * @note 00401 * @param 00402 * @retval 00403 */ 00404 int can_filter(uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) { 00405 CAN_FilterConfTypeDef sFilterConfig; 00406 00407 sFilterConfig.FilterNumber = handle; // Specifies the filter number (must be a number between 0 and 13 at 32-bit filter scale) 00408 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; 00409 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; 00410 sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF); 00411 sFilterConfig.FilterIdLow = ((id) & 0xFFFF); 00412 sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF); 00413 sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF); 00414 sFilterConfig.FilterFIFOAssignment = 0; 00415 sFilterConfig.FilterActivation = ENABLE; 00416 sFilterConfig.BankNumber = 0; // Selects the start bank filter 00417 return HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig); 00418 } 00419 00420 /** 00421 * @brief 00422 * @note 00423 * @param 00424 * @retval 00425 */ 00426 void can_reset(void) { 00427 __HAL_CAN_RESET_HANDLE_STATE(&_canHandle); 00428 } 00429 00430 /** 00431 * @brief 00432 * @note 00433 * @param 00434 * @retval 00435 */ 00436 unsigned char can_rderror(void) { 00437 return HAL_CAN_GetError(&_canHandle); 00438 } 00439 00440 /** 00441 * @brief 00442 * @note 00443 * @param 00444 * @retval 00445 */ 00446 unsigned char can_tderror(void) { 00447 return HAL_CAN_GetError(&_canHandle); 00448 } 00449 00450 /** 00451 * @brief 00452 * @note 00453 * @param 00454 * @retval 00455 */ 00456 void can_monitor(int silent) { 00457 00458 // not implemented 00459 } 00460 00461 00462 00463 00464 00465 00466 00467
Generated on Sat Jul 16 2022 03:43:32 by 1.7.2