Este ultimo codigo es muy similar al anterior solo que esta vez estamos usando un filtro que solo dejara recivir los mensajes con el ID 0x1FE, asi que ya no es necesario el if en la funcion callback. Para configurar el filtro se utiliza la estructura FDCAN_FilterTypeDef
y despues la funcion HAL_FDCAN_ConfigFilter
, esta funcion no es la unica que debemos usar, es necesario llamar HAL_FDCAN_ConfigGlobalFilter
para indicar que efecto tendran, si rechazan o aceptan los mensajes, en este caso rechazaran los mensajes que no coincidan con el ID. Otra cosa importante a anotar esque los filtros se deben configurarse antes de iniciar el modulo FDCAN con HAL_FDCAN_Start
de lo contrario no tendran efecto
#include "bsp.h"
/* structure type variables for USER CAN initialization */
FDCAN_HandleTypeDef CANHandler;
/*CAN Rx header structure*/
FDCAN_RxHeaderTypeDef CANRxHeader;
/*Can filter structure*/
FDCAN_FilterTypeDef CANFilter;
/*buffer to save the message*/
uint8_t RxData[8];
/*flag to indicate a message has been received*/
uint8_t message;
int main( void )
{
HAL_Init(); /*Init HAL library*/
/* FDCAN1 module to transmit up to 100Kbps and sample point of 75%
fCAN = fHSI / CANHandler.Init.ClockDivider / CANHandler.Init.NominalPrescaler
fCAN = 16MHz / 1 / 10 = 1.6Mhz
Time quantas:
Ntq = fCAN / CANbaudrate
Ntq = 1.6Mhz / 100Kbps = 16
Sample point:
Sp = ( CANHandler.Init.NominalTimeSeg1 + 1 / Ntq ) * 100
Sp = ( ( 11 + 1 ) / 16 ) * 100 = 75% */
CANHandler.Instance = FDCAN1;
CANHandler.Init.Mode = FDCAN_MODE_NORMAL; /*CAN full operative, Tx and Rx*/
CANHandler.Init.FrameFormat = FDCAN_FRAME_CLASSIC; /*Classic frame*/
CANHandler.Init.ClockDivider = FDCAN_CLOCK_DIV1; /*No APB divider for FDCAN module*/
CANHandler.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /*Tx buffer in Fifo mode*/
CANHandler.Init.NominalPrescaler = 10; /*CAN clock divider by 10*/
CANHandler.Init.NominalSyncJumpWidth = 1; /*SWJ of 1*/
CANHandler.Init.NominalTimeSeg1 = 11; /*phase time seg1 + prop seg*/
CANHandler.Init.NominalTimeSeg2 = 4; /*phase time seg2*/
HAL_FDCAN_Init( &CANHandler);
/* Configure reception filter to Rx FIFO 0, the filter will only accept ID 0x1FE */
CANFilter.IdType = FDCAN_STANDARD_ID; /*11 bits ID*/
CANFilter.FilterIndex = 0;
CANFilter.FilterType = FDCAN_FILTER_MASK;
CANFilter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;/*filter on fifo0*/
CANFilter.FilterID1 = 0x1FE; /*filter ID*/
CANFilter.FilterID2 = 0x7FF; /*filter mask*/
HAL_FDCAN_ConfigFilter( &CANHandler, &CANFilter );
/*accpet only messages with ID 0x1FE*/
HAL_FDCAN_ConfigGlobalFilter( &CANHandler, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE );
/* Change FDCAN instance from initialization mode to normal mode */
HAL_FDCAN_Start( &CANHandler);
/*enable reception interrupts when arrive a message on fifo0*/
HAL_FDCAN_ActivateNotification( &CANHandler, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0 );
while( 1u )
{
/*is a message arrive*/
if( message == 1u )
{
message = 0u; /*clear the flag*/
/*we can do anything we want with the message store in RxData
something important is that the structure CANRxHeader is
filled with message data we can use.
Review the FDCAN_RxHeaderTypeDef structure elements
to see the information store whaen a message arrives*/
}
}
}
/*This callback is called bu the HAL_FDCAN_IRQHandler every time a single message
is received on fifo0 only with ID equal to 0x1FE*/
void HAL_FDCAN_RxFifo0Callback( FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs )
{
/* Retrieve Rx messages from RX FIFO0 */
HAL_FDCAN_GetRxMessage( hfdcan, FDCAN_RX_FIFO0, &CANRxHeader, RxData );
/*set the flag to indicate a message arrive*/
message = 1u;
}
msps.c
/*This function is called in HAL_FDCAN_Init*/
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *hfdcan)
{
GPIO_InitTypeDef GpioCanStruct;
/* Habilitamos los relojes de los perifericos GPIO y CAN */
__HAL_RCC_FDCAN_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/* configuramos pin 0(rx) y pin 1(tx) en modo alterno para FDCAN1 */
GpioCanStruct.Mode = GPIO_MODE_AF_PP;
GpioCanStruct.Alternate = GPIO_AF3_FDCAN1;
GpioCanStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GpioCanStruct.Pull = GPIO_NOPULL;
GpioCanStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init( GPIOD, &GpioCanStruct );
/*Enable vector interrupt to attend CAN IRQs */
HAL_NVIC_SetPriority(TIM16_FDCAN_IT0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(TIM16_FDCAN_IT0_IRQn);
}
ints.c
/*reference to FDCAN control structure handler*/
extern FDCAN_HandleTypeDef CANHandler;
/*Declare CAN interrupt service rutine as it is declare in startup_stm32g0b1xx.s file*/
void TIM16_FDCAN_IT0_IRQHandler( void )
{
/*HAL library functions that attend interrupt on CAN*/
HAL_FDCAN_IRQHandler( &CANHandler );
}