[技术问答] 【分享】HC32F072 CAN 驱动中如何添加过滤器

[复制链接]
3441|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的。
  1. #include "bsp_can.h"
  2. #include "bsp_led.h"
  3. #include "bsp_timer.h"

  4. stc_can_rxframe_t   stcRxFrame;
  5. stc_can_txframe_t   TxFrame_Gain;
  6. stc_can_txframe_t   TxFrame_Keepalive;

  7. stc_can_t APP_CAN;

  8. en_ACC_Status ACC_Status = Off;

  9. extern void PWM_duty_adjust(uint16_t adc_value, uint16_t MAX_Value);

  10. static void Can_Gpio_Init(void)
  11. {
  12.     stc_gpio_cfg_t stcGpioCfg;

  13.     Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

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

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

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

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


  35. #ifdef CAN_CHIP_TJA1043

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

  47.     Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

  48.     ///< 端口方向配置->输出
  49.     stcGpioCfg.enDir = GpioDirOut;
  50.     ///< 端口驱动能力配置->高驱动能力
  51.     stcGpioCfg.enDrv = GpioDrvH;
  52.     ///< 端口上下拉配置->无
  53.     stcGpioCfg.enPu = GpioPuDisable;
  54.     stcGpioCfg.enPd = GpioPdDisable;
  55.     ///< 端口开漏输出配置->开漏输出关闭
  56.     stcGpioCfg.enOD = GpioOdDisable;
  57.     ///< 端口输入/输出值寄存器总线控制模式配置->AHB
  58.     stcGpioCfg.enCtrlMode = GpioAHB;
  59.         
  60.     Gpio_Init(GpioPortA, GpioPin3, &stcGpioCfg); // STB_N
  61.     Gpio_Init(GpioPortB, GpioPin3, &stcGpioCfg); //IO_INH  
  62.     Gpio_Init(GpioPortB, GpioPin7, &stcGpioCfg); // IO_EN
  63.         
  64.         Gpio_ClrIO(GpioPortB, GpioPin3);  /* PB3 IO_INH*/
  65.         delay1ms(10);
  66.     Gpio_SetIO(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN);
  67.         Gpio_SetIO(GpioPortB, GpioPin7);// IO_EN
  68.         
  69. }


  70. void TJA1043_Goto_Sleep(void)
  71. {
  72.         Gpio_ClrIO(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN);
  73.         Gpio_SetIO(GpioPortB, GpioPin7);// IO_EN
  74. }

  75. #endif

  76. void BSP_Can_Init(void)
  77. {
  78.     stc_can_init_config_t   stcCanInitCfg;
  79.     stc_can_filter_t        stcFilter;

  80.         Can_Gpio_Init();

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

  88. #ifdef CAN_CONFIG_48MHZ_500K         
  89.         
  90.         stcCanInitCfg.stcCanBt.PRESC = 6-1;
  91.         stcCanInitCfg.stcCanBt.SEG_1 = 9-2;
  92.         stcCanInitCfg.stcCanBt.SEG_2 = 7-1;        
  93.         stcCanInitCfg.stcCanBt.SJW   = 3-1;        
  94.         
  95. //        stcCanInitCfg.stcCanBt.PRESC = 8-1;
  96. //  stcCanInitCfg.stcCanBt.SEG_1 = 7-2;
  97. //  stcCanInitCfg.stcCanBt.SEG_2 = 5-1;
  98. //  stcCanInitCfg.stcCanBt.SJW   = 5-1;
  99.         
  100. #endif

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

  103.     stcCanInitCfg.enCanRxBufAll  = CanRxNormal;
  104.     stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
  105.     stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;

  106.     CAN_Init(&stcCanInitCfg);

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

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

  114.         stcFilter.enFilterSel = CanFilterSel2;
  115.     stcFilter.u32CODE     = CAN_ID_ACC;
  116.     stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_ACC);
  117.         CAN_FilterConfig(&stcFilter, TRUE);
  118.         
  119.         stcFilter.enFilterSel = CanFilterSel3;
  120.     stcFilter.u32CODE     = CAN_ID_BRAKE_X;
  121.     stcFilter.u32MASK     = 0x1FFFFFFF& (~CAN_ID_BRAKE_X);
  122.     CAN_FilterConfig(&stcFilter, TRUE);

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

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


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

  148. void Can_IRQHandler(void)
  149. {
  150.     if(TRUE == CAN_Irq**Get(CanBusErrorIrq**))  /*当总线短路时,进入此中断*/
  151.         {         
  152.                 CAN_Irq**Clr(CanBusErrorIrq**);         
  153.                 APP_CAN.BusErrorFlag = TRUE;
  154.                 // M0P_CAN->CFG_STAT = 0x00; /* 清除由硬件置位的Reset 标志位,必须在中断外部执行*/                 
  155.         }         
  156.         if(TRUE == CAN_Irq**Get(CanRxIrq**))
  157.     {
  158.         CAN_Irq**Clr(CanRxIrq**);
  159.         CAN_Receive(&stcRxFrame);
  160.                 APP_CAN.RxFlag = TRUE;
  161.                 APP_CAN.Rx_cnt = 0;
  162.                 /*总线上发送周期约500ms*/
  163.                 if( CAN_ID_BACKLIGHT == stcRxFrame.StdID )
  164.                 {
  165.                         if(stcRxFrame.Data[0] & 0x04)
  166.                         {
  167.                                 LED_ON;
  168.                         }        
  169.                         else
  170.                         {
  171.                                 LED_OFF;
  172.                         }
  173.                 }
  174.                 /*
  175.                 XX 00 00 20 52 FF FB 00
  176.                 XX:02 (ON)  00(OFF)
  177.                 */        
  178.                 if (CAN_ID_ACC == stcRxFrame.StdID)
  179.                 {
  180.                         if(stcRxFrame.Data[0]&0x02)
  181.                         {
  182.                                 ACC_Status = On;
  183.                         }
  184.                         else
  185.                         {                        
  186.                                 ACC_Status = Off;  /* ACC off 后延时30s进入休眠*/                        
  187.                         }
  188.                 }

  189.                 if (CAN_ID_BRAKE_X == stcRxFrame.StdID)
  190.                 {
  191.                         APP_CAN.brake_value = (stcRxFrame.Data[0]<<8) + stcRxFrame.Data[1];        
  192.                         APP_CAN.RxFlag_Break = TRUE;
  193.                         
  194.                 }

  195.                 if (CAN_ID_BRAKE_SIGNAL == stcRxFrame.StdID)
  196.                 {               
  197.                         if( stcRxFrame.Data[2]&0x80)
  198.                         {
  199.                                 APP_CAN.brake_signal = TRUE;
  200.                         }
  201.                         else
  202.                         {                        
  203.                                 APP_CAN.brake_signal = FALSE;
  204.                         }
  205.                 }               
  206.     }
  207. }

  208. void CAN_BUS_Process(void)
  209. {
  210.         //if(ACC_Status == On) // AccOff 状态也需要发送数据
  211.         {
  212.                  if(APP_CAN.CANSendFlag) /*100ms*/
  213.                  {
  214.                         APP_CAN.CANSendFlag = FALSE;
  215.                         CAN_send_Frame(&TxFrame_Gain, 8);
  216.                  }
  217.                 if(APP_CAN.CAN_keepalive_SendFlag) /*心跳包数据,1s发送一次*/
  218.                  {
  219.                         APP_CAN.CAN_keepalive_SendFlag = FALSE;        
  220.                         CAN_send_Frame(&TxFrame_Keepalive, 8);
  221.                  }
  222.         }        
  223.         if(APP_CAN.BusErrorFlag)
  224.         {
  225.                 APP_CAN.BusErrorFlag = FALSE;
  226.                 M0P_CAN->CFG_STAT = 0x00;
  227.         }
  228. }
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 | 显示全部楼层
什么是过滤器,作用是什么
您需要登录后才可以回帖 登录 | 注册

本版积分规则

100

主题

856

帖子

16

粉丝
快速回复 在线客服 返回列表 返回顶部