CAN Transmit and Receive Testing on AC7840x Microcontroller
Hardware Configuration
CAN Transceiver Circuit
Standard CAN transceiver circuitry implemented.
Interface Pins
CAN signals routed through:
- PE4: Receiver input
- PE5: Transmitter output
Port Mapping
PE4 and PE5 configured for CAN0 controller operation.
Software Implementation
CAN Driver Module
#include "ac7840x.h"
#include "gpio_drv.h"
#include "can_drv.h"
#include "clock_config.h"
#define CLK_SRC_FREQ (60000000UL)
#define PROCESS_FRAMES (1)
#define ENABLE_TIMESTAMP (0)
typedef struct {
uint32_t rx_count;
uint32_t tx_count;
} can_stats_t;
#if (CLK_SRC_FREQ == 80000000UL)
static const can_time_segment_t baud_config[] = {
{0x1C, 0x09, 0x09, 0x01}, // 1M
{0x26, 0x09, 0x09, 0x01}, // 800K
{0x1C, 0x09, 0x09, 0x03}, // 500K
{0x1C, 0x09, 0x09, 0x07}, // 250K
{0x1C, 0x09, 0x09, 0x0F}, // 125K
{0x1C, 0x09, 0x09, 0x13}, // 100K
{0x1C, 0x09, 0x09, 0x27} // 50K
};
elif (CLK_SRC_FREQ == 60000000UL)
static const can_time_segment_t baud_config[] = {
{0x0D, 0x04, 0x04, 0x02}, // 1M
{0x12, 0x04, 0x04, 0x02}, // 800K
{0x1C, 0x09, 0x09, 0x02}, // 500K
{0x1C, 0x09, 0x09, 0x05}, // 250K
{0x1C, 0x09, 0x09, 0x0B}, // 125K
{0x1C, 0x09, 0x09, 0x0E}, // 100K
{0x1C, 0x09, 0x09, 0x1D} // 50K
};
#endif
static can_stats_t can_status[4] = {0};
void configure_can_pins(uint8_t channel) {
if(channel == 0) {
GPIO_DRV_SetMuxModeSel(PORTE, 4, PORT_MUX_ALT5);
GPIO_DRV_SetMuxModeSel(PORTE, 5, PORT_MUX_ALT5);
}
}
static can_time_segment_t get_baud_config(uint8_t index) {
return (index < sizeof(baud_config)/sizeof(baud_config[0])) ?
baud_config[index] : (can_time_segment_t){0};
}
static void process_received_frame(uint8_t ch, const can_msg_info_t* frame) {
can_status[ch].rx_count++;
#if PROCESS_FRAMES
if(frame->IDE) {
// Extended ID processing
} else {
// Standard ID processing
}
#endif
}
void can_event_handler(uint8_t ch, uint32_t event, uint32_t error) {
can_msg_info_t rx_frame = {0};
uint8_t data_buf[8] = {0};
if(event & CAN_EVENT_RECEIVE_DONE) {
while(CAN_DRV_GetRbufStatus(ch)) {
rx_frame.DATA = data_buf;
if(CAN_DRV_Receive(ch, &rx_frame)) {
process_received_frame(ch, &rx_frame);
}
}
}
}
void initialize_can_controller(void) {
can_user_config_t cfg = {
.filterNum = 0,
.canMode = CAN_NORMAL_MODE,
.interruptEn = true,
.tsMode = CAN_TSMODE_FIFO,
.bitrate = get_baud_config(2), // 500Kbps
.callback = can_event_handler
};
configure_can_pins(0);
CAN_DRV_Init(0, &cfg);
}
void transmit_can_frame(uint8_t* payload) {
static can_msg_info_t tx_frame = {
.ID = 0x220,
.IDE = 0,
.RTR = 0,
.DLC = 8
};
uint8_t data_buffer[8];
memcpy(data_buffer, payload, 8);
tx_frame.DATA = data_buffer;
if(CAN_DRV_Send(0, &tx_frame, CAN_TRANSMIT_SECONDARY) == STATUS_SUCCESS) {
can_status[0].tx_count++;
}
}
Main Application
#include "ac7840x.h"
#include "clock_config.h"
#include "can.h"
uint8_t transmission_buffer[8];
int main(void) {
SystemClock_Config();
initialize_can_controller();
uint8_t counter = 0;
while(1) {
transmission_buffer[0] = counter++;
transmit_can_frame(transmission_buffer);
OSIF_TimeDelay(100);
}
}
Test Verification
Transmission Test
Connected CAN analyzer confirms recepsion of periodic frames with incrementign first byte.
Reception Test
Serial temrinal displays decoded CAN frames matching transmitted data patterns.