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

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

[复制链接]
waiman-156411 提问时间: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. }
复制代码





<
收藏 2 评论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节点本身在没有辅助电路的情况下是无法区分这两种情况的。
回答时间: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-156411 回答时间: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-156411 回答时间: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问题
12下一页

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版