2019-06-12 09:36 AM
I am new to FDCAN on STM32H7.
Using STM32H753VIT6, STM32CubeMX , and HAL, I configured both FDCAN1 (master) and FDCAN2 (slave) at 250 kbps, and all seems to work fine.
To check it, I used a MicroChip CAN Bus Analyzer Tool (BTW a very limited and buggy product, but not expensive).
I calculated the nominal bit time for 250kbps, which should be 4uS.
This is how configured it. I switched the FDCAN clock to PLL2Q which I have set to 80, to get a clock of 10MHz.
PeriphClkInitStruct.PLL2.PLL2Q = 80; // fdcan_ker_ck = 800MHz / 80 = 10MHz
PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL2;
Then I configured values in the function MX_FDCAN1_Init.
My calculations:
* Bit time configuration:
* ************************
* Bit time parameter | Nominal | Data
* ---------------------------|--------------|------------------
* fdcan_ker_ck | 10 MHz | 10 MHz
* Time_quantum (tq) | 100 ns | 100 ns
* Synchronization_segment | 1 tq | 1 tq
* Propagation_segment | 23 tq | 23 tq
* Phase_segment_1 | 8 tq | 8 tq
* Phase_segment_2 | 8 tq | 8 tq
* Synchronization_Jump_width | 8 tq | 8 tq
* Sample (80%) | 32 tq | 32 tq
* Bit_length | 40 tq = 4 µs | 40 tq = 4 µs
* Bit_rate | 250 kBit/s | 250 kBit/s
Some of the important values:
/* Specifies the value by which the oscillator frequency is
* divided for generating the nominal bit time quanta.
* This parameter must be a number between 1 and 512
* 800MHz / PLL2@80 = 10MHz / 250kHz = 40
*/
hfdcan1.Init.NominalPrescaler = 1; /* tq = NominalPrescaler x (1/fdcan_ker_ck) */
/* Specifies the maximum number of time quanta the FDCAN
* hardware is allowed to lengthen or shorten a bit to perform
* re-synchronization.
* This parameter must be a number between 1 and 128
*/
hfdcan1.Init.NominalSyncJumpWidth = 0x08;
/* Specifies the number of time quanta in Bit Segment 1.
* This parameter must be a number between 2 and 256
*/
hfdcan1.Init.NominalTimeSeg1 = 31; /* NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */
/* Specifies the number of time quanta in Bit Segment 2.
* This parameter must be a number between 2 and 128
*/
hfdcan1.Init.NominalTimeSeg2 = 8;
/* Specifies the value by which the oscillator frequency is
* divided for generating the data bit time quanta.
* This parameter must be a number between 1 and 32
*/
hfdcan1.Init.DataPrescaler = 1;
/* Specifies the maximum number of time quanta the FDCAN
* hardware is allowed to lengthen or shorten a data bit to
* perform re-synchronization.
* This parameter must be a number between 1 and 16
*/
hfdcan1.Init.DataSyncJumpWidth = 0x08;
/* Specifies the number of time quanta in Data Bit Segment 1.
* This parameter must be a number between 1 and 32
*/
hfdcan1.Init.DataTimeSeg1 = 31;
/* Specifies the number of time quanta in Data Bit Segment 2.
* This parameter must be a number between 1 and 16
*/
hfdcan1.Init.DataTimeSeg2 = 8;
I am not sure DataPrescaler is the same as NominalPrescaler, and same for DataTimeSeg1 = NominalTimeSeg1 and DataTimeSeg2 = DataTimeSeg1. But all works.
I transmit a message using the following code:
uint8_t ubKeyNumber = 0x0;
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
FDCAN_TxHeaderTypeDef TxHeader;
uint8_t TxData[8];
void dmc_canbus_transmit_1(void)
{
/* Prepare Tx Header */
TxHeader.Identifier = 0x321;
TxHeader.IdType = FDCAN_EXTENDED_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
/* Set the data to be transmitted */
TxData[0] = ubKeyNumber++;
TxData[1] = 0xAD;
TxData[2] = 0xDE;
TxData[3] = 0xAD;
TxData[4] = 0xBE;
TxData[5] = 0xEF;
TxData[6] = 0xFA;
TxData[7] = 0xCE;
/* Start the Transmission process */
dmc_puts("HAL_FDCAN_AddMessageToTxFifoQ: ");
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
{
/* Transmission request Error */
Error_Handler();
}
}
// This function is called after MX_FDCAN1_Init(); to configure the filter
void dmc_canbus_init_1(void)
{
// FDCAN_FilterTypeDef sFilterConfig;
// /* Configure Rx filter */
// sFilterConfig.IdType = FDCAN_EXTENDED_ID;
// sFilterConfig.FilterIndex = 0;
// sFilterConfig.FilterType = FDCAN_FILTER_MASK;
// sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
// sFilterConfig.FilterID1 = 0x321;
// sFilterConfig.FilterID2 = 0x1FFFFFFF;
// if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
// {
// /* Filter configuration Error */
// Error_Handler();
// }
/* Configure global filter to reject all non-matching frames */
// HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
/* Start the FDCAN module */
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
/* Notification Error */
Error_Handler();
}
}
When I use the out-commented filtering, the hardware filtering does not seem to work, I will not receive data.
If using it, in MX_FDCAN1_Init I also specify
hfdcan1.Init.ExtFiltersNbr = 1;
What can be the problem?
Any help would be appreciated.