Este ultimo programa utiliza interrupciones para captar cuando el mensaje se ha transmitido por completo, mediante la función HAL_FDCAN_ActivateNotification
se activa la interrupción cuando todos los buffers se vacían y después la interrupción manda llamar automáticamente la callback HAL_FDCAN_TxFifoEmptyCallback
En esta función se transmite de nueva cuenta y se repite la operación otras tres veces para un total de 4 transmisiones en un espacio de 5 segundos, para que de nueva se repita la operación
#include "bsp.h"
/* structure type variables for USER CAN initialization */
FDCAN_HandleTypeDef CANHandler;
/*CAN header structure*/
FDCAN_TxHeaderTypeDef CANTxHeader;
/*message to send*/
uint8_t message[8] = {0x48, 0x31, 0x20, 0x57, 0x4F, 0x52, 0x4C, 0x44};
uint8_t msgs;
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);
/* 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*/
/*enable transmision interrupts when fifo0 is empty */
HAL_FDCAN_ActivateNotification( &CANHandler, FDCAN_IT_TX_FIFO_EMPTY, FDCAN_TX_BUFFER0 );
while( 1u )
{
/*set the first message on fifo0 to send it*/
msgs = 0u;
message[ 1u ] = 0x31u;
HAL_FDCAN_AddMessageToTxFifoQ( &CANHandler, &CANTxHeader, &message[0u] );
/*wait five seconds, long enough for the ISR to trnasmit the rest of the messageso*/
HAL_Delay( 5000u );
}
}
/*This callback is called bu the HAL_FDCAN_IRQHandler every time a single message is transmitted*/
void HAL_FDCAN_TxFifoEmptyCallback( FDCAN_HandleTypeDef *hfdcan )
{
/*send only another three messages more usinf this rutine*/
if( msgs < 3u )
{
/*send another messages using interrupts*/
message[ 1u ]++;
HAL_FDCAN_AddMessageToTxFifoQ( hfdcan, &CANTxHeader, &message[0u] );
msgs++;
}
}
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 );
}