查看: 1232|回复: 0

[项目提交] 《2023 DigiKey 汽车应用创意挑战赛》 CAN 驱动适配

[复制链接]
  • TA的每日心情
    奋斗
    2024-12-12 14:13
  • 签到天数: 212 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2024-1-16 17:45:06 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 andeyqi 于 2024-1-16 20:54 编辑

        我们基于之前适配好的系统和PIN驱动的基础上继续适配S32K146的CAN 驱动,有了CAN 驱动我们就可以通过PCAN 模拟车辆内部的CAN 总线数据,接收发送CAN消息至车辆的CAN 总线,完成和其他ECU的信息交互。
    CAN 收发器使用的TJA1043,该IC 只需要按照时序控制对应的PIN脚即可让其进入 normal 模式,对应代码如下:
    1. void can1_control_init(void)
    2. {
    3.     rt_base_t mcu_can1_en;
    4.     rt_base_t mcu_can1_wake;
    5.     rt_base_t mcu_can1_stby;

    6.     /* init can controler pin */
    7.     mcu_can1_en = rt_pin_get(MCU_CAN1_EN);
    8.     mcu_can1_wake = rt_pin_get(MCU_CAN1_WAKE);
    9.     mcu_can1_stby = rt_pin_get(MCU_CAN1_STBY);

    10.     rt_pin_mode(mcu_can1_en,PIN_MODE_OUTPUT);
    11.     rt_pin_mode(mcu_can1_wake,PIN_MODE_OUTPUT);
    12.     rt_pin_mode(mcu_can1_stby,PIN_MODE_OUTPUT);

    13.     /* init tja1043 */
    14.     rt_pin_write(mcu_can1_wake,PIN_HIGH);
    15.     rt_pin_write(mcu_can1_stby,PIN_LOW);
    16.     rt_pin_write(mcu_can1_en,PIN_LOW);

    17.     rt_thread_mdelay(1);

    18.     rt_pin_write(mcu_can1_stby,PIN_HIGH);
    19.     rt_pin_write(mcu_can1_en,PIN_HIGH);

    20.     rt_thread_mdelay(1);

    21.     rt_pin_write(mcu_can1_wake,PIN_LOW);

    22. }
    复制代码
    使用 S32K SDK 中的CAN驱动接口对CAN进行初始化,配置CAN 的波特率为500Kb,及CAN 参数,配置CAN 首发mailbox 资源配置,配置CAN 接收过滤器配置,即可完成CAN 模块的驱动配置对应代码如下:
    1. void can1_init(void)
    2. {
    3.     status_t ret = STATUS_SUCCESS;
    4.     flexcan_id_table_t id_filter_table[40];
    5.     uint16_t i = 0;

    6.     for(i =0; i < 40;i++)
    7.     {
    8.         id_filter_table[i].isRemoteFrame = false;
    9.         id_filter_table[i].isExtendedFrame =false;
    10.         id_filter_table[i].id = 0x400 + (0x10*i);
    11.     }

    12.     ret = FLEXCAN_DRV_Init(INST_FLEXCAN_CONFIG_1,&flexcanState0,&flexcanInitConfig0);
    13.     if(ret != STATUS_SUCCESS)
    14.     {
    15.         rt_kprintf("can1 init failed.\n");
    16.     }

    17.     FLEXCAN_DRV_SetRxMaskType(INST_FLEXCAN_CONFIG_1,FLEXCAN_RX_MASK_INDIVIDUAL);

    18.     FLEXCAN_DRV_ConfigRxFifo(INST_FLEXCAN_CONFIG_1, FLEXCAN_RX_FIFO_ID_FORMAT_A, id_filter_table);

    19.     for(i = 0;i < 16; i++)
    20.     {
    21.         ret = FLEXCAN_DRV_SetRxIndividualMask(INST_FLEXCAN_CONFIG_1, FLEXCAN_MSG_ID_STD, i, 0x7ff);
    22.         if( ret != STATUS_SUCCESS )
    23.         {
    24.             rt_kprintf( "can1 set rx filter failed %x.\n",ret);
    25.         }
    26.     }
    27. }
    复制代码

    驱动配置完之后,我们创建一收一发线程用于处理CAN 接收发送的数据,对应代码如下:
    1. #define THREAD_PRIORITY      25
    2. #define THREAD_STACK_SIZE    1024
    3. #define THREAD_TIMESLICE     5


    4. void cantx_entry(void *parameter)
    5. {
    6.     can1_control_init();
    7.     can1_init();

    8.     flexcan_data_info_t msg =
    9.     {
    10.         .data_length = 8,
    11.         .msg_id_type = FLEXCAN_MSG_ID_STD,
    12.         .enable_brs  = false,
    13.         .fd_enable   = false,
    14.         .fd_padding  = 0U,
    15.         .is_remote   = false
    16.     };

    17.     static uint8_t buff[8] = {0x55,0xaa,0x55,0xaa,0xaa,0xbb,0xcc,0xdd};

    18.     while(1)
    19.     {
    20.         FLEXCAN_DRV_Send(INST_FLEXCAN_CONFIG_1,16,&msg,0x100,buff);

    21.         rt_thread_mdelay(100);
    22.     }
    23. }


    24. void canrx_entry(void *parameter)
    25. {
    26.     static flexcan_msgbuff_t data;
    27.     status_t ret = STATUS_SUCCESS;

    28.     while(1)
    29.     {
    30.         ret = FLEXCAN_DRV_RxFifo(INST_FLEXCAN_CONFIG_1,&data);

    31.         if(ret == STATUS_SUCCESS)
    32.         {
    33.             rt_kprintf("id = %x :%x %x %x %x %x %x %x %x\n",data.msgId,\
    34.             data.data[0],data.data[1],data.data[2],data.data[3],\
    35.             data.data[4],data.data[5],data.data[6],data.data[7]);
    36.         }

    37.         rt_thread_mdelay(10);
    38.     }
    39. }


    40. int can_sample(void)
    41. {
    42.     rt_thread_t tid = RT_NULL;

    43.     tid = rt_thread_create("cantx",
    44.                            cantx_entry, RT_NULL,
    45.                            THREAD_STACK_SIZE,
    46.                            THREAD_PRIORITY,
    47.                            THREAD_TIMESLICE);
    48.     if (tid != RT_NULL)
    49.         rt_thread_startup(tid);

    50.      tid = rt_thread_create("canrx",
    51.                            canrx_entry, RT_NULL,
    52.                            THREAD_STACK_SIZE,
    53.                            THREAD_PRIORITY,
    54.                            THREAD_TIMESLICE);
    55.     if (tid != RT_NULL)
    56.         rt_thread_startup(tid);

    57.     return 0;
    58. }
    59. MSH_CMD_EXPORT_ALIAS(can_sample, can ,can sample);
    复制代码
    对应玩上述驱动,我们通过usb can 模拟发送0x400 消息携带车速及车窗状态信息,通过串口输出运行如下,可以看到can 通信的发送接收都工作,已经能模拟采集车辆的CAN总线数据了。
    20240116-204923.gif


    /*代码路径如下*/


    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /5 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-12-24 08:40 , Processed in 0.111868 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.