Implementación de Recepción por Interrupción en STM32F4 para el Bus CAN
Los microcontroladores STM32F4, basados en el núcleo ARM Cortex-M4, son ampliamente utilizados en aplicaciones de electrónica automotriz y control industrial debido a sus capacidades de procesamiento en tiempo real y sus periféricos de comunicación integrados. La interfaz CAN (Controller Area Network) es fundamental para la comunicación robusta y confiable entre diferentes unidades de control electrónicas (ECUs).
- Introducción a la Familia STM32F4
La serie STM32F4 ofrece un rendimiento de procesamiento elevado con frecuencias de reloj que pueden alcanzar los 180 MHz. Su núcleo Cortex-M4 incluye una unidad de punto flotante (FPU) y capacidades de procesamiento de señales digitales (DSP). Estos microcontroladores proporcionan una amplia gama de periféricos, incluyendo múltiples interfaces de comunicación como USART, SPI, I2C y, crucialmente, controladores CAN.
El entorno de desarrollo típicamente implica herramientas como STM32CubeIDE, Keil MDK o IAR EWARM, complementadas con el software de configuración gráfica STM32CubeMX, que simplifica enormemente la inicialización y configuración de periféricos.
- Fundamentos del Bus CAN
CAN es un protocolo de comunicación en serie desarrollado inicialmente para el sector automotriz. Su diseño permite que múltiples nodos compartan un bus de comunicación de dos cables (CAN_H y CAN_L), reduciendo significativamente el cableado y mejorando la confiabilidad.
2.1 Características Principales
- Multi-maestro con arbitraje: Cualquier nodo puede iniciar una transmisión. Si dos nodos comienzan a transmitir simultáneamente, se emplea un mecanismo de arbitraje no destructivo basado en el identificador del mensaje, donde el de menor prioridad cede el bus.
- Alta inmunidad al ruido: Utiliza señales diferenciales, lo que proporciona una excelente resistencia a interferencias electromagnéticas comunes en entornos industriales.
- Detección de errores robusta: Incluye múltiples mecanismos de detección de errores como CRC, verificación de trama y monitoreo de bits.
2.2 Formato de los Mensajes
La comunicación CAN se basa en marcos de datos y marcos remotos. Un marco de datos estándar (CAN 2.0A) consiste en los campos de inicio de trama, arbitraje (contiene el identificador), control, datos (0-8 bytes), CRC, acuse de recibo y fin de trama.
- Arquitectura del Módulo CAN en STM32F4
El periférico CAN integrado en los STM32F4 comprende un controlador CAN que maneja el protocolo y una conexión física a la línea del bus.
3.1 Estructura del Hardware
El controlador CAN incluye múltiples buzones de transmisión (Tx) y una jerarquía de FIFOs de recepción (Rx). El STM32F4 típicamente dispone de dos controladores CAN (CAN1 y CAN2). CAN2 puede compartir algunos recursos de filtrado con CAN1, lo que requiere una configuración cuidadosa.
3.2 Mecanismos de Filtrado y Buffers
Para gestionar eficientemente el tráfico de la red, el módulo CAN posee filtros configurables por hardware. Estos filtros permiten que solo los mansajes con iedntificadores específicos se acepten y almacenen en las FIFOs de recepción, reduciendo la carga de interrupción en el procesador.
- Guía de Configuración para Recepción por Interrupción
A continuación se detallan los pasos esenciales para configurar CAN1 o CAN2 en modo de recepción por interrupción usando la biblioteca HAL.
4.1 Habilitación de Relojes y Estructura de Inicialización
Primero, se deben habilitar los relojes para los periféricos relevantes. Esto incluye el reloj del controlador CAN y el reloj del GPIO asociado a los pines CAN (TX y RX).
// Habilitar relojes usando los registros RCC
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Ejemplo para pines en puerto B
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; // Habilitar reloj para CAN1
La inicialización de la interfaz CAN se realiza definiendo una estructura de configuración con los parámetros de temporización deseados para alcanzar la velocidad del bus (por ejemplo, 500 kbps).
CAN_HandleTypeDef hcan_device;
void InicializarCAN(void) {
hcan_device.Instance = CAN1;
hcan_device.Init.Prescaler = 12; // Valor dependiente del reloj APB1
hcan_device.Init.Mode = CAN_MODE_NORMAL;
hcan_device.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan_device.Init.TimeSeg1 = CAN_BS1_11TQ;
hcan_device.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan_device.Init.TimeTriggeredMode = DISABLE;
hcan_device.Init.AutoBusOff = ENABLE;
hcan_device.Init.AutoWakeUp = DISABLE;
hcan_device.Init.AutoRetransmission = ENABLE;
hcan_device.Init.ReceiveFifoLocked = DISABLE;
hcan_device.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan_device) != HAL_OK) {
// Manejar error de inicialización
}
}
4.2 Configuración de los Filtros de Recepción
Los filtros determinan qué mensajes serán aceptados. En el siguiente ejemplo, se configura un filtro en modo de máscara para aceptar mensajes con cualquier identificador (filtro pasante), útil para diagnóstico.
CAN_FilterTypeDef filtro_recepcion;
filtro_recepcion.FilterBank = 0;
filtro_recepcion.FilterMode = CAN_FILTERMODE_IDMASK;
filtro_recepcion.FilterScale = CAN_FILTERSCALE_32BIT;
filtro_recepcion.FilterIdHigh = 0x0000;
filtro_recepcion.FilterIdLow = 0x0000;
filtro_recepcion.FilterMaskIdHigh = 0x0000;
filtro_recepcion.FilterMaskIdLow = 0x0000;
filtro_recepcion.FilterFIFOAssignment = CAN_RX_FIFO0;
filtro_recepcion.FilterActivation = ENABLE;
filtro_recepcion.SlaveStartFilterBank = 14; // Importante si se usa CAN2
HAL_CAN_ConfigFilter(&hcan_device, &filtro_recepcion);
4.3 Habilitación de Interrupciones y Manejadores
Para procesar los mensajes entrantes de forma eficiente, se habilitan las interrupciones de la FIFO de recepción.
// Configurar prioridad y habilitar la interrupción en el NVIC
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
// Iniciar el módulo CAN
HAL_CAN_Start(&hcan_device);
// Habilitar la interrupción de mensaje pendiente en FIFO0
HAL_CAN_ActivateNotification(&hcan_device, CAN_IT_RX_FIFO0_MSG_PENDING);
El manejador de interrupción genérico llama a la función de gestión de la biblioteca HAL, la cual a su vez invoca una función de callback específica que el programador debe implementar.
// Manejador de interrupción vectorial
void CAN1_RX0_IRQHandler(void) {
HAL_CAN_IRQHandler(&hcan_device);
}
// Función de callback para mensajes recibidos en FIFO0
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
CAN_RxHeaderTypeDef header_rx;
uint8_t datos_rx[8];
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header_rx, datos_rx) == HAL_OK) {
// Procesar el mensaje recibido
// header_rx.StdId contiene el identificador
// datos_rx[] contiene la carga útil
} else {
// Manejar error en la recepción
}
}
- Uso de Herramientas de Desarrollo
STM32CubeMX puede generar el código de inicialización esquemático para la configuración CAN seleccionada, incluyendo la configuración de pines, relojes, parámetros CAN y la generación del código base para las enterrupciones.
El código generado sirve como punto de partida. La lógica de la aplicación, como el procesamiento de mensajes específicos en el callback, debe ser implementada por el desarrollador.
- Bibliotecas HAL y LL
La biblioteca HAL (Hardware Abstraction Layer) ofrece una capa de abstracción portable que simplifica el acceso al hardware, incluyendo funciones de alto nivel para la comunicación CAN como HAL_CAN_AddTxMessage y HAL_CAN_GetRxMessage.
La biblioteca LL (Low Layer) proporciona acceso más directo a los registros del periférico, ofreciendo un rendimiento potencialmente superior y una huella de código más pequeña, ideal para aplicaciones con restricciones estrictas de recursos o latencia.
La elección entre ambas bibliotecas depende de los requisitos específicos del proyecto en términos de portabilidad, facilidad de desarrollo y rendimiento.
Una gestión adecuada de los estados y errores del periférico, utilizando funciones como HAL_CAN_GetState y HAL_CAN_GetError, es crucial para construir una aplicación de comunicación CAN robusta y fiable.