在RT-Thread中给STM32F413添加CAN3

在RT-Thread中给STM32F413添加CAN3简介目前最新的RT-Thread v4.0.2并不能直接支持STM32F413的CAN3,从配置项添加的CAN驱动只能够支持CAN1 / CAN2,而F413的CAN3需要我们手动添加。创建STM32F413工程首先新建一个工程stm32f413-xxx-xxx复制模板代码bsp\stm32\libraries\templates\stm32f4xx,在《bsp\stm32\docs\STM32系列BSP制作教程.md》文件中有介绍在bsp\
摘要由CSDN通过智能技术生成

在RT-Thread中给STM32F413添加CAN3

简介

目前最新的RT-Thread v4.0.2并不能直接支持STM32F413的CAN3,从配置项添加的CAN驱动只能够支持CAN1 / CAN2,而F413的CAN3需要我们手动添加。

创建STM32F413工程

首先新建一个工程stm32f413-xxx-xxx
复制模板代码bsp\stm32\libraries\templates\stm32f4xx,在《bsp\stm32\docs\STM32系列BSP制作教程.md》文件中有介绍
在bsp\stm32\stm32f413-xxx-xxx\board\Kconfig文件中修改MCU型号,改为:

config SOC_STM32F413VG

添加CAN3驱动代码

在bsp\stm32\stm32f413-xxx-xxx\board\Kconfig文件中添加CAN配置项

menuconfig BSP_USING_CAN
        bool "Enable CAN"
        default y
        select RT_USING_CAN
        if BSP_USING_CAN
            config BSP_USING_CAN1
                bool "Enable CAN1"
                default y
            config BSP_USING_CAN2
                bool "Enable CAN2"
                default y
            config BSP_USING_CAN3
                bool "Enable CAN3"
                default y
        endif

添加文件bsp\stm32\stm32f413-xxx-xxx\board\drv_can.c,含CAN3代码

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-08-05     Xeon Xu      the first version
 * 2019-01-22     YLZ          port from stm324xx-HAL to bsp stm3210x-HAL
 * 2019-02-19     YLZ          add support EXTID RTR Frame. modify send, recv functions.
 *                             fix bug.port to BSP [stm32]
 * 2019-03-27     YLZ          support double can channels, support stm32F4xx (only Legacy mode).
 * 2019-06-17     YLZ          port to new STM32F1xx HAL V1.1.3.
 * 2021-04-19     unit,lhs     support 3 can channels, support stm32F413VGTx
 */
#include "drv_can.h"
#ifdef BSP_USING_CAN

#define LOG_TAG    "drv_can"
#include <drv_log.h>

/* attention !!! baud calculation example: Tclk / ((ss + bs1 + bs2) * brp)  36 / ((1 + 8 + 3) * 3) = 1MHz*/
#if defined (SOC_SERIES_STM32F1)/* APB1 36MHz(max) */
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
{
   
    {
   CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 3)},
    {
   CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_5TQ  | CAN_BS2_3TQ | 5)},
    {
   CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 6)},
    {
   CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 12)},
    {
   CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 24)},
    {
   CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 30)},
    {
   CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 60)},
    {
   CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 150)},
    {
   CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 300)}
};
#elif defined (SOC_SERIES_STM32F4)/* APB1 45MHz(max) */
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
{
   
    {
   CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 3)},
    {
   CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_5TQ | 4)},
    {
   CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 6)},
    {
   CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 12)},
    {
   CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 24)},
    {
   CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 30)},
    {
   CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 60)},
    {
   CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 150)},
    {
   CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 300)}
};
#elif defined (SOC_SERIES_STM32F7)/* APB1 54MHz(max) */
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
{
   
    {
   CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 3)},
    {
   CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_7TQ | 4)},
    {
   CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 6)},
    {
   CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 12)},
    {
   CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 24)},
    {
   CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 30)},
    {
   CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 60)},
    {
   CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 150)},
    {
   CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_10TQ  | CAN_BS2_7TQ | 300)}
};
#endif

#ifdef BSP_USING_CAN1
static struct stm32_can drv_can1 =
{
   
    .name = "can1",
    .CanHandle.Instance = CAN1,
};
#endif

#ifdef BSP_USING_CAN2
static struct stm32_can drv_can2 =
{
   
    "can2",
    .CanHandle.Instance = CAN2,
};
#endif

#ifdef BSP_USING_CAN3
static struct stm32_can drv_can3 =
{
   
    "can3",
    .CanHandle.Instance = CAN3,
};
#endif

static rt_uint32_t get_can_baud_index(rt_uint32_t baud)
{
   
    rt_uint32_t len, index;

    len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]);
    for (index = 0; index < len; index++)
    {
   
        if (can_baud_rate_tab[index].baud_rate == baud)
            return index;
    }

    return 0; /* default baud is CAN1MBaud */
}

static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
{
   
    struct stm32_can *drv_can;
    rt_uint32_t baud_index;

    RT_ASSERT(can);
    RT_ASSERT(cfg);
    drv_can = (struct stm32_can *)can->parent.user_data;
    RT_ASSERT(drv_can);

    drv_can->CanHandle.Init.TimeTriggeredMode = DISABLE;
    drv_can->CanHandle.Init.AutoBusOff = ENABLE;
    drv_can->CanHandle.Init.AutoWakeUp = DISABLE;
    drv_can->CanHandle.Init.AutoRetransmission = DISABLE;
    drv_can->CanHandle.Init.ReceiveFifoLocked = DISABLE;
    drv_can->CanHandle.Init.TransmitFifoPriority = ENABLE;

    switch (cfg->mode)
    {
   
    case RT_CAN_MODE_NORMAL:
        drv_can->CanHandle.Init.Mode = CAN_MODE_NORMAL;
        break;
    case RT_CAN_MODE_LISEN:
        drv_can->CanHandle.Init.Mode = CAN_MODE_SILENT;
        break;
    case RT_CAN_MODE_LOOPBACK:
        drv_can->CanHandle.Init.Mode = CAN_MODE_LOOPBACK;
        break;
    case RT_CAN_MODE_LOOPBACKANLISEN:
        drv_can->CanHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
        break;
    }

    baud_index = get_can_baud_index(cfg->baud_rate);
    drv_can->CanHandle.Init.SyncJumpWidth = BAUD_DATA(SJW, baud_index);
    drv_can->CanHandle.Init.TimeSeg1 = BAUD_DATA(BS1, baud_index);
    drv_can->CanHandle.Init.TimeSeg2 = BAUD_DATA(BS2, baud_index);
    drv_can->CanHandle.Init.Prescaler = BAUD_DATA(RRESCL, baud_index);
    /* init can */
    if (HAL_CAN_Init(&drv_can->CanHandle) != HAL_OK)
    {
   
        return -RT_ERROR;
    }

    /* default filter config */
    HAL_CAN_ConfigFilter(&drv_can->CanHandle, &drv_can->FilterConfig);
    /* can start */
    HAL_CAN_Start(&drv_can->CanHandle);

    return RT_EOK;
}

static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
{
   
    rt_uint32_t argval;
    struct stm32_can *drv_can;
    struct rt_can_filter_config *filter_cfg;

    RT_ASSERT(can != RT_NULL);
    drv_can = (struct stm32_can *)can->parent.user_data;
    RT_ASSERT(drv_can != RT_NULL);

    switch (cmd)
    {
   
    case RT_DEVICE_CTRL_CLR_INT:
        argval = (rt_uint32_t) arg;
        if (argval == RT_DEVICE_FLAG_INT_RX)
        {
   
            if (CAN1 == drv_can->CanHandle.Instance)
            {
   
                HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
                HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
            }
#ifdef CAN2
            if (CAN2 == drv_can->CanHandle.Instance)
            {
   
                HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn);
                HAL_NVIC_DisableIRQ(CAN2_RX1_IRQn);
            }
#endif
#ifdef CAN3
            if (CAN3 == drv_can->CanHandle.Instance)
            {
   
                HAL_NVIC_DisableIRQ(CAN3_RX0_IRQn);
                HAL_NVIC_DisableIRQ(CAN3_RX1_IRQn);
            }
#endif
            __HAL_CAN_DISABLE_IT(&drv_can->CanHandle, CAN_IT_RX_FIFO0_MSG_PENDING);
            __HAL_CAN_DISABLE_IT(&drv_can->CanHandle, CAN_IT_RX_FIFO0_FULL);
            __HAL_CAN_DISABLE_IT(&drv_can->CanHandle, CAN_IT_RX_FIFO0_OVERRUN);
            __HAL_CAN_DISABLE_IT(&drv_can->CanHandle, CAN_IT_RX_FIFO1_MSG_PENDING);
            __HAL_CAN_DISABLE_IT(&drv_can->CanHandle, CAN_IT_RX_FIFO1_FULL);
            __HAL_CAN_DISABLE_IT(&drv_can->CanHandle, CAN_IT_RX_FIFO1_OVERRUN);
        }
        else if (argval == RT_DEVICE_FLAG_INT_TX)
        {
   
            if (CAN1 == drv_can
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值