El programa es muy similar al anterior solo que esta vez mandamos tres mensajes uno detrás de otro, haciendo uso de los buffers que posee el CAN del micrcontrolador stm32g0 que solo son tres, estos buffers solo pueden mandar un solo mensaje de 1 hasta 8 bytes en modo clásico o hasta 64 bytes en modo FD. Si intentáramos mandar un cuarto mensaje este seria rechazado ya que tres es el limite y habría que esperar a que se mandara uno o todos los mensajes, como en ambos programas mandamos cada segundo, no es necesario preguntar por alguna bandera si alguno de los buffer ya están libre, pero lo mas recomendable es si hacerlo con las funciones HAL_FDCAN_GetLatestTxFifoQRequestBuffer y HAL_FDCAN_IsTxBufferMessagePending

#include "bsp.h"

/* structure type variables for USER CAN initialization */
FDCAN_HandleTypeDef CANHandler;

int main( void )
{
    /*CAN header structure*/
    FDCAN_TxHeaderTypeDef CANTxHeader;
    /*message to send*/
    uint8_t message1[8u] = {0x48, 0x31, 0x20, 0x57, 0x4F, 0x52, 0x4C, 0x44};
    uint8_t message2[8u] = {0x48, 0x32, 0x20, 0x57, 0x4F, 0x52, 0x4C, 0x44};
    uint8_t message3[8u] = {0x48, 0x33, 0x20, 0x57, 0x4F, 0x52, 0x4C, 0x44};

    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);

    /* set options to transmit the messages, 11 bits address, 8 bits data frame */
    CANTxHeader.IdType      = FDCAN_STANDARD_ID;    /*11 bits CAN ID*/
    CANTxHeader.FDFormat    = FDCAN_CLASSIC_CAN;    /*classic CAN format up to 8 bytes*/
    CANTxHeader.TxFrameType = FDCAN_DATA_FRAME;     /*type of frame, data*/
    CANTxHeader.Identifier  = 0x1EF;                /*can message ID*/
    CANTxHeader.DataLength  = FDCAN_DLC_BYTES_8;    /*8 bytes to transmit*/
    
    while( 1u )
    {
        /*Fill the TX buffer with all the three messages to transmit*/
        HAL_FDCAN_AddMessageToTxFifoQ( &CANHandler, &CANTxHeader, message1 );
        HAL_FDCAN_AddMessageToTxFifoQ( &CANHandler, &CANTxHeader, message2 );
        HAL_FDCAN_AddMessageToTxFifoQ( &CANHandler, &CANTxHeader, message3 );
        /*wait for one second*/
        HAL_Delay( 1000u );
    }
}

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 );
}