CAN收发器故障检测电路及算法

描述

本应用笔记讨论了MAX33011E的控制局域网(CAN)总线故障检测特性,并通过示例代码演示了如何在固件中实现故障检测算法。

介绍

在数据未传输或接收时对控制区域网络 (CAN) 进行故障排除可能会令人沮丧。Maxim在CAN收发器中开发了内置故障检测机制,可帮助用户快速确定根本原因。本应用笔记介绍了故障检测机制的功能,解释了其工作原理,并通过示例代码演示了如何在固件中实现故障检测算法。

使能故障检测电路

MAX33011E CAN收发器需要100 TXD上升沿(通常为几个CAN协议消息)来启用故障检测电路。故障检测电路使能后,收发器仍可正常传输消息。

读取和清除故障代码

当检测到故障情况时,发射器将被禁用,FAULT引脚将通过外部上拉电阻器拉高。当系统控制器接收到FAULT引脚信号时,TXD上需要16次从低到高的转换来移出故障代码,如表1所示。另外 10 个从低到高的 TXD 转换可清除故障并禁用故障检测电路。例如,过流故障代码为101010,其时序图如图1所示。

CAN收发器

图1.过流故障报告时序图

故障条件

MAX33011E是首款内置故障检测电路的CAN收发器。当故障检测电路使能时,它可以检测CAN总线上的三种常见故障条件(过压、过流和传输故障),如表1所示。

 

故障 条件(启用故障检测) 故障代码 可能的原因
过电流 CANH 输出电流和 CANL 输入电流均> 85mA 101010 CANH 缩短为 CANL
CANH 连接到 GND 和 CANL 连接到 VDD
电压 CANH > +29V 或 CANL < -29V 101100 CMR 故障
传输故障 RXD 在 10 个连续 TXD 脉冲内保持不变,建议最低频率 = 200kHz 110010 CANH 和 CANL 上的开路负载(两个终端电阻器均缺失)
超出驱动器的共模范围
连接到固定电压源的 CANH 和/或 CANL

 

过流故障

当CANH的源电流和CANL的灌电流均高于85mA(典型值)时,检测到过流故障。故障的更可能原因是总线上的CANH和CANL短路。但是,如果短路远离CAN节点,则由于电缆阻抗高,可能无法检测到。减慢CAN信号频率可以降低电缆阻抗,并有助于从更远的距离检测短路。但是,如果电缆的总电阻变得明显高,即使CAN信号始终处于主导模式,也无法检测到短路。图2显示了过流检测的最大工作频率与作为参考的电缆长度的关系。使用 Cat5E 铜包铝电缆。最大频率因电缆类型而异。

CAN收发器

图2.过流检测的最大工作频率与电缆长度的关系

过压故障

MAX33011E共模输入范围(CMR)为±25V。当CANH高于29V或CANH低于-29V时,检测到过压故障。这是由于 CMR 超出规范造成的。

传输故障故障

故障检测电路使能后,收发器仍可传输消息。在正常工作条件下,RXD 会回显 TXD 信号。如果RXD连续10个脉冲没有回显TXD信号,则检测电路会产生传输故障。有几个常见的可能原因使 RXD 无法回显 TXD:

如果CANH和CANL短路至电源,并且收发器无法过驱电源,则接收器将始终在CAN总线上看到固定信号。

当共模电压超过驱动器的共模范围(-5V至+10V)时,驱动器关断。当驱动器关闭时,CANH/CANL输出不会在TXD上反射信号,接收器将在CAN总线上看到固定信号。

如果终端电阻未连接到CAN节点,则可能导致传输故障。终端电阻在隐性模式下使CANH和CANL达到相同的电压电平方面起着非常重要的作用。如果没有端接电阻,收发器的内部共模电压缓冲器仍然可以将CANH和CANL连接在一起,但速度要慢得多。总线上的容性负载也会减慢CANH和CANL电压的合并速度。当控制器向TXD发送脉冲时,如果隐性间隔不够长,差分电压(CANH – CANL)连续10个脉冲周期低于输入低阈值(RXD在10个TXD脉冲中保持低电平),则将报告传输故障故障。这也意味着如果TXD高电平时间过长,CAN总线信号可能进入隐性模式,RXD将变为高电平,不会报告传输故障故障。检测传输故障故障的推荐最小TXD脉冲频率为200kHz。

故障检测算法

Maxim开发了一种算法,能够利用MAX33011E可靠地检测CAN总线上的故障条件,而不会中断正常的CAN通信。以下所有示例 Mbed 代码都是为 NUCLEO-F303K8 平台开发的。®

通常,CAN网络的每个节点都使用带有CAN外设的微控制器。要执行故障检测,微控制器的 TXD 和 RXD 引脚必须配置为 GPIO,以对 TXD 信号进行位冲击并从 RXD 读取故障代码。需要中断引脚连接到MAX33011E的故障信号。

为避免中断正常通信,该算法在进入故障检测模式前需要对通信故障进行强指示。如果发生以下情况之一,算法将进入故障检测模式:

故障很高。

发射器生成误码帧。

发射器错误计数器升至255以上,节点进入总线关闭状态。

以下示例代码在上述任何条件变为 GP 时将微控制器引脚配置为 GPIO。

我们使用STM32F303K8 MCU作为CAN控制器。此参考代码是在 Mbed-OS 上开发的,Mbed-OS 是一个免费的开源嵌入式操作系统。有关更多详细信息,请访问:https://os.mbed.com/mbed-os/

Mbed 提供 API 将微控制器的 IO 配置为数字输入/输出引脚。也可以使用任何其他类似的低级 API。

 

DigitalOut txd (PA_12); // Configures PA_12 of MCU (TXD of CAN controller) as digital o/p pin   
DigitalIn rxd (PA_11); // Configures PA_11 of MCU (RXD of CAN controller) as digital i/p pin   

在故障检测模式下,应使用2μs TXD正脉冲。在正脉冲之后,只要需要处理算法,TXD 就可以保持低电平。这使得故障检测电路能够可靠地检测过流和传输故障故障。为确保TXD脉冲宽度准确,应使用定时器。下面是设置计时器的示例代码。

首选低级 API 来配置分辨率为 2μs 的定时器。Mbed 定时器提供最低 8μs 分辨率。在本例中,使用了STM2F32K303控制器中的TIM8定时器。有关寄存器设置说明的更多详细信息,请参阅STM32F303K8编程手册。

 

static TIM_HandleTypeDef s_TimerInstance = {                                  //Creates a timer instance (TIM2)
    . Instance = TIM2
};
__HAL_RCC_TIM2_CLK_ENABLE ();                                                 //Enable TIM2 APB clock (72MHz)
s_TimerInstance.Init.Period.Prescalar = 16;                                        //Set the counter prescalar value
s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;     // Set the counter in "UP" mode
s_TimerInstance.Init.Period = 500;                                                      //Set the counter period
s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;  // Set the clock divisor value to none
s_TimerInstance.Init.RepetitionCounter = 0;                                       //Disable the auto-reload 
HAL_TIM_Base_Init(&s_TimerInstance);                        // Initializes TIM base unit according to specified parameters
HAL_TIM_Base_Start(&s_TimerInstance);                                         //Start the timer in time-base mode

如果故障变为高电平,则在CAN报文传输中,它随时可能变为高电平。这意味着消息最有可能在 FAULT 为高电平后结束,因此从下一个故障检测周期读取错误代码更可靠。故障变为高电平后,CAN外设引脚配置为GPIO。故障检测算法将重复产生2μs TXD正脉冲,直到FAULT引脚上升沿后RXD变为高电平。建议在TXD的下降沿之后对RXD进行采样。RXD变为高电平后,还需要五个TXD脉冲来移出故障代码。另外<>个TXD脉冲用于禁用故障检测。下面是 FAULT 变高时的算法示例代码:

 

InterruptIn fault (PA_0);                                 //Configure Fault pin as interrupt pin
fault.rise(&fault_init);                                            // Attach an interrupt callback function when fault pin goes high 
int state=0;                                                          // This is the state of state machine for fault detection
void fault_init()
{
     fault.rise (NULL);                                                  //Detach an interrupt till state machine gets completed
     toggle_txd_i_ticker.attach_us(&toggle_txd_i,6); // Initiate a state machine to detect a fault, each cycle is 6us
}
void toggle_txd_i()
{
      DigitalOut txd(PA_12);                                    //Configure CAN TXD pin as digital o/p
      DigitalIn rxd(PA_11);                                    // Configure CAN RXD pin as digital i/p
      DigitalIn fault_pin(PA_0);                            //Configure fault pin as digital i/p
      int status = fault_pin.read();                    //Fault pin status is stored in status variable
      static int count,N;
     

       do {                                                                  //This code toggles TXD for 2us duration using TIM2 timer
               txd = 1;
            } while (__HAL_TIM_GET_COUNTER(&s_TimerInstance) < 9);
                txd=0;
              count++;
 switch (state ){                                                   //State machine for fault detection
           case 0:     // Ignore the first high fault, giving txd pulses to clear the fault without reading fault code
             if (count >= 26 && status == 0 ) {                
                count = 0;
                state = 1;
                }                
              break;
                
           case 1:      // Fault pin is low and giving 100 fault pulses/waiting for fault pin to go High for second time
            if (count>=100 && status == 1 ) {                
                count = 0;
                state = 2;
             } 
                break;
                
            case 2:         // Second time fault activated, need to read the fault code(10 pulses + 6 pulses to read the rxd + 
                                  +10 pulses to clear the fault
               if (status == 1){        
                    if( (rxd.read() == 1 || rxd_read == 1) && i<6) {   
                        arr[k] = rxd.read();                      //Read RXD (fault code bit) and store in array
                        k++;
                        rxd_read = 1;                          //Flag to indicate that fault has been read
                     i++;   
                    }
                    }       
            else if ( status == 0  ) {    // Once fault pin becomes 0, move to state 3              
                fault_read = 1;
                rxd_read = 1;
                count = 0;
                state = 3;    
               } 
               break;
             case 3:
             if (status == 0) {
               InterruptIn fault (PA_0);          //Configure fault pin as interrupt pin
                Fault.rise(&fautl_init);             //Enable fault interrupt
                toggle_txd_i_ticker.detach();  //Disable state machine 
              }
               break;
            }                     
}    
    

对于其他两种情况(误码帧和发射器错误计数>255),FAULT不一定会变高。该算法将CAN外设引脚配置为GPIO,并将重复产生2μs TXD正脉冲,直到RXD在故障上升沿后变为高电平。建议在TXD的下降沿之后对RXD进行采样。RXD变为高电平后,还需要五个TXD脉冲来移出故障代码。另外 110 个 TXD 脉冲禁用故障检测。如果 FAULT 在 <> TXD 脉冲后没有变为高电平,则表示未检测到故障,故障检测模式将退出。下面是该算法的示例代码:

在STM32F303K8 CAN控制器中,ESR(错误状态寄存器)具有7:0的发送器错误计数器[TEC]位。如果此计数器超过 255,则启动用于检测故障的状态机。此外,ESR 具有 2 位 LEC[2:0](最后一个错误代码)来指示错误条件,例如误码帧。

 

Int tec_count= ((CAN1->ESR) && (0x00FF0000))>>16;          //Get the transmit error counter value from ESR register
Int error_code= ((CAN1->ESR) && (0X00000070)>>4;         //Get the error code value from ESR register
if((tec_count >255) || (error_code !=0 ))
       {
            fault_init();                                              //Run the fault detection algorithm as implemented in above section
       }

审核编辑:郭婷

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分