你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F107,CAN发送错误,导致CAN离线状态,如何恢复CAN总线?

[复制链接]
waiman 提问时间:2017-1-5 13:39 /
CAN规范里头提到,如果一个节点由于发送错误计数器的值不小于255时,它会进入bus off离线状态。
当它监听到总线上有128次连续11个“隐性”位后,允许处于bus off状态的节点转到“error active”状态。

但问题是,我的STM32F107是主机,负责发送CAN信号的,当由于信号线的问题(CANH和CANL短路),导致主机发送错误,离线了(CAN_ESR上的TEC>255),CAN上也就没有信号,那么从何而来《128次连续11个“隐性”位》进入恢复过程。

而且 CAN_MCR里的RESET置位,也不能复位CAN寄存器,CAN_ESR上错误次数还是存在。难道只能强行复位芯片才能解决?

下面是我的错误中断里的处理代码

  1. void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
  2. {
  3.         uint32_t err = hcan->ErrorCode;
  4.         uint8_t i=0;
  5.         uint8_t status=0;
  6.         Process_Status = 0;
  7.        
  8.         uint32_t canTSR = hcan->Instance->TSR;
  9.         uint32_t canABRQ = CAN_TSR_ABRQ0;        // 终止发送
  10.         uint32_t canTERR = CAN_TSR_TERR0;        // 发送失败
  11.         uint32_t canALST = CAN_TSR_ALST0;        // 仲裁失败
  12.        
  13.         switch(err){
  14.           case HAL_CAN_ERROR_EWG:        // EWG error   
  15.                 printf("CAN ERRROR = EWG\r\n");
  16.                 break;
  17.           case HAL_CAN_ERROR_EPV:        // EPV error
  18.                 printf("CAN ERRROR = EPV\r\n");
  19.                 break;
  20.           case HAL_CAN_ERROR_BOF:        // BOF error
  21.                 printf("CAN ERRROR = BOF\r\n");
  22.                 break;
  23.           case HAL_CAN_ERROR_STF:        // Stuff error
  24.                 printf("CAN ERRROR = Stuff\r\n");
  25.                 break;
  26.           case HAL_CAN_ERROR_FOR:        // Form error
  27.                 printf("CAN ERRROR = Form\r\n");
  28.                 break;
  29.           case HAL_CAN_ERROR_ACK:        // Acknowledgment error
  30.                 printf("CAN ERRROR = ACK\r\n");
  31.                 break;
  32.           case HAL_CAN_ERROR_BR:        // Bit recessive
  33.                 printf("CAN ERRROR = Bit recessive\r\n");
  34.                 break;
  35.           case HAL_CAN_ERROR_BD:        // LEC dominant
  36.                 printf("CAN ERRROR = LEC dominant\r\n");
  37.                 break;
  38.           case HAL_CAN_ERROR_CRC:        // LEC transfer error
  39.                 printf("CAN ERRROR = LEC transfer\r\n");
  40.                 break;
  41.           case HAL_CAN_ERROR_NONE:        // No error
  42.                 printf("CAN ERRROR = NO\r\n");
  43.                 break;
  44.                
  45.           default:
  46.                 break;
  47.         }
  48.        
  49.        
  50.        
  51.     hcan->ErrorCode = HAL_CAN_ERROR_NONE;
  52.     hcan->State = HAL_CAN_STATE_READY;
  53.        
  54.         hcan->Instance->IER = 0;        // 清除全部中断
  55.         hcan->Instance->ESR = 0;        // 清除错误计数
  56.        
  57.         // 清空发送邮箱       
  58.         for(i=0;i<3;i++){
  59.                 if((canTSR & canTERR) !=0){
  60.                         hcan->Instance->TSR |=canABRQ;
  61.                 }
  62.                 if((canTSR & canALST) !=0){
  63.                         hcan->Instance->TSR |=canABRQ;
  64.                 }
  65.                 canABRQ <<=8;
  66.                 canTERR <<=8;
  67.                 canALST <<=8;
  68.                
  69.         }
  70.         for(i=0;i<3;i++){
  71.                 hcan->Instance->sTxMailBox[i].TIR=0;
  72.                 hcan->Instance->sTxMailBox[i].TDTR=0;
  73.                 hcan->Instance->sTxMailBox[i].TDLR=0;
  74.                 hcan->Instance->sTxMailBox[i].TDHR=0;
  75.         }
  76.        

  77.         BSP_CAN_Reset(hcan);        // 复位CAN寄存器 CAN_MCR RESET置位
  78.         HAL_CAN_MspDeInit(hcan);// 注销CAN实例
  79.         status = BSP_CAN_Init(CAN_Baudrate);        //重新初始化CAN
  80. }
复制代码





收藏 3 评论17 发布时间:2017-1-5 13:39

举报

17个回答
任风吹吹 回答时间:2017-12-7 10:30:48
楼主你是想知道BUSOFF后如何恢复吗? 将ABOM设1后,一旦检测到条件会自动恢复的,不需要人工干预。

但楼主的问题显然不是这个,楼主主要是对这句话“当它监听到总线上有128次连续11个“隐性”位后,允许处于bus off状态的节点转到“error active”状态。”不怎么理解吧?

当CAN节点进入到BUS OFF状态后,只要使能了ABOM位,那么它还是持续检测总线是否存在128次连续11个隐性位,这个是CAN接口恢复到主动错误状态的条件,那么,关键的是,如何理解这个128次连续11个隐性位。

那么我要问的是,什么是隐性位?当CANH=CANL=2.3V时! 这里是约等于,我没找到这个符号,用等号代替。

当CANH和CANL短接时,CAN节点本身并不知道(如果没有其他外围辅助检测电路的话),从CAN节点来看,只是知道CANH=CANL=2.3V,对于CAN节点来说,这个就是IDLE状态。所以当持续一段时间后,BUS OFF状态会解除,自动恢复到主动错误状态,但是回到主动错误状态后,由于CANH与CANL还是短接(CAN BUS IDLE状态),此时若发送报文,则会导致发送错误,进而导致TEC累加,最终再次导致进入到BUSOFF状态。如此反复循环。

在此过程中,楼主如查看BUSOFF寄存器的状态,楼主会发现有时为0,有时为1,这就是返回循环导致的。

进入到BUSS OFF状态需要发送来驱动,但从BUS OFF状态恢复到主动错误状态并不需要任何操作来驱动,它就是自动检测128次连续11位隐性位这个条件来决定的。

这里关键的是,当CANH与CANL短接时,对于CAN节点来说,就是一直为IDLE,当CAN总线上没有任何消息时,也是IDLE,CAN节点本身在没有辅助电路的情况下是无法区分这两种情况的。
剑鱼 回答时间:2018-11-8 13:17:04
    hcan.Instance = CAN;
    hcan.Lock = HAL_UNLOCKED;
    hcan.pRxMsg = &CanRxMsgStruct;
    hcan.pRx1Msg = &CanRxMsg1Struct;
    hcan.pTxMsg = &CanTxMsgStruct;
    hcan.Init.Prescaler = 32;               
    hcan.Init.Mode = CAN_MODE_NORMAL;//CAN_MODE_LOOPBACK;
    hcan.Init.SJW = CAN_SJW_1TQ;
    hcan.Init.BS1 = CAN_BS1_3TQ;
    hcan.Init.BS2 = CAN_BS2_5TQ;
    hcan.Init.TTCM = DISABLE;               
    hcan.Init.ABOM = ENABLE;               
    hcan.Init.AWUM = ENABLE;       
    hcan.Init.NART = DISABLE;               
    hcan.Init.RFLM = DISABLE;               
    hcan.Init.TXFP = DISABLE;       

将以上红色项使能试试。       

废鱼 回答时间:2017-1-5 14:42:25
没有遇到类似问题,从手册看,以下是解决方法:
如果ABOM位为’1’,bxCAN进入离线状态后,就自动开启恢复过程。
如果ABOM位为’0’,软件必须先请求bxCAN进入然后再退出初始化模式,随后恢复过程才被开启。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

xmshao 回答时间:2017-1-5 14:54:31
你配置ABOM为1,可以自动恢复的。你不妨验证下。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

andypanfan 回答时间:2017-1-6 09:12:01
研究的比较的深,还没有考虑过!!!!
waiman 回答时间:2017-1-6 11:07:54
安 发表于 2017-1-5 14:42
没有遇到类似问题,从手册看,以下是解决方法:
如果ABOM位为’1’,bxCAN进入离线状态后,就自动开启恢复 ...

在初始化的时候已经置位了,但就是恢复不了,重新发can也发不出去。

手册里说的恢复过程是:需要CAN总线上有128次连续11个隐形位,相当于,用CAN总线上的数据把CAN_ESR里的TEC域递减清零。才能恢复完成。但我这个是主机,停止CAN发送的话,CAN总线上也没有数据存在。所以就清除不了错误。

难道是互联产品的从CAN就是用在恢复主CAN的?
当主CAN出现故障之后,从CAN用来发数据,清除主CAN的CAN_ESR计数?然后恢复现场?
废鱼 回答时间:2017-1-7 11:12:00
楼主把重发机制关闭了试试。
waiman 回答时间:2017-1-19 09:15:58
安 发表于 2017-1-7 11:12
楼主把重发机制关闭了试试。

没有开重发机制。

CAN总线默认的状态是隐性电平“1” (没有差分信号),那么CAN总线上如果没有数据在传输,那么128次连续11个隐性位,相当于总线闲置过一段时间之后,CAN会自己恢复?
jcx0324 回答时间:2017-1-19 12:24:49
可以设置自动重启

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

yzez 回答时间:2017-12-6 17:32:36
楼主问题解决了吗。。。
hjl2832 回答时间:2017-12-7 09:13:54
关注,标记,CAN问题
yzez 回答时间:2017-12-7 09:58:26
hjl2832 发表于 2017-12-7 09:13
关注,标记,CAN问题

在进入错误回调函数之前,把相关的中断都关掉了,需要重新打开
waiman 回答时间:2017-12-8 21:01:00
任风吹吹 发表于 2017-12-7 10:30
楼主你是想知道BUSOFF后如何恢复吗? 将ABOM设1后,一旦检测到条件会自动恢复的,不需要人工干预。

但楼主 ...

多谢您的详细回答。也就是说CAN主机也无法判定CAN线短路这种情况对吗?
任风吹吹 回答时间:2017-12-11 09:42:53
waiman-156411 发表于 2017-12-8 21:01
多谢您的详细回答。也就是说CAN主机也无法判定CAN线短路这种情况对吗?

CAN控制器是不知道的,但不排除有些CAN收发器可能知道,或者在加入外围辅助电路后,MCU有方法可以判别,这个就看怎么设计电路了。
北宸 回答时间:2018-4-22 15:22:45
本帖最后由 北宸 于 2018-4-22 15:26 编辑

我目前也碰到这个问题,就是在总线上,CAN_H和CAN_L在线上短路,二条边连接到一起了。
然后直接在初始化上,把ABOM位为’1’,bxCAN进入离线状态后,就自动开启恢复过程。我用的是STM32F103ZET6.
谢谢!!
12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版