uint32_t can_rx(CanRxMsgTypeDef *rx_msg, uint32_t timeout) { uint32_t status; hcan.pRxMsg = rx_msg; status = HAL_CAN_Receive(&hcan, CAN_FIFO0, timeout); return status; }
// Receive message from the CAN bus (blocking) uint32_t can_rx(CanRxMsgTypeDef *rx_msg, uint32_t timeout) { uint32_t status; can_handle.pRxMsg = rx_msg; status = HAL_CAN_Receive(&can_handle, CAN_FIFO0, timeout); led_blue_on(); return status; }
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_CAN_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ setup_can_filter(); for (int i = 0; i < 10; ++i) { led_blink(); HAL_Delay(100); } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ CanRxMsgTypeDef rx_msg; uint8_t prebuf[12]; uint8_t uart_msg[18]; while (1) { // while (__HAL_CAN_MSG_PENDING(&hcan, CAN_FIFO0) <= 0) ; hcan.pRxMsg = &rx_msg; if (HAL_OK != HAL_CAN_Receive(&hcan, CAN_FIFO0, 3)) continue; // uint8_t flags = rx_msg.DLC & 0xf; if (rx_msg.RTR == CAN_RTR_REMOTE) flags |= 0x10; if (rx_msg.IDE == CAN_ID_EXT) flags |= 0x20; uint32_t id = (rx_msg.IDE == CAN_ID_EXT ? rx_msg.ExtId : rx_msg.StdId); for (int i = 3; i >= 0; --i) { prebuf[i] = (id & 0xff); id >>= 8; } for (int i = 4; i < 12; ++i) prebuf[i] = 0; for (int i = 0; i < 8 && i < rx_msg.DLC; ++i) prebuf[4+i] = rx_msg.Data[i]; // int j = 0; for (int i = 0; i < 12; i += 3, j += 4) { uint32_t triple = 0; for (int k = 0; k < 3; ++k) { triple <<= 8; triple += prebuf[i+k]; } for (int k = 0; k < 4; ++k) { uart_msg[j+3-k] = basis_64[triple & 63]; triple >>= 6; } } uart_msg[16] = basis_64[flags]; uart_msg[17] = '\n'; // HAL_UART_Transmit(&huart1, uart_msg, 18, 1000); // led_blink(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
int __start(void) { const volatile uint32_t *src; volatile uint32_t *dest; /* Set up BSS and copy data from flash */ for (src = &_eronly, dest = &_sdata; dest < &_edata;) { *dest++ = *src++; } for (dest = &_sbss; dest < &_ebss;) { *dest++ = 0; } SystemInit(); HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Make sure the flash option bytes are set such that we don't re-enter bootloader mode */ set_dfu_option_bytes(0u); MX_USB_DEVICE_Init(); /* Configure GPIO for the CAN_SILENT signal */ GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); __CRS_CLK_ENABLE(); /*Configure GPIO pin : PB7 */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /**CAN GPIO Configuration PB8 ------> CAN_RX PB9 ------> CAN_TX */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_CAN; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Configure the bxCAN transceiver */ CAN_HandleTypeDef hcan; __CAN_CLK_ENABLE(); hcan.Instance = CAN; hcan.Init.Mode = CAN_MODE_SILENT; hcan.Init.TTCM = DISABLE; hcan.Init.ABOM = ENABLE; hcan.Init.AWUM = ENABLE; hcan.Init.NART = DISABLE; hcan.Init.RFLM = DISABLE; hcan.Init.TXFP = DISABLE; /* Set the bitrate and init */ set_can_bitrate(&hcan, 1000000u); CanRxMsgTypeDef rx_msg; hcan.pRxMsg = &rx_msg; CanTxMsgTypeDef tx_msg; hcan.pTxMsg = &tx_msg; CAN_FilterConfTypeDef filter; filter.FilterNumber = 0; filter.FilterMode = CAN_FILTERMODE_IDMASK; filter.FilterScale = CAN_FILTERSCALE_32BIT; filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; filter.FilterActivation = ENABLE; filter.BankNumber = 0; filter.FilterMaskIdLow = filter.FilterIdLow = filter.FilterMaskIdHigh = filter.FilterIdHigh = 0; HAL_CAN_ConfigFilter(&hcan, &filter); __HAL_UNLOCK(&hcan); /* Now that USB is active, we need to sync with the 1 kHz SOF packets to tune the HSI48 so it's accurate enough not to disrupt the CAN bus. */ RCC_CRSInitTypeDef crs_config; crs_config.Prescaler = RCC_CRS_SYNC_DIV1; crs_config.Source = RCC_CRS_SYNC_SOURCE_USB; crs_config.Polarity = RCC_CRS_SYNC_POLARITY_RISING; crs_config.ReloadValue = RCC_CRS_RELOADVALUE_DEFAULT; crs_config.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT; crs_config.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT; HAL_RCCEx_CRSConfig(&crs_config); /* Don't continue unless we're synced */ while (!(HAL_RCCEx_CRSWaitSynchronization(1000000u) & RCC_CRS_SYNCOK)); while (1) { /* Set up the command record */ size_t i; uint8_t current_cmd; uint8_t current_cmd_data[32]; uint8_t current_cmd_data_length; uint8_t channel_open; current_cmd = current_cmd_data_length = i = 0; channel_open = 0; rx_buffer_length = 0; while (hUsbDevice_0 && hUsbDevice_0->pClassData) { /* If the RX buffer is non-empty, process any commands/messages in it and then acknowledge the transfer to the USB stack */ if (rx_buffer_length) { /* Exit if we've read the entire buffer, or if transmit mailboxes are full and the current command is a transmit. */ for (; i < rx_buffer_length && ((current_cmd != 't' && current_cmd != 'T') || __HAL_CAN_GET_FLAG(&hcan, CAN_FLAG_TME0)); i++) { if (rx_buffer[i] == '\r') { uint8_t *buf = active_buffer ? tx_buffer_1 : tx_buffer_0; /* End of command -- process and reset state */ switch (current_cmd) { case 'S': /* Setup bitrate -- data should be a number from 0 to 8. */ if (current_cmd_data[0] < '0' || current_cmd_data[0] > '8') { buf[active_buffer_length++] = '\a'; } else if (set_can_bitrate( &hcan, bitrate_lookup[current_cmd_data[0] - '0'])) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'O': /* Open channel -- take CAN out of silent mode and start receiving. */ if (!channel_open) { channel_open = 1; set_can_silent(&hcan, 0); buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'L': /* Open in listen-only -- CAN should already be in silent mode but just make sure. */ if (!channel_open) { channel_open = 1; set_can_silent(&hcan, 1); buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'C': /* Close channel -- put CAN back in silent mode. */ if (channel_open) { channel_open = 0; set_can_silent(&hcan, 1); buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'V': /* Hardware version */ buf[active_buffer_length++] = 'V'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '1'; buf[active_buffer_length++] = '\r'; break; case 'v': /* Major/minor version */ buf[active_buffer_length++] = 'v'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '1'; buf[active_buffer_length++] = '\r'; break; case 'N': /* Serial number */ buf[active_buffer_length++] = 'N'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = '\r'; break; case 'T': /* Extended message */ if (read_ext_message(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 't': /* Standard message */ if (read_std_message(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'R': /* Extended RTR */ if (read_ext_rtr(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'r': /* Standard RTR */ if (read_std_rtr(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case '_': /* Bootloader request */ if (current_cmd_data[0] == '_' && current_cmd_data[1] == 'd' && current_cmd_data[2] == 'f' && current_cmd_data[3] == 'u') { /* Set option bytes to force bootloader entry */ set_dfu_option_bytes(1u); NVIC_SystemReset(); } else { buf[active_buffer_length++] = '\a'; } break; case 'F': /* Read status flags -- return 4 hex digits */ case 'Z': /* Timestamp on/off -- 0=off, 1=on */ case 'M': /* Acceptance mask -- 8 hex digits */ case 'm': /* Acceptance value -- 8 hex digits */ case 's': /* Set bitrate register -- 6 hex digits */ default: /* NACK */ buf[active_buffer_length++] = '\a'; break; } current_cmd = current_cmd_data_length = 0; } else if (current_cmd) { /* Command data -- save it */ current_cmd_data[current_cmd_data_length++] = rx_buffer[i]; /* Reset command state if the data is too long */ if (current_cmd_data_length == 32u) { current_cmd = current_cmd_data_length = 0; } } else { /* The first letter of a line is the command type -- don't bother validating as we can't NACK until the data has been received. */ current_cmd = rx_buffer[i]; } } if (i == rx_buffer_length) { /* Mark last packet as received */ rx_buffer_length = i = 0; USBD_CDC_ReceivePacket(hUsbDevice_0); } } /* Check the CAN controller for messages and process them if the channel is open */ if (HAL_CAN_Receive(&hcan, CAN_FIFO0, 0) == HAL_OK && hUsbDevice_0 && channel_open) { /* Format the message and send it to the host. The data format for a standard ID message is: tiiildddddddddddddddd\r The data format for a standard ID RTR is: riii\r The data format for an extended ID message is: Tiiiiiiiildddddddddddddddd\r The data format for an extended ID RTR is: Riiiiiiii\r */ uint8_t *write_location; if (active_buffer_length + EXT_MESSAGE_LEN > TX_BUFFER_SIZE) { /* Reset buffer if we're too far behind -- use worst-case message length for calculation */ active_buffer_length = 0; } write_location = &((active_buffer ? tx_buffer_1 : tx_buffer_0)[active_buffer_length]); if (rx_msg.IDE == CAN_ID_EXT && rx_msg.RTR) { active_buffer_length += write_ext_rtr( write_location, &rx_msg); } else if (rx_msg.IDE == CAN_ID_EXT && !rx_msg.RTR) { active_buffer_length += write_ext_message( write_location, &rx_msg); } else if (rx_msg.IDE == CAN_ID_STD && rx_msg.RTR) { active_buffer_length += write_std_rtr( write_location, &rx_msg); } else if (rx_msg.IDE == CAN_ID_STD && !rx_msg.RTR) { active_buffer_length += write_std_message( write_location, &rx_msg); } } if (!hUsbDevice_0 || !hUsbDevice_0->pClassData) { /* Reset TX buffer if USB is not connected */ active_buffer_length = 0; } else if (active_buffer_length && ((USBD_CDC_HandleTypeDef*)hUsbDevice_0->pClassData)->TxState == 0) { /* Transmit the next buffer if one is available */ CDC_Transmit_FS(active_buffer ? tx_buffer_1 : tx_buffer_0, active_buffer_length); active_buffer_length = 0; active_buffer = active_buffer ? 0 : 1; } } } }
/** * @brief Configures the CAN, transmit and receive by polling * @param None * @retval PASSED if the reception is well done, FAILED in other case */ HAL_StatusTypeDef CAN_Polling(void) { CAN_FilterConfTypeDef sFilterConfig; static CanTxMsgTypeDef TxMessage; static CanRxMsgTypeDef RxMessage; /*##-1- Configure the CAN peripheral #######################################*/ CanHandle.Instance = CANx; CanHandle.pTxMsg = &TxMessage; CanHandle.pRxMsg = &RxMessage; CanHandle.Init.TTCM = DISABLE; CanHandle.Init.ABOM = DISABLE; CanHandle.Init.AWUM = DISABLE; CanHandle.Init.NART = DISABLE; CanHandle.Init.RFLM = DISABLE; CanHandle.Init.TXFP = DISABLE; CanHandle.Init.Mode = CAN_MODE_LOOPBACK; CanHandle.Init.SJW = CAN_SJW_1TQ; CanHandle.Init.BS1 = CAN_BS1_6TQ; CanHandle.Init.BS2 = CAN_BS2_8TQ; CanHandle.Init.Prescaler = 2; if(HAL_CAN_Init(&CanHandle) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /*##-2- Configure the CAN Filter ###########################################*/ sFilterConfig.FilterNumber = 0; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = 0x0000; sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000; sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = 0; sFilterConfig.FilterActivation = ENABLE; sFilterConfig.BankNumber = 14; if(HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig) != HAL_OK) { /* Filter configuration Error */ Error_Handler(); } /*##-3- Start the Transmission process #####################################*/ CanHandle.pTxMsg->StdId = 0x11; CanHandle.pTxMsg->RTR = CAN_RTR_DATA; CanHandle.pTxMsg->IDE = CAN_ID_STD; CanHandle.pTxMsg->DLC = 2; CanHandle.pTxMsg->Data[0] = 0xCA; CanHandle.pTxMsg->Data[1] = 0xFE; if(HAL_CAN_Transmit(&CanHandle, 10) != HAL_OK) { /* Transmition Error */ Error_Handler(); } if(HAL_CAN_GetState(&CanHandle) != HAL_CAN_STATE_READY) { return HAL_ERROR; } /*##-4- Start the Reception process ########################################*/ if(HAL_CAN_Receive(&CanHandle, CAN_FIFO0,10) != HAL_OK) { /* Reception Error */ Error_Handler(); } if(HAL_CAN_GetState(&CanHandle) != HAL_CAN_STATE_READY) { return HAL_ERROR; } if(CanHandle.pRxMsg->StdId != 0x11) { return HAL_ERROR; } if(CanHandle.pRxMsg->IDE != CAN_ID_STD) { return HAL_ERROR; } if(CanHandle.pRxMsg->DLC != 2) { return HAL_ERROR; } if((CanHandle.pRxMsg->Data[0]<<8|RxMessage.Data[1]) != 0xCAFE) { return HAL_ERROR; } return HAL_OK; /* Test Passed */ }