El programa anterior manda configurar el modulo FDCAN en modo can classic en el cual solo se mandan 8 bytes por frame, se establece una velocidad de 100kpbs y un sample point de 75%, el ID es de 11 bytes. El programa manda 8 bytes de información cada segundo sin hacer uso de interrupciones, solo con propósitos ilustrativos. Es importante revisar muy bien la frecuencia que alimenta el modulo CAN y como se calculan las time quantas y el sample point ( revisar comentarios en el código ), para poder analizar los datos mandados es necesario usar candump el cual es parte de las , configurar la velocidad para que coincidan con el modulo del micro. Hay que tomar en cuenta que la función HAL_FDCAN_AddMessageToTxFifoQ
solo carga la información a mandar en el buffer de salida e inicia su transmisión, pero cuando la función retorna no quiere decir que la información ya se mando por completo.
#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 message[8] = {0x48, 0x31, 0x20, 0x57, 0x4F, 0x52, 0x4C, 0x44};
HAL_Init(); /* Inicializamos libreria HAL */
/* 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 Classic mode*/
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 option to transmit the messages */
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 )
{
/*Colocanmos el mensaje en el buffer de salida y activamos el envio*/
HAL_FDCAN_AddMessageToTxFifoQ( &CANHandler, &CANTxHeader, message );
/*esperamos un segundo*/
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 );
}