En el codigo anterior activamos la interrupcion por recepcion de mensajes en el Fifo0, cuando llega un mensaje se activa la interrupcion y esta a su vez manda llamar la callback HAL_FDCAN_RxFifo0Callback
dentro de esta funcion es necesario preguntar si la interrupcion fue causada por el arrivo de un nuevo mensaje, depues de esto optenemos la informacion del mensaje usando la funcion HAL_FDCAN_GetRxMessage
los cuales son los datos del mensaje en el areglo RxData
y las caracteristicas del mensaje en CANRxHeader
, aqui solo nos sercioramos si el ID del mensaje es el que necesitamos y solo activamos una bandera la cual posteriormente se usa dentro de la funcion main para invertir el estado del led.
#include "bsp.h"
/* structure type variables for USER CAN initialization */
FDCAN_HandleTypeDef CANHandler;
/*CAN Rx header structure*/
FDCAN_RxHeaderTypeDef CANRxHeader;
/*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);
/* 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 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*/
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 );
}