pub
Fork of CANnucleo by
can_api.c
- Committer:
- hudakz
- Date:
- 2015-07-19
- Revision:
- 0:e29bc8e0dddd
- Child:
- 1:eb04f7f0478d
File content as of revision 0:e29bc8e0dddd:
/* can_api.c for STMicroelectronics mbed boards equipped with Controller Area Network interface: NUCLEO-F070RB NUCLEO-F072RB NUCLEO-F103RB NUCLEO-F302R8 NUCLEO-F334R8 NUCLEO-F303RE NUCLEO-F091RC DISCO-F334C8 DISCO-F746NG Copyright (c) 2015 Zoltan Hudak <hudakz@inbox.com> All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "stm32f1xx_hal.h" #include "can_api.h" #include "can_helper.h" #include "pinmap.h" extern void (*rxCompleteCallback) (void); extern CAN_HandleTypeDef _canHandle; /** * @brief * @note * @param * @retval */ void can_init(can_t* obj, PinName rd, PinName td) { initCAN(obj, rd, td); can_filter(obj, 0, 0, CANAny, 0); } /** * @brief * @note * @param * @retval */ void can_free(can_t* obj) { HAL_CAN_MspDeInit(obj); } /** * @brief * @note * @param * @retval */ int can_frequency(can_t* obj, int hz) { /* Disable the NVIC for CAN reception */ HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); #if defined(TARGET_NUCLEO_F103RB) || \ defined(TARGET_NUCLEO_F302R8) || \ defined(TARGET_NUCLEO_F334R8) || \ defined(TARGET_NUCLEO_F303RE) || \ defined(TARGET_DISCO_F334C8) // APB1 pheripheral clock = 36000000Hz switch(hz) { case 1000000: // 1000kbps bit rate _canHandle.Init.Prescaler = 3; // number of time quanta = 36000000/3/1000000 = 12 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_3TQ; break; case 500000: // 500kbps bit rate _canHandle.Init.Prescaler = 6; // number of time quanta = 36000000/6/500000 = 12 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_3TQ; break; case 250000: // 250kbps _canHandle.Init.Prescaler = 9; // number of time quanta = 36000000/9/250000 = 16 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_4TQ; break; case 125000: // 125kbps _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_4TQ; break; default: // 125kbps (default) printf("Unknown frequency specified!\r\n"); printf("Using default 125kbps\r\n"); _canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_4TQ; } #elif defined(TARGET_NUCLEO_F070RB) || \ defined(TARGET_NUCLEO_F072RB) || \ defined(TARGET_NUCLEO_F091RC) // APB1 pheripheral clock = 48000000Hz switch(hz) { case 1000000: // 1000kbps bit rate _canHandle.Init.Prescaler = 4; // number of time quanta = 48000000/4/1000000 = 12 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_3TQ; break; case 500000: // 500kbps bit rate _canHandle.Init.Prescaler = 8; // number of time quanta = 48000000/8/500000 = 12 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_3TQ; break; case 250000: // 250kbps _canHandle.Init.Prescaler = 12; // number of time quanta = 48000000/12/250000 = 16 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_4TQ; break; case 125000: // 125kbps _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_4TQ; break; default: // 125kbps (default) printf("Unknown frequency specified!\r\n"); printf("Using default 125kbps\r\n"); _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 _canHandle.Init.SJW = CAN_SJW_1TQ; _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% _canHandle.Init.BS2 = CAN_BS2_4TQ; } #endif HAL_CAN_Init(&_canHandle); HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); } /** * @brief * @note * @param * @retval */ void can_irq_init(can_t* obj, can_irq_handler handler, uint32_t id) { if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) { printf("CAN reception initialization error\r\n"); } } /** * @brief * @note * @param * @retval */ void can_irq_free(can_t* obj) { rxCompleteCallback = NULL; } /** * @brief * @note * @param * @retval */ //void can_irq_set(can_t* obj, CanIrqType irq, uint32_t enable) //{ //} void can_irq_set(void (*fptr) (void)) { rxCompleteCallback = fptr; } /** * @brief * @note * @param * @retval */ int can_write(can_t* obj, CAN_Message msg, int cc) { int i = 0; if(msg.format == CANStandard) { _canHandle.pTxMsg->StdId = msg.id; _canHandle.pTxMsg->ExtId = 0x00; } else { _canHandle.pTxMsg->StdId = 0x00; _canHandle.pTxMsg->ExtId = msg.id; } _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE; _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT; _canHandle.pTxMsg->DLC = msg.len; for(i = 0; i < msg.len; i++) _canHandle.pTxMsg->Data[i] = msg.data[i]; if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) { printf("Transmission error\r\n"); } } /** * @brief * @note * @param * @retval */ int can_read(can_t* obj, CAN_Message* msg, int handle) { int i = 0; msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId; msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote; msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended; msg->len = _canHandle.pRxMsg->DLC; for(i = 0; i < msg->len; i++) msg->data[i] = _canHandle.pRxMsg->Data[i]; } /** * @brief * @note * @param * @retval */ int can_mode(can_t* obj, CanMode mode) { switch(mode) { case MODE_RESET: return HAL_ERROR; case MODE_NORMAL: _canHandle.Init.Mode = CAN_MODE_NORMAL; break; case MODE_SILENT: _canHandle.Init.Mode = CAN_MODE_SILENT; break; case MODE_TEST_GLOBAL: _canHandle.Init.Mode = CAN_MODE_LOOPBACK; break; case MODE_TEST_LOCAL: _canHandle.Init.Mode = CAN_MODE_LOOPBACK; break; case MODE_TEST_SILENT: _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK; break; } _canHandle.Init.Mode = CAN_MODE_NORMAL; return HAL_CAN_Init(&_canHandle); } /** * @brief * @note * @param * @retval */ int can_filter(can_t* obj, uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) { CAN_FilterConfTypeDef sFilterConfig; sFilterConfig.FilterNumber = handle; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF); sFilterConfig.FilterIdLow = ((id) & 0xFFFF); sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF); sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF); sFilterConfig.FilterFIFOAssignment = 0; sFilterConfig.FilterActivation = ENABLE; sFilterConfig.BankNumber = 14; HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig); } /** * @brief * @note * @param * @retval */ void can_reset(can_t* obj) { __HAL_CAN_RESET_HANDLE_STATE(&_canHandle); } /** * @brief * @note * @param * @retval */ unsigned char can_rderror(can_t* obj) { return HAL_CAN_GetError(&_canHandle); } /** * @brief * @note * @param * @retval */ unsigned char can_tderror(can_t* obj) { return HAL_CAN_GetError(&_canHandle); } /** * @brief * @note * @param * @retval */ void can_monitor(can_t* obj, int silent) { // not implemented }