[技术问答]

【分享】HC32F072 CAN 驱动中如何添加过滤器

[复制链接]
2024|10
手机看帖
扫描二维码
随时随地手机跟帖
caizhiwei|  楼主 | 2020-6-10 20:35 | 显示全部楼层 |阅读模式
本帖最后由 caizhiwei 于 2020-6-10 20:37 编辑

        CAN总线是一种可以在四轴飞行器情况下实现微处理器或者设备之间相互通信的总线标准。本模块遵循 CAN 总线协议 2.0A 和 2.0B 协议并向上兼容 CAN-FD。 CAN 总线控制器可以处理总线上的数据收发,在本产品中, CAN 具有 8组筛选器。筛选器用于为应用程序选择要接收的消息。应用程序通过 1 个高优先级的主发送缓冲器( Primary Transmit Buffer, 以下简称 PTB)和 4 个辅发送缓冲器( Secondary Transmit Buffer, 以下简称 STB) 将发送数据送至总线,由发送调度器决定邮箱发送顺序。通过 10 个接收缓冲器( Receive Buffer, 以下简称 RB)获取总线数据。 4 个 STB 以及 10 个 RB 可以理解为一个 4 级 FIFO 和一个 10级 FIFO, FIFO 完全由硬件控制。CAN 总线控制器同时也可以支持时间触发 CAN 通信( Time-trigger communication)。
      也就是接收白名单最多可以设置8个,当然不严格的情况下,也可以超过8个ID的。
#include "bsp_can.h"
#include "bsp_led.h"
#include "bsp_timer.h"

stc_can_rxframe_t   stcRxFrame;
stc_can_txframe_t   TxFrame_Gain;
stc_can_txframe_t   TxFrame_Keepalive;

stc_can_t APP_CAN;

en_ACC_Status ACC_Status = Off;

extern void PWM_duty_adjust(uint16_t adc_value, uint16_t MAX_Value);

static void Can_Gpio_Init(void)
{
    stc_gpio_cfg_t stcGpioCfg;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    ///< 端口方向配置->输入
    stcGpioCfg.enDir = GpioDirIn;
    ///< 端口驱动能力配置->高驱动能力
    stcGpioCfg.enDrv = GpioDrvL;
    ///< 端口上下拉配置->无
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdDisable;
    ///< 端口开漏输出配置->开漏输出关闭
    stcGpioCfg.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    stcGpioCfg.enCtrlMode = GpioAHB;

    Gpio_Init(EVB_CAN_RX_PORT, EVB_CAN_RX_PIN, &stcGpioCfg);
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(EVB_CAN_TX_PORT, EVB_CAN_TX_PIN, &stcGpioCfg);
    Gpio_Init(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN, &stcGpioCfg);

    ///<CAN RX\TX复用功能配置
    Gpio_SetAfMode(EVB_CAN_RX_PORT, EVB_CAN_RX_PIN, GpioAf3);
    Gpio_SetAfMode(EVB_CAN_TX_PORT, EVB_CAN_TX_PIN, GpioAf5);

    ///<STB 低-PHY有效
    Gpio_ClrIO(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN);
}


#ifdef CAN_CHIP_TJA1043

/*
TJA1043 刚上电是出于激活状态的,如果CAN总线没有数据,30s左右会休眠
3个IO需要配置:
IO_ERR 检测总线出错标志(可以忽略)
IO_EN 芯片使能
IO_INH 使能外部LDO +5V
IO_STB_N standby模式使能
*/
static void TJA1043_Gpio_Init(void)
{
    stc_gpio_cfg_t stcGpioCfg;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    ///< 端口方向配置->输出
    stcGpioCfg.enDir = GpioDirOut;
    ///< 端口驱动能力配置->高驱动能力
    stcGpioCfg.enDrv = GpioDrvH;
    ///< 端口上下拉配置->无
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdDisable;
    ///< 端口开漏输出配置->开漏输出关闭
    stcGpioCfg.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    stcGpioCfg.enCtrlMode = GpioAHB;
        
    Gpio_Init(GpioPortA, GpioPin3, &stcGpioCfg); // STB_N
    Gpio_Init(GpioPortB, GpioPin3, &stcGpioCfg); //IO_INH  
    Gpio_Init(GpioPortB, GpioPin7, &stcGpioCfg); // IO_EN
        
        Gpio_ClrIO(GpioPortB, GpioPin3);  /* PB3 IO_INH*/
        delay1ms(10);
    Gpio_SetIO(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN);
        Gpio_SetIO(GpioPortB, GpioPin7);// IO_EN
        
}


void TJA1043_Goto_Sleep(void)
{
        Gpio_ClrIO(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN);
        Gpio_SetIO(GpioPortB, GpioPin7);// IO_EN
}

#endif

void BSP_Can_Init(void)
{
    stc_can_init_config_t   stcCanInitCfg;
    stc_can_filter_t        stcFilter;

        Can_Gpio_Init();

#ifdef CAN_CHIP_TJA1043
        TJA1043_Gpio_Init();        
#endif
        
    Sysctrl_SetPeripheralGate(SysctrlPeripheralCan, TRUE);
    //<<CAN 波特率配置
        // 手册page884.exp: bt = (PRESC+1)((SEG_1+2) + (SEG_2+1))*(1/8M) = 1us (1000k)

#ifdef CAN_CONFIG_48MHZ_500K         
        
        stcCanInitCfg.stcCanBt.PRESC = 6-1;
        stcCanInitCfg.stcCanBt.SEG_1 = 9-2;
        stcCanInitCfg.stcCanBt.SEG_2 = 7-1;        
        stcCanInitCfg.stcCanBt.SJW   = 3-1;        
        
//        stcCanInitCfg.stcCanBt.PRESC = 8-1;
//  stcCanInitCfg.stcCanBt.SEG_1 = 7-2;
//  stcCanInitCfg.stcCanBt.SEG_2 = 5-1;
//  stcCanInitCfg.stcCanBt.SJW   = 5-1;
        
#endif

    stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10;
    stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16-1;

    stcCanInitCfg.enCanRxBufAll  = CanRxNormal;
    stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
    stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;

    CAN_Init(&stcCanInitCfg);

    //<<CAN 滤波器配置 /*u32MASK = 0x1FFFFFFF is all received*/
  
        stcFilter.enAcfFormat = CanStdFrames;

    stcFilter.enFilterSel = CanFilterSel1;
    stcFilter.u32CODE     = CAN_ID_BACKLIGHT;
    stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_BACKLIGHT);   
    CAN_FilterConfig(&stcFilter, TRUE);

        stcFilter.enFilterSel = CanFilterSel2;
    stcFilter.u32CODE     = CAN_ID_ACC;
    stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_ACC);
        CAN_FilterConfig(&stcFilter, TRUE);
        
        stcFilter.enFilterSel = CanFilterSel3;
    stcFilter.u32CODE     = CAN_ID_BRAKE_X;
    stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_BRAKE_X);
    CAN_FilterConfig(&stcFilter, TRUE);

        stcFilter.enFilterSel = CanFilterSel4;
        stcFilter.u32CODE     = CAN_ID_BRAKE_SIGNAL;
        stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_BRAKE_SIGNAL);
        CAN_FilterConfig(&stcFilter, TRUE);

    CAN_IrqCmd(CanRxIrqEn, TRUE); /* 接收中断使能 */
        CAN_IrqCmd(CanBusErrorIrqEn, TRUE); /*总线错误中断使能*/
    EnableNvic(CAN_IRQn, IrqLevel0, TRUE);
}


/********************************************************************************************************
**函数信息 :void CAN_send_Frame()
**功能描述 :CAN发送一帧报文
**输入参数 :stcTxFrame
**输出参数 :None
**    备注  目前只考虑标准帧
********************************************************************************************************/
void CAN_send_Frame(stc_can_txframe_t *TxFrame, uint8_t frame_len)
{
        TxFrame->Control_f.DLC = frame_len;
        TxFrame->Control_f.IDE = 0; /*标准帧 or 扩展帧*/
        TxFrame->Control_f.RTR = 0; /*数据帧 or 远程帧*/
        TxFrame->enBufferSel = (en_can_buffer_sel_t)0U; /*使用主缓冲器*/
        CAN_SetFrame(TxFrame); /*数据塞进fifo缓冲器*/        
        CAN_TransmitCmd(CanPTBTxCmd);
}
        

void Can_IRQHandler(void)
{
    if(TRUE == CAN_Irq**Get(CanBusErrorIrq**))  /*当总线短路时,进入此中断*/
        {         
                CAN_Irq**Clr(CanBusErrorIrq**);         
                APP_CAN.BusErrorFlag = TRUE;
                // M0P_CAN->CFG_STAT = 0x00; /* 清除由硬件置位的Reset 标志位,必须在中断外部执行*/                 
        }         
        if(TRUE == CAN_Irq**Get(CanRxIrq**))
    {
        CAN_Irq**Clr(CanRxIrq**);
        CAN_Receive(&stcRxFrame);
                APP_CAN.RxFlag = TRUE;
                APP_CAN.Rx_cnt = 0;
                /*总线上发送周期约500ms*/
                if( CAN_ID_BACKLIGHT == stcRxFrame.StdID )
                {
                        if(stcRxFrame.Data[0] & 0x04)
                        {
                                LED_ON;
                        }        
                        else
                        {
                                LED_OFF;
                        }
                }
                /*
                XX 00 00 20 52 FF FB 00
                XX:02 (ON)  00(OFF)
                */        
                if (CAN_ID_ACC == stcRxFrame.StdID)
                {
                        if(stcRxFrame.Data[0]&0x02)
                        {
                                ACC_Status = On;
                        }
                        else
                        {                        
                                ACC_Status = Off;  /* ACC off 后延时30s进入休眠*/                        
                        }
                }

                if (CAN_ID_BRAKE_X == stcRxFrame.StdID)
                {
                        APP_CAN.brake_value = (stcRxFrame.Data[0]<<8) + stcRxFrame.Data[1];        
                        APP_CAN.RxFlag_Break = TRUE;
                        
                }

                if (CAN_ID_BRAKE_SIGNAL == stcRxFrame.StdID)
                {               
                        if( stcRxFrame.Data[2]&0x80)
                        {
                                APP_CAN.brake_signal = TRUE;
                        }
                        else
                        {                        
                                APP_CAN.brake_signal = FALSE;
                        }
                }               
    }
}

void CAN_BUS_Process(void)
{
        //if(ACC_Status == On) // AccOff 状态也需要发送数据
        {
                 if(APP_CAN.CANSendFlag) /*100ms*/
                 {
                        APP_CAN.CANSendFlag = FALSE;
                        CAN_send_Frame(&TxFrame_Gain, 8);
                 }
                if(APP_CAN.CAN_keepalive_SendFlag) /*心跳包数据,1s发送一次*/
                 {
                        APP_CAN.CAN_keepalive_SendFlag = FALSE;        
                        CAN_send_Frame(&TxFrame_Keepalive, 8);
                 }
        }        
        if(APP_CAN.BusErrorFlag)
        {
                APP_CAN.BusErrorFlag = FALSE;
                M0P_CAN->CFG_STAT = 0x00;
        }
}
829275ee0d38d68df6.png


使用特权

评论回复
caizhiwei|  楼主 | 2020-6-10 20:36 | 显示全部楼层
驱动代码中有2个关键点。

使用特权

评论回复
sgrtf661| | 2020-6-11 14:07 | 显示全部楼层
华大代理 qq:409946461   供样品提供技术支持

使用特权

评论回复
caizhiwei|  楼主 | 2020-6-11 15:30 | 显示全部楼层
sgrtf661 发表于 2020-6-11 14:07
华大代理 qq:409946461   供样品提供技术支持

各种代理,哈哈哈哈

使用特权

评论回复
781354052| | 2022-4-27 15:32 | 显示全部楼层
    stcFilter.u32CODE     = CAN_ID_BACKLIGHT;

    stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_BACKLIGHT);   

这样配置好像不是配置单个ID,

每组筛选器有一个 32 位 ID CODE
寄存器和一个 32 位 ID MASK 寄存器,ID CODE 寄存器用于比较接收到 CAN ID,而
HC32F072 系列用户手册 Rev1.62  Page 770 of 934
ID MASK 寄存器用于选择比较的 CAN ID 位。对应的 ID MASK 位为 1 时,不比较该
位的 ID CODE。

使用特权

评论回复
mollylawrence| | 2022-5-28 16:37 | 显示全部楼层
CAN 驱动中如何添加过滤器?

使用特权

评论回复
wwppd| | 2022-5-29 09:38 | 显示全部楼层
CAN 驱动可以添加过滤器?

使用特权

评论回复
sanxingnote7| | 2022-5-29 09:57 | 显示全部楼层
这个学习一下了。  

使用特权

评论回复
everyrobin| | 2022-5-29 10:24 | 显示全部楼层
做滤波算法吗?

使用特权

评论回复
wangdezhi| | 2022-5-29 10:58 | 显示全部楼层
是数字信号过滤器吗  

使用特权

评论回复
sparrow054| | 2022-6-5 14:36 | 显示全部楼层
什么是过滤器,作用是什么

使用特权

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

本版积分规则

96

主题

842

帖子

11

粉丝