大家好!非常感谢使用华大MCU,在调试HC32F460遇到的问题作一些笔记和个人理解,希望能帮助大家!谢谢。
近来在配合客户做BMS管理,需要使用到CAN功能,CAN功能比较频繁的收发多包数据,大概1秒收发15包数据。
1、客户遇到的问题,在进行CAN收发过程,发现数据只能发送或者接收。
2、压力测试情况下直接造成数据阻塞,CAN无法工作。
3、在进行超过8Bit数据情况下,进行分包发送或者接收也会出现频繁出现数据阻塞。
A、按照客户遇到以上问题进行CAN分析。使用CAN总线分析仪进行压力测试。并且复现以上问题。
B、首先我们看华大官方例程can_rx_tx_irq,其实直接使用官方例程即可,波特率修改如下,用户手册有计算波特率说明
static void CanInitConfig(uint16_t CAN_Baud_Rate)
{
stc_can_init_config_t stcCanInitCfg;
stc_can_filter_t astcFilters[CAN_FILTERS_COUNT] = \
{
{0x00000000ul, 0x1FFFFFFFul, CanFilterSel1, CanAllFrames}
};
//<< Enable can peripheral clock and buffer(ram)
PWC_RamOpMdConfig(HighSpeedMd);
PWC_RamPwrdownCmd(PWC_RAMPWRDOWN_CAN, Enable);
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable);
//<< CAN GPIO config
PORT_SetFunc(PortB, Pin06, Func_Can1_Rx, Disable);
PORT_SetFunc(PortB, Pin07, Func_Can1_Tx, Disable);
PORT_ResetBits(PortD, Pin15);
PORT_OE(PortD, Pin15, Enable);
PORT_SetBits(PortB, Pin13);
PORT_OE(PortB, Pin13, Enable);
MEM_ZERO_STRUCT(stcCanInitCfg);
//<< Can bit time config
// stcCanInitCfg.stcCanBt.PRESC = 4u-1u;//波特率,主要修改这个地方即可
switch(CAN_Baud_Rate)
{
case 500://500K
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
break;
case 250://250K
stcCanInitCfg.stcCanBt.PRESC = 4u-1u;
break;
case 125://125K
stcCanInitCfg.stcCanBt.PRESC = 8u-1u;
break;
case 100://100K
stcCanInitCfg.stcCanBt.PRESC = 10u-1u;
break;
default:
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
break;
}
stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u;
stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u;
stcCanInitCfg.stcCanBt.SJW = 3u-1u;
stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;
stcCanInitCfg.enCanRxBufAll = CanRxNormal;
stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;//新CAN消息 不做存储
stcCanInitCfg.enCanSAck = CanSelfAckDisable;//CanSelfAckEnable;// 有应答响应
stcCanInitCfg.enCanSTBMode = CanSTBFifoMode;//
stcCanInitCfg.pstcFilter = astcFilters;
stcCanInitCfg.u8FilterCount = CAN_FILTERS_COUNT;
CAN_Init(&stcCanInitCfg);
}
C、按照以上配置,直接使用官方开发板进行数据收发是没有问题的。但问题不是出在CAN配置上面。
D、咱们再看看CAN中断节点枚举,这些是CAN中断标记位枚举节点,引起节点中断有很多原因,比如收发数据中断,错误帧、超时、干扰中断等等。
并不是说只打开某个中断节点,MCU就只会产生某个中断,因为的中断寄存器是硬件置位,需要软件进行清零。所有需要在中断回调里面进行中断枚举清零。
我是全部中断节点都在回调函数里面进行标记位清零。经过测试没有发现上面提到的问题。
typedef enum
{
//<<Can Tx or Tx Irq **
CanTxBufFullIrq** = 0x00000001, ///<
CanRxIrq** = 0x00008000, ///< Receive interrupt flag
CanRxOverIrq** = 0x00004000, ///< RB overrun interrupt flag
CanRxBufFullIrq** = 0x00002000, ///< RB full interrupt flag
CanRxBufAlmostFullIrq** = 0x00001000, ///< RB almost full interrupt flag
CanTxPrimaryIrq** = 0x00000800, ///< Transmission primary interrupt flag
CanTxSecondaryIrq** = 0x00000400, ///< Transmission secondary interrupt flag
CanErrorIrq** = 0x00000200, ///< Error interrupt flag
CanAbortIrq** = 0x00000100, ///< Abort interrupt flag
//<< Can Error Irq **
CanErrorWarningIrq** = 0x00800000, ///< Error warning limit reached flag
CanErrorPassivenodeIrq** = 0x00400000, ///< Error passive mode active flag
CanErrorPassiveIrq** = 0x00100000, ///< Error passive interrupt flag
CanArbiLostIrq** = 0x00040000, ///< Arbitration lost interrupt flag
CanBusErrorIrq** = 0x00010000, ///< Bus error interrupt flag
}en_can_irq_flag_type_t;
static void CAN_RxIrqCallBack(void)
{
if(true == CAN_Irq**Get(CanRxIrq**))
{
CAN_Irq**Clr(CanRxIrq**);
CAN_IrqCmd(CanRxIrqEn, Disable);
CAN_Receive(&stcRxFrame);
u8RxFlag = true;
}
if(true == CAN_Irq**Get(CanTxPrimaryIrq**))
{
CAN_Irq**Clr(CanTxPrimaryIrq**);
CAN_IrqCmd(CanRxIrqEn, Enable);
}
//总线忙碌中断
if(true == CAN_Irq**Get(CanBusErrorIrq**))
{
CAN_Irq**Clr(CanBusErrorIrq**);
}
//仲裁失败中断
if(true == CAN_Irq**Get(CanArbiLostIrq**))
{
CAN_Irq**Clr(CanArbiLostIrq**);
}
}
实则是需要及时清除CAN产生的错误节点,需要及时清理标记位。
E、经过进行全部节点进行清除,压力测试CAN数据收发,没有复现以上问题。
如有其他问题,请联系:131 6807 9092(微信同号) 华大代理商 喻生
|