GD32F103C8T6入门教程-CAN外设回环测试
基础知识相关stm32CAN外设
外设特征:
3个发送邮箱
2个深度为3个邮箱的接收FIFO
自动重传
自动唤醒
发送、接收时间戳
最大速率1Mbps
3种工作模式
睡眠模式:可以检车总线状态自动唤醒
初始化工作模式:如果需要对 CAN 总线通信参数调整, CAN 必须进入初始化工作模式
正常工作模式:
4中通讯模式:
静默通讯模式
回环通讯模式:发送的数据又可以被自己接收,同时这些发送数据也送至 CAN 网络
静默回环模式:CAN 总线控制器既不从CAN 网络接收数据,也不向 CAN 网络发送数据
正常模式:
数据发送:
选择一个空闲邮箱
配置发送寄存器
使能发送
检测发送转态和错误标志
数据接收
查看FIFO中的帧数量
通过2个深度为3个个邮箱的FIFO接收数据,读取数据
释放邮箱 4个中断向量
发送中断{3个邮箱空闲中断}
fifo0中断{FIFO有数据,数据满,数据溢出}
FIFO1中断
错误和状态改变中断{错误,唤醒,进入睡眠}
CAN外设挂载在APB1 ,APB1 最大时钟54MHz 过滤器
掩码模式和列表模式
16位或32位
例程:CAN回环模式下的数据发送接收测试
CAN设置必须使能过滤器,关闭过滤器接收数据失败 CAN外设的基本初始化
/*
can 外设基本初始化
*/
void can_loopback_init(void)
{
can_parameter_struct can_parameter;
can_filter_parameter_struct can_filter;
//使能外设时钟
rcu_periph_clock_enable(RCU_CAN0);
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);
/* 复位CAN外设 */
can_deinit(CANX);
/* initialize CAN */
can_parameter.time_triggered = DISABLE;//时间触发
can_parameter.auto_bus_off_recovery = DISABLE;//自动离线
can_parameter.auto_wake_up = DISABLE;//自动唤醒
can_parameter.no_auto_retrans = DISABLE;//自动重发
can_parameter.rec_fifo_overwrite = DISABLE;//禁用FIFO满覆盖
can_parameter.trans_fifo_order = DISABLE;//标识符小的先发送,发送优先级
can_parameter.working_mode = CAN_LOOPBACK_MODE;//工作模式,回环模式
/* 配置波特率为 125kbps CAN外设的时钟是在APB1=54MHz,125K = 54Mhz/48(分频)/(1+5+3)*/
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;//固定一个TQ
can_parameter.time_segment_1 = CAN_BT_BS1_5TQ;//1-16个TQ
can_parameter.time_segment_2 = CAN_BT_BS2_3TQ;//可选1-8个TQ
can_parameter.prescaler = 48;
can_init(CANX, &can_parameter);
/* initialize filter */
#ifdefCAN0_USED
/* CAN0 filter number */
can_filter.filter_number = 0;
#else
/* CAN1 filter number过滤器数量*/
can_filter.filter_number = 15;
#endif
/* initialize filter */
can_filter.filter_mode = CAN_FILTERMODE_MASK;//掩码模式
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
can_filter.filter_list_high = 0x0000;
can_filter.filter_list_low = 0x0000;
can_filter.filter_mask_high = 0x0000;
can_filter.filter_mask_low = 0x0000;
can_filter.filter_fifo_number = CAN_FIFO1;//过滤器关联的FIFO
can_filter.filter_enable = ENABLE;
can_filter_init(&can_filter);
}
轮训模式下的数据发送接收测试函数
/*
轮训模式下CAN数据发送和接收测试,使用CAN的回环模式
*/
ErrStatus can_loopback(void)
{
can_trasnmit_message_struct transmit_message;
can_receive_message_structreceive_message;
uint32_t timeout = 0xFFFF;
uint8_t transmit_mailbox = 0;
/* 初始化 CAN */
can_loopback_init();
/* initialize transmit message 初始化发送消息结构 */
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
transmit_message.tx_sfid = 0x11;//标准帧ID
transmit_message.tx_ft = CAN_FT_DATA;//数据帧
transmit_message.tx_ff = CAN_FF_STANDARD;//标准帧
transmit_message.tx_dlen = 2;//数据长度
transmit_message.tx_data = 0xAB;//数据adcd
transmit_message.tx_data = 0xCD;
/* initialize receive message初始化发送消息结构 */
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
/* transmit message 发送消息 返回邮箱编号*/
transmit_mailbox = can_message_transmit(CANX, &transmit_message);
/* waiting for transmit completed 等待消息发送完成*/
while((CAN_TRANSMIT_OK != can_transmit_states(CANX, transmit_mailbox)) && (0 != timeout))
{
timeout--;
}
timeout = 0xFFFF;
/* waiting for receive completed 等待接收完成*/
while((can_receive_message_length_get(CANX, CAN_FIFO1) < 1) && (0 != timeout))
{
timeout--;
}
/* initialize receive message 初始化接收结构体*/
receive_message.rx_sfid = 0x00;
receive_message.rx_ff = 0;
receive_message.rx_dlen = 0;
receive_message.rx_data = 0x00;
receive_message.rx_data = 0x00;
//接收数据
can_message_receive(CANX, CAN_FIFO1, &receive_message);
printf("recv:%02x %02x", (int)receive_message.rx_data, (int)receive_message.rx_data);
/* check the receive message */
if((0x11 == receive_message.rx_sfid) && (CAN_FF_STANDARD == receive_message.rx_ff)
&& (2 == receive_message.rx_dlen) && (0xCDAB == (receive_message.rx_data << 8 | receive_message.rx_data)))
{
printf("data send recv ok\r\n");
return SUCCESS;
}
else
{
printf("data send recv error\r\n");
return ERROR;
}
}
中断模式下的数据接收测试
//中断模式下接收数据
ErrStatus can_loopback_interrupt(void)
{
can_trasnmit_message_struct transmit_message;
uint32_t timeout = 0x0000FFFF;
/* initialize CAN and filter 初始化CAN外设和CAN过滤器 */
can_loopback_init();
/* enable CAN receive FIFO1 not empty interrupt打开CAN中断*/
nvic_irq_enable(CAN0_RX1_IRQn, 0, 0);
can_interrupt_enable(CANX, CAN_INT_RFNE1);
/* initialize transmit message */
transmit_message.tx_sfid = 0;
transmit_message.tx_efid = 0x1234; //扩展ID
transmit_message.tx_ff = CAN_FF_EXTENDED;//扩展帧
transmit_message.tx_ft = CAN_FT_DATA;//数据帧
transmit_message.tx_dlen = 2;//数据长度
transmit_message.tx_data = 0xDE;//数据ABCD
transmit_message.tx_data = 0xCA;
/* 发送数据*/
can_message_transmit(CANX, &transmit_message);
/* 等待中断*/
while((SUCCESS != test_flag_interrupt) && (0 != timeout))
{
timeout--;
}
if(0 == timeout)
{
test_flag_interrupt = ERROR;
}
/* disable CAN receive FIFO1 not empty interrupt 关闭CAN设备的FIFO1接收非空中断*/
can_interrupt_disable(CANX, CAN_INTEN_RFNEIE1);
return test_flag_interrupt;
}
CAN外设的中断服务函数
//can0 外设中断服务函数
void CAN0_RX1_IRQHandler(void)
{
can_receive_message_struct receive_message;
/* 初始化消息结构体 */
receive_message.rx_sfid = 0x00;
receive_message.rx_efid = 0x00;
receive_message.rx_ff = 0;
receive_message.rx_dlen = 0;
receive_message.rx_fi = 0;
receive_message.rx_data = 0x00;
receive_message.rx_data = 0x00;
/* 从FIFO1接收消息 */
can_message_receive(CAN0, CAN_FIFO1, &receive_message);
//判断消息是否和发送一致
if((0x1234 == receive_message.rx_efid) && (CAN_FF_EXTENDED == receive_message.rx_ff)
&& (2 == receive_message.rx_dlen) && (0xCADE == (receive_message.rx_data << 8 | receive_message.rx_data)))
{
test_flag_interrupt = SUCCESS;
}
else
{
test_flag_interrupt = ERROR;
}
}
例程测试函数
/*
CAN外设测试函数
*/
void can_test(void)
{
//回环模式下的轮训方式接收数据
test_flag = can_loopback();
if(SUCCESS == test_flag)
{
printf("ok\r\n");
}
else
{
printf("fail\r\n");
}
//中断模式下接收数据
test_flag_interrupt = can_loopback_interrupt();
if(SUCCESS == test_flag_interrupt)
{
printf("ok\r\n");
}
else
{
printf("fail\r\n");
}
while (1);
}
测试截图
CAN的回环测试还是很有用的 回环测试,在自检时比较实用。 CAN外设回环测试成功了 为什么连接另一端就不成功了呢 在can外设回环测试模式下 如何验证我的过滤参数设置是否正确呢 回环模式没有问题 但是正常模式不成功 一般都是什么原因导致的呢 CAN回环模式可以用作系统上电自检。 keaibukelian 发表于 2022-12-7 16:36
回环模式没有问题 但是正常模式不成功 一般都是什么原因导致的呢
首先肯定需要检查寄存器配置另外外部硬件连接看看有没有接错 检查一下线路上的波形是否良好先确保外部的条件都完全满足 请问3个邮箱的接收FIFO的使用顺序是如何定义的呢
页:
[1]
2