[技术问答]

HC32F460 CAN通讯问题

[复制链接]
3400|18
手机看帖
扫描二维码
随时随地手机跟帖
luckyren|  楼主 | 2023-1-13 09:01 | 显示全部楼层 |阅读模式
本帖最后由 luckyren 于 2023-1-13 09:04 编辑

我在调试HC32F460的CAN通讯时发现如果同时收到了两帧数据,第二帧数据会保存下来,导致下面接收的数据是上一帧的数据,然后后面的接收都错位了,中断里也清标志位了,有人指导一下吗?我的初始化及中断接收处理如下:
static void CanInitConfig(uint16_t CAN_Baud_Rate)
{
    stc_can_init_config_t stcCanInitCfg;
    stc_can_filter_t astcFilters[CAN_FILTERS_COUNT] = \
    {
        {0x00000000ul, 0x111ul, 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(PortC, Pin06, Func_Can1_Rx, Disable);
    PORT_SetFunc(PortC, Pin07, Func_Can1_Tx, Disable);

    MEM_ZERO_STRUCT(stcCanInitCfg);
    //<< Can bit time config
    switch(CAN_Baud_Rate)
    {
        case 1000:      //1M
            stcCanInitCfg.stcCanBt.PRESC = 1u-1u;
            break;
        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;
    stcCanInitCfg.enCanSAck      = CanSelfAckDisable;
    stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;

    stcCanInitCfg.pstcFilter     = astcFilters;

    stcCanInitCfg.u8FilterCount  = CAN_FILTERS_COUNT;

    CAN_Init(&stcCanInitCfg);

    stc_irq_regi_conf_t     stcIrqRegiConf;

    stcIrqRegiConf.enIRQn = Int000_IRQn;
    stcIrqRegiConf.enIntSrc = INT_CAN_INT;
    stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack;
    enIrqRegistration(&stcIrqRegiConf);
    NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
}
static void CAN_RxIrqCallBack(void)
{
    if(true == CAN_Irq**Get(CanRxIrq**))
    {
        CAN_Irq**Clr(CanRxIrq**);
        CAN_IrqCmd(CanRxIrqEn, Disable);         
        CAN_Receive(&stcRxFrame);
//        rt_kprintf("stcRxFrame.Cst.Control_f.DLC = %d\r\n",stcRxFrame.Cst.Control_f.DLC);
//        rt_kprintf("stcRxFrame.Cst.Control_f.IDE = %d\r\n",stcRxFrame.Cst.Control_f.IDE);


        can_RX_flag = 1;
        
    }
    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**);
    }
    if(true == CAN_Irq**Get(CanRxOverIrq**))  
    {
        CAN_Irq**Clr(CanRxOverIrq**);
//        for (size_t i = 0; i < 10; i++)
//        {
//            CAN_Receive(&stcRxFrame);
//            rt_kprintf("stcRxFrame.Cst.Control_f.DLC = %d\r\n",stcRxFrame.Cst.Control_f.DLC);
//            rt_kprintf("stcRxFrame.Cst.Control_f.IDE = %d\r\n",stcRxFrame.Cst.Control_f.IDE);
//        }

    }
    if(true == CAN_Irq**Get(CanErrorIrq**))  
    {
        //gData.ResetCanF=1;
        CAN_Irq**Clr(CanErrorIrq**);      
    }   
    if(true == CAN_Irq**Get(CanErrorWarningIrq**))  
    {
        //gData.ResetCanF=1;
        CAN_Irq**Clr(CanErrorWarningIrq**);      
    }      
    if(true == CAN_Irq**Get(CanErrorPassivenodeIrq**))  
    {
        //gData.ResetCanF=1;
        CAN_Irq**Clr(CanErrorPassivenodeIrq**);      
    }
   
    if(true == CAN_Irq**Get(CanTxBufFullIrq**))  
    {
        CAN_Irq**Clr(CanTxBufFullIrq**);      
    }
     
    if(true == CAN_Irq**Get(CanRxBufFullIrq**))  
    {
        CAN_Irq**Clr(CanRxBufFullIrq**);
        //CAN_Receive(&stcRxFrame);

//        memset(rxCanBuff,0,sizeof(rxCanBuff));
//        memset(txCanBuff,0,sizeof(txCanBuff));
//        memset(&stcRxFrame,0,sizeof(stcRxFrame));
//        putCan_Data(txCanBuff,8,rxCanBuff[2]);
            
    }

    if(true == CAN_Irq**Get(CanRxBufAlmostFullIrq**))  
    {
        CAN_Irq**Clr(CanRxBufAlmostFullIrq**);      
    }
   
    if(true == CAN_Irq**Get(CanTxSecondaryIrq**))  
    {
        CAN_Irq**Clr(CanTxSecondaryIrq**);      
    }
   
    if(true == CAN_Irq**Get(CanAbortIrq**))  
    {
        CAN_Irq**Clr(CanAbortIrq**);      
    }

    if(true == CAN_Irq**Get(CanErrorPassiveIrq**))  
    {
        CAN_Irq**Clr(CanErrorPassiveIrq**);      
    }        
}


使用特权

评论回复
请叫我污春| | 2023-1-13 09:20 | 显示全部楼层
没明白什么意思,指的是一次接收两帧数据但是保存下来的只有第二帧吗

使用特权

评论回复
luckyren|  楼主 | 2023-1-13 09:35 | 显示全部楼层
不是,是同时给MCU发送了两条数据,按我这个配置stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;不应当是不保存数据,应当是只保存一条数据吧,但是在RX接收里保存了两条,我读出来一条,还有一条在里面,导致我下一次再发数据时是上一条的数据,于是我解析的是上一条的数据,新的数据又被保存下来了,然后就这么错位了。。。就是解析的数据和当前发送给MCU的不一致

使用特权

评论回复
luckyren|  楼主 | 2023-1-13 09:36 | 显示全部楼层
请叫我污春 发表于 2023-1-13 09:20
没明白什么意思,指的是一次接收两帧数据但是保存下来的只有第二帧吗

不是,是同时给MCU发送了两条数据,按我这个配置stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;不应当是不保存数据,应当是只保存一条数据吧,但是在RX接收里保存了两条,我读出来一条,还有一条在里面,导致我下一次再发数据时是上一条的数据,于是我解析的是上一条的数据,新的数据又被保存下来了,然后就这么错位了。。。就是解析的数据和当前发送给MCU的不一致

使用特权

评论回复
请叫我污春| | 2023-1-13 09:57 | 显示全部楼层
本帖最后由 请叫我污春 于 2023-1-13 10:11 编辑
luckyren 发表于 2023-1-13 09:36
不是,是同时给MCU发送了两条数据,按我这个配置stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;不应 ...

stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored这个定义意思是只有当接收缓存满了之后新接收的数据不会被存入,并不是说不存数据了,因为你每次接收两帧,肯定不会让接收缓存溢出,两帧还是被存进去了,如果你每次只读一帧肯定下次读里面还剩一帧,就出现你说得问题了,而且时间长了接收缓存满了,新数据就不会被存入了从而有丢失数据的风险

使用特权

评论回复
luckyren|  楼主 | 2023-1-13 10:13 | 显示全部楼层
请叫我污春 发表于 2023-1-13 09:57
stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored这个定义意思是只有当接收缓存满了之后新接收的数据不 ...

那如何清除接收缓存,保证我每次接收的都是最新的?我stcCanInitCfg.enCanRxBufMode = CanRxBufOverwritten;把这个设置成这样也不行

使用特权

评论回复
请叫我污春| | 2023-1-13 10:18 | 显示全部楼层
本帖最后由 请叫我污春 于 2023-1-13 10:22 编辑

看手册定义,stcCanInitCfg.enCanRxBufMode只是对溢出模式的选择,并不是对存不存数据的选择
截图_20230113101654.png

使用特权

评论回复
请叫我污春| | 2023-1-13 10:21 | 显示全部楼层
luckyren 发表于 2023-1-13 10:13
那如何清除接收缓存,保证我每次接收的都是最新的?我stcCanInitCfg.enCanRxBufMode = CanRxBufOverwritt ...

看手册怎么说的,释放掉就行 5549763c0bff34c918.png

使用特权

评论回复
请叫我污春| | 2023-1-13 10:23 | 显示全部楼层
多看看数据手册吧,里面都有

使用特权

评论回复
luckyren|  楼主 | 2023-1-13 10:23 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:18
看手册定义,stcCanInitCfg.enCanRxBufMode只是对溢出模式的选择,并不是对存不存数据的选择
...

好的,谢谢,再请教你一下,有没有哪个库函数可以把接收的缓存清掉呢?

使用特权

评论回复
luckyren|  楼主 | 2023-1-13 10:26 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:23
多看看数据手册吧,里面都有

好的,谢啦!

使用特权

评论回复
请叫我污春| | 2023-1-13 10:27 | 显示全部楼层
本帖最后由 请叫我污春 于 2023-1-13 10:29 编辑
luckyren 发表于 2023-1-13 10:23
好的,谢谢,再请教你一下,有没有哪个库函数可以把接收的缓存清掉呢? ...

不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读了,缓存自然就没了

使用特权

评论回复
luckyren|  楼主 | 2023-1-13 10:56 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:27
不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读 ...

多谢多谢,现在改好了

使用特权

评论回复
tpgf| | 2023-2-3 13:47 | 显示全部楼层
你这个前后两帧数据 有发送间隔吗

使用特权

评论回复
nawu| | 2023-2-3 14:28 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:21
看手册怎么说的,释放掉就行

这个释放缓存 需要我们人为的释放吗

使用特权

评论回复
aoyi| | 2023-2-3 14:36 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:27
不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读 ...

也就是说只要缓存中的数据被读取了  自然就会清除这个标志位了是吗

使用特权

评论回复
zljiu| | 2023-2-3 14:58 | 显示全部楼层
归根结底还是缓存数据处理不得当造成的

使用特权

评论回复
gwsan| | 2023-2-3 15:11 | 显示全部楼层
楼主读取数据的速度太慢了  缓存要爆掉了

使用特权

评论回复
tfqi| | 2023-2-3 15:29 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:27
不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读 ...

是不是缓存里边的数据读取之后缓存里边就没有数据呢

使用特权

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

本版积分规则