【兆易GD32H759I-EVAL】 CAN2通信收发测试
[复制链接]
本帖最后由 TL-LED 于 2024-6-1 17:38 编辑
测试开发板上的CAN2接口收发测试。
一、硬件部分
1.1、芯片手册部分
1.1.1、芯片外设框图
CH32H759内部有3个CAN通信接口
1.1.2、CAN简介
CAN(Controller Area Network)总线是一种可以在无主机情况下实现微处理器和设备之间相互通信的总线标准。 CAN 网络接口支持 CAN 总线协议 2.0A/B、 ISO11898-1:2015 规范和
BOSCH CAN-FD 规范。CAN 总线控制器集成了可灵活配置的邮箱系统用于 CAN 帧的发送和接收。邮箱系统包含一组邮箱,用于存储控制数据,时间戳,消息标识符和消息数据,最大支持 32 个邮箱。可将邮箱配置为接收 FIFO,接收 FIFO 具有标识符过滤的功能,可最大支持 104 个扩展标识符的过滤,或者 208 个标准标识符的过滤,或者 416 个对标识符部分 8 位的过滤,最多有 32 个标识符过滤表元素可通过接收 FIFO/邮箱私有过滤寄存器进行配置。
注: GD32H737xx 系列不支持 CAN FD 帧。
1.1.3、主要特征
支持CAN总线协议2.0A/B;
遵循ISO 11898-1:2015规范;
支持CAN FD帧,最大64字节数据,通信波特率最大为8 Mbit/s;
支持CAN常规帧,最大8字节数据,通信波特率最大为1 Mbit/s;
支持发送和接收时间戳,基于16位内部计数器;
支持传输延迟补偿,用于CAN FD帧的高速率数据阶段;
中断可配置屏蔽;
支持4种通信模式:正常模式,暂停模式,回环静默模式,和监听模式;
支持2种省电模式: CAN_Disable模式,和虚拟联网模式;
支持2种从虚拟联网模式唤醒的方式:唤醒匹配事件,和唤醒超时事件;
最大32个邮箱,此时每个邮箱都配置为8字节数据长度,可灵活配置为发送或接收邮箱;
支持通过一个特殊帧同步全局网络时间。
发送
支持发送中止;
发送邮箱状态可查看;
发送帧消息的CRC校验;
支持发送优先级:最小邮箱号优先,或最高优先级优先。
接收
接收私有过滤寄存器用于每个接收邮箱或者接收FIFO;
接收邮箱公有过滤寄存器用于接收邮箱,接收FIFO公有过滤寄存器用于接收FIFO;
支持接收优先级,可配置在匹配阶段的接收邮箱和接收FIFO的优先级;
接收FIFO的标识符过滤功能支持最大104个扩展标识符的过滤,或者208个标准标识符的
过滤,或者416个对标识符部分8位的过滤;
深度为6帧的接收FIFO,支持DMA功能
1.1.4、CAN模块结构框图
1.2、电路图部分
开发板上引出了CAN1和CAN2通道接口。
使用CAN1通道时,需要跳线来选择,JP53和JP61来选择CAN1。
CAN2不需要跳线,为了不影响LCD接口,下面使用CAN2接口测试
二、程序部分
2.1、can.c
#include "main.h"
can_mailbox_descriptor_struct transmit_message;
can_mailbox_descriptor_struct receive_message;
FlagStatus can2_receive_flag;
#define BUFFER_SIZE 8U
const uint8_t tx_data[BUFFER_SIZE] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8};
uint8_t rx_data[BUFFER_SIZE];
void can_gpio_config(void)
{
/* configure CAN2 clock source */
rcu_can_clock_config(IDX_CAN2, RCU_CANSRC_APB2_DIV2);
/* enable CAN clock */
rcu_periph_clock_enable(RCU_CAN2);
/* enable CAN port clock */
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOF);
/* configure CAN2_RX GPIO */
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_af_set(GPIOD, GPIO_AF_5, GPIO_PIN_12);
/* configure CAN2_TX GPIO */
gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_af_set(GPIOF, GPIO_AF_2, GPIO_PIN_7);
}
void can_config(void)
{
can_parameter_struct can_parameter;
/* initialize CAN register */
can_deinit(CAN2);
/* initialize CAN */
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
/* initialize CAN parameters */
can_parameter.internal_counter_source = CAN_TIMER_SOURCE_BIT_CLOCK;
can_parameter.self_reception = DISABLE;
can_parameter.mb_tx_order = CAN_TX_HIGH_PRIORITY_MB_FIRST;
can_parameter.mb_tx_abort_enable = ENABLE;
can_parameter.local_priority_enable = DISABLE;
can_parameter.mb_rx_ide_rtr_type = CAN_IDE_RTR_FILTERED;
can_parameter.mb_remote_frame = CAN_STORE_REMOTE_REQUEST_FRAME;
can_parameter.rx_private_filter_queue_enable = DISABLE;
can_parameter.edge_filter_enable = DISABLE;
can_parameter.protocol_exception_enable = DISABLE;
can_parameter.rx_filter_order = CAN_RX_FILTER_ORDER_MAILBOX_FIRST;
can_parameter.memory_size = CAN_MEMSIZE_32_UNIT;
/* filter configuration */
can_parameter.mb_public_filter = 0U;
/* baud rate 1Mbps, sample point at 80% */
can_parameter.resync_jump_width = 1U;
can_parameter.prop_time_segment = 2U;
can_parameter.time_segment_1 = 5U;
can_parameter.time_segment_2 = 2U;
can_parameter.prescaler = 15U;
/* initialize CAN */
can_init(CAN2, &can_parameter);
/* configure CAN1 NVIC */
nvic_irq_enable(CAN2_Message_IRQn, 0U, 0U);
/* enable CAN MB0 interrupt */
can_interrupt_enable(CAN2, CAN_INT_MB0);
can_operation_mode_enter(CAN2, CAN_NORMAL_MODE);
}
void init_can(void)
{
can_struct_para_init(CAN_MDSC_STRUCT, &transmit_message);
can_struct_para_init(CAN_MDSC_STRUCT, &receive_message);
can_gpio_config();
can_config();
/* initialize transmit message */
transmit_message.rtr = 0U;
transmit_message.ide = 0U;
transmit_message.code = CAN_MB_TX_STATUS_DATA;
transmit_message.brs = 0U;
transmit_message.fdf = 0U;
transmit_message.prio = 0U;
transmit_message.data_bytes = BUFFER_SIZE;
/* tx message content */
transmit_message.data = (uint32_t *)(tx_data);
transmit_message.id = 0x55U;
receive_message.rtr = 0U;
receive_message.ide = 0U;
receive_message.code = CAN_MB_RX_STATUS_EMPTY;
/* rx mailbox */
receive_message.id = 0x55U;
receive_message.data = (uint32_t *)(rx_data);
can_mailbox_config(CAN2, 0U, &receive_message);
}
void can2_rx_hdl(void)
{
uint8_t i = 0U;
if(SET == can2_receive_flag)
{
can2_receive_flag = RESET;
/* check the receive message */
can_mailbox_receive_data_read(CAN2, 0U, &receive_message);
printf("\r\nCAN2 receive data: \r\n");
printf("CAN2 ID : %x\r\n",receive_message.id);
printf("CAN2 RXDAT : ");
for(i = 0U; i < receive_message.data_bytes; i++)
{
printf("%02x ", rx_data[i]);
}
printf("\r\n");
can2_txbuf(receive_message.id+1,receive_message.ide, receive_message.data_bytes, rx_data);
}
}
void can2_txbuf(uint32_t id, uint8_t ide, uint8_t dlc, uint8_t *txbuf)
{
uint8_t i=0;
transmit_message.data = (uint32_t *)(txbuf);
transmit_message.id = id;
transmit_message.dlc = dlc;
transmit_message.ide = ide;
can_mailbox_config(CAN2, 1U, &transmit_message);
printf("\r\nCAN2 transmit data: \r\n");
printf("CAN2 ID : %x\r\n",id);
printf("CAN2 TXDAT : ");
for(i = 0U; i < transmit_message.data_bytes; i++) {
printf("%02x ", txbuf[i]);
}
printf("\r\n");
}
2.2、can.h
#ifndef _CAN_H
#define _CAN_H
void init_can(void);
void can2_txbuf(uint32_t id, uint8_t ide, uint8_t dlc, uint8_t *txbuf);
void can2_rx_hdl(void);
#endif
2.3、main.c
#include "main.h"
void cache_enable(void);
int main(void)
{
uint8_t x=0;
uint32_t sd=0;
uint32_t yd=0;
uint8_t tx_dat[8];
cache_enable();
systick_config();
init_usart(115200);
init_can();
while(1)
{
can2_rx_hdl();
}
}
void cache_enable(void)
{
/* enable i-cache */
SCB_EnableICache();
/* enable d-cache */
SCB_EnableDCache();
}
三、测试结果
CAN2接收到标准帧或扩展帧后,将接收到的数据,以ID+1的地址发送接收到的数据。
四、附件
程序代码:
|