打印
[研电赛技术支持]

GD32F103C8T6入门教程-CAN外设回环测试

[复制链接]
1281|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kqh11a|  楼主 | 2022-11-18 15:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
基础知识

相关stm32CAN外设
外设特征:

3个发送邮箱
2个深度为3个邮箱的接收FIFO
自动重传
自动唤醒
发送、接收时间戳
最大速率1Mbps
3种工作模式

睡眠模式:可以检车总线状态自动唤醒
初始化工作模式:如果需要对 CAN 总线通信参数调整, CAN 必须进入初始化工作模式
正常工作模式:
4中通讯模式:

静默通讯模式
回环通讯模式:发送的数据又可以被自己接收,同时这些发送数据也送至 CAN 网络
静默回环模式:CAN 总线控制器既不从CAN 网络接收数据,也不向 CAN 网络发送数据
正常模式:

使用特权

评论回复
评论
kqh11a 2022-11-18 15:47 回复TA
———————————————— 版权声明:本文为CSDN博主「Car12」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u010261063/article/details/124251643 
沙发
kqh11a|  楼主 | 2022-11-18 15:48 | 只看该作者
数据发送:

选择一个空闲邮箱
配置发送寄存器
使能发送
检测发送转态和错误标志
数据接收

查看FIFO中的帧数量

通过2个深度为3个个邮箱的FIFO接收数据,读取数据

释放邮箱

使用特权

评论回复
板凳
kqh11a|  楼主 | 2022-11-18 15:49 | 只看该作者
4个中断向量

发送中断{3个邮箱空闲中断}
fifo0中断{FIFO有数据,数据满,数据溢出}
FIFO1中断
错误和状态改变中断{错误,唤醒,进入睡眠}
CAN外设挂载在APB1 ,APB1 最大时钟54MHz

使用特权

评论回复
地板
kqh11a|  楼主 | 2022-11-18 15:50 | 只看该作者
过滤器

掩码模式和列表模式
16位或32位

使用特权

评论回复
5
kqh11a|  楼主 | 2022-11-18 15:51 | 只看该作者
例程:CAN回环模式下的数据发送接收测试

CAN设置必须使能过滤器,关闭过滤器接收数据失败

使用特权

评论回复
6
kqh11a|  楼主 | 2022-11-18 15:52 | 只看该作者
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 */
    #ifdef  CAN0_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);
}

使用特权

评论回复
7
kqh11a|  楼主 | 2022-11-18 15:52 | 只看该作者
轮训模式下的数据发送接收测试函数

/*
        轮训模式下CAN数据发送和接收测试,使用CAN的回环模式
*/
ErrStatus can_loopback(void)
{
    can_trasnmit_message_struct transmit_message;
    can_receive_message_struct  receive_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[0] = 0xAB;//数据adcd
    transmit_message.tx_data[1] = 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[0] = 0x00;
    receive_message.rx_data[1] = 0x00;
    //接收数据
    can_message_receive(CANX, CAN_FIFO1, &receive_message);
    printf("recv:%02x %02x", (int)receive_message.rx_data[0], (int)receive_message.rx_data[1]);

    /* 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[1] << 8 | receive_message.rx_data[0])))
    {

        printf("data send recv ok\r\n");
        return SUCCESS;
    }
    else
    {
        printf("data send recv error\r\n");
        return ERROR;
    }
}

使用特权

评论回复
8
kqh11a|  楼主 | 2022-11-18 15:53 | 只看该作者
中断模式下的数据接收测试
//中断模式下接收数据
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[0] = 0xDE;//数据ABCD
    transmit_message.tx_data[1] = 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;
}


使用特权

评论回复
9
kqh11a|  楼主 | 2022-11-18 16:36 | 只看该作者
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[0] = 0x00;
    receive_message.rx_data[1] = 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[1] << 8 | receive_message.rx_data[0])))
    {
        test_flag_interrupt = SUCCESS;
    }
    else
    {
        test_flag_interrupt = ERROR;
    }
}

使用特权

评论回复
10
kqh11a|  楼主 | 2022-11-18 16:38 | 只看该作者
例程测试函数
/*
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);
}


使用特权

评论回复
11
kqh11a|  楼主 | 2022-11-18 16:48 | 只看该作者
测试截图

使用特权

评论回复
12
chenqianqian| | 2022-11-19 10:45 | 只看该作者
CAN的回环测试还是很有用的

使用特权

评论回复
13
daichaodai| | 2022-11-19 17:44 | 只看该作者
回环测试,在自检时比较实用。

使用特权

评论回复
14
tpgf| | 2022-12-7 16:05 | 只看该作者
CAN外设回环测试成功了 为什么连接另一端就不成功了呢

使用特权

评论回复
15
heimaojingzhang| | 2022-12-7 16:27 | 只看该作者
在can外设回环测试模式下 如何验证我的过滤参数设置是否正确呢

使用特权

评论回复
16
keaibukelian| | 2022-12-7 16:36 | 只看该作者
回环模式没有问题 但是正常模式不成功 一般都是什么原因导致的呢

使用特权

评论回复
17
weifeng90| | 2022-12-7 17:46 | 只看该作者
CAN回环模式可以用作系统上电自检。

使用特权

评论回复
18
paotangsan| | 2022-12-8 08:58 | 只看该作者
keaibukelian 发表于 2022-12-7 16:36
回环模式没有问题 但是正常模式不成功 一般都是什么原因导致的呢

首先肯定需要检查寄存器配置  另外外部硬件连接看看有没有接错

使用特权

评论回复
19
renzheshengui| | 2022-12-8 09:32 | 只看该作者
检查一下线路上的波形是否良好  先确保外部的条件都完全满足

使用特权

评论回复
20
wakayi| | 2022-12-8 10:48 | 只看该作者
请问3个邮箱的接收FIFO的使用顺序是如何定义的呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

499

帖子

0

粉丝