STM32 CAN总线故障检测功能的使用

STM32 中的CAN总线模块是具有故障监测功能的

就是CANx_SCE_IRQHandler

这个用的很少,它叫CAN总线状态改变中断 

 通过打开这个中断,配合代码可以精确的监测CAN总线的故障情况

STM32 CAN总线故障检测功能的使用_第1张图片

就是监测对应CAN的ESR寄存器

可以使用轮询或者中断的方式

中断的方式,以CAN1为例

调用HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn),调好优先级,在CAN1_SCE_IRQHandler里面编好功能就可以

只要CAN总线发送状态改变,就会触发中断

可以非常灵敏的检测CAN总线断线,短路等等故障

 

查询比较好些,这样不会频繁进中断

简单设计了一个故障监测计数的功能,1ms刷新一次CAN_Error_Process函数,计数超了就置位标志,可以提供到应用层作为收发函数的调用判断前提,并且把收发FIFO的故障检测一并做了进来,方便监测。

//CAN总线故障
#define CAN_FUNC_ERR            0x55
//CAN总线正常
#define CAN_FUNC_OK             0xaa

#define CANx_ERRx_MAX_TIME 1500//所有CAN的错误超过500ms就要告警了

//CPU中对CAN总线故障的细分
typedef enum {
    CANx_ERR_NONE,//无故障
    CANx_ERR_FILLIN,//填充错误
    CANx_ERR_FORMAT,//格式错误
    CANx_ERR_ACK,//应答错误
    CANx_ERR_BIT_0,//位隐性错误
    CANx_ERR_BIT_1,//位显性错误
    CANx_ERR_CRC,//CRC错误
    CANx_ERR_DEFAULT//软件默认错误
} EM_CANx_ERR_CODE;

typedef struct {
    uint16_t Its_LEC[7]; // CAN各种错误状态次数:位填充,格式,确认,隐性,显性,CRC
    uint16_t Its_BOF; // CAN离线错误次数
    uint16_t Its_EPV;// CAN错误被动次数
    uint16_t Its_EWG;// CAN错误警告标志次数
    uint16_t Its_TX_MAILBOX_TX_ERR[3];//3个发送邮箱发送错误计数
    uint16_t Its_TX_MAILBOX_ARB_ERR[3];//3个发送邮箱仲裁计数
    uint16_t Its_RX_FIFOx_OVR[2];//2个接收FIFO上溢出
    uint16_t Its_RX_FIFOx_FULL[2];//2个接收FIFO满

    uint8_t Its_RX_ERR_FLAG;//CAN接收标志位
    uint8_t Its_TX_ERR_FLAG;//CAN发送标志位
} ST_CAN_ERROR;

// 3个CAN故障检测变量定义
ST_CAN_ERROR g_Canx_Error_System[3];

//初始化任意一个CAN总线的故障监测功能
static void CAN_Error_System_Init(uint8_t CANx,CAN_HandleTypeDef* hcan)
{
    memset(&g_Canx_Error_System[CANx], 0, sizeof(ST_CAN_ERROR));
    g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_OK;
    g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_OK;
    hcan->Instance->ESR |= CAN_ESR_LEC; //将上次错误号设置为用户状态(程序不会设置该状态)以区分新的状态
}

//查询指定CAN总线的故障状态并记录
static void CAN_Error_Process(uint8_t CANx,CAN_HandleTypeDef* hcan)
{

//  uint16_t TEC_VAL = ((hcan->Instance->ESR&CAN_ESR_TEC)>>CAN_ESR_TEC_Pos);
//  uint16_t REC_VAL = ((hcan->Instance->ESR&CAN_ESR_REC)>>CAN_ESR_REC_Pos);
    g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_OK;
    g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_OK;

    if (hcan->Instance->ESR) //有故障
    {
        //上一次错误处理
        if ((hcan->Instance->ESR & CAN_ESR_LEC_Msk) != CAN_ESR_LEC) //故障不等于上一次默认故障
        {

            switch (((hcan->Instance->ESR & CAN_ESR_LEC_Msk) >> CAN_ESR_LEC_Pos))
            {
                case CANx_ERR_NONE:
                {
                    // 没有故障的时候,清0所有计数器
                    g_Canx_Error_System[CANx].Its_LEC[CANx_ERR_FILLIN] = 0;
                    g_Canx_Error_System[CANx].Its_LEC[CANx_ERR_FORMAT] = 0;
                    g_Canx_Error_System[CANx].Its_LEC[CANx_ERR_ACK] = 0;
                    g_Canx_Error_System[CANx].Its_LEC[CANx_ERR_BIT_0] = 0;
                    g_Canx_Error_System[CANx].Its_LEC[CANx_ERR_BIT_1] = 0;
                    g_Canx_Error_System[CANx].Its_LEC[CANx_ERR_CRC] = 0;
                    break;
                }

                case CANx_ERR_DEFAULT:
                {
                    break;
                }
                case CANx_ERR_FILLIN:
                case CANx_ERR_FORMAT:
                case CANx_ERR_ACK:
                case CANx_ERR_BIT_0:
                case CANx_ERR_BIT_1:
                case CANx_ERR_CRC:
                {
                    if (g_Canx_Error_System[CANx].Its_LEC[((hcan->Instance->ESR & CAN_ESR_LEC_Msk) >> CAN_ESR_LEC_Pos)] < CANx_ERRx_MAX_TIME)
                    {
                        // 对应故障计数++
                        g_Canx_Error_System[CANx].Its_LEC[((hcan->Instance->ESR & CAN_ESR_LEC_Msk) >> CAN_ESR_LEC_Pos)]++;
                    }
                    else
                    {
                        //拒绝发送&接收
                        g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
                        g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
                    }

                    break;
                }
                default:
                {
                    break;
                }
            }
            hcan->Instance->ESR |= CAN_ESR_LEC; //将上次错误号设置为用户状态(程序不会设置该状态)以区分新的状态
        }
    }

    //存在离线错误
    if (hcan->Instance->ESR & CAN_ESR_BOFF)
    {
        if (g_Canx_Error_System[CANx].Its_BOF < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_BOF++;
        }
        else
        {
            //告警
            //拒绝发送&接收
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_BOF = 0;
    }

    //存在被动错误
    if (hcan->Instance->ESR & CAN_ESR_EPVF)
    {
        if (g_Canx_Error_System[CANx].Its_EPV < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_EPV++;
        }
        else
        {
            //告警
            //拒绝发送&接收
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_EPV = 0;
    }

    //存在错误警告[小于95就不告警了]
    if (hcan->Instance->ESR & CAN_ESR_EWGF)
    {
        if (g_Canx_Error_System[CANx].Its_EWG < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_EWG++;
        }
        else
        {
            //告警
            //拒绝发送&接收
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_EWG = 0;
    }

    ///检测发送邮箱错误
    if ((hcan->Instance->TSR & CAN_TSR_TERR0) >> CAN_TSR_TERR0_Pos)// 发送邮箱0
    {
        if (g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[0] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[0]++;
        }
        else
        {
            //告警
            //拒绝发送
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[0] = 0;
    }

    if ((hcan->Instance->TSR & CAN_TSR_TERR1) >> CAN_TSR_TERR1_Pos)// 发送邮箱1
    {
        if (g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[1] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[1]++;
        }
        else
        {
            //告警
            //拒绝发送
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[1] = 0;
    }

    if ((hcan->Instance->TSR & CAN_TSR_TERR2) >> CAN_TSR_TERR2_Pos)// 发送邮箱2
    {
        if (g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[2] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[2]++;
        }
        else
        {
            //告警
            //拒绝发送
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_TX_MAILBOX_TX_ERR[2] = 0;
    }
    /

    ///检测发送邮箱仲裁错误
    if ((hcan->Instance->TSR & CAN_TSR_ALST0) >> CAN_TSR_ALST0_Pos)// 发送邮箱0
    {
        if (g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[0] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[0]++;
        }
        else
        {
            //告警
            //拒绝发送
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
        }
    }
    else
    {
        g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[0] = 0;
    }

    if ((hcan->Instance->TSR & CAN_TSR_ALST1) >> CAN_TSR_ALST1_Pos)// 发送邮箱1
    {
        if (g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[1] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[1]++;
        }
        else
        {
            //告警
            //拒绝发送
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
        }
    }
    else
    {
        g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[1] = 0;
    }

    if ((hcan->Instance->TSR & CAN_TSR_ALST2) >> CAN_TSR_ALST2_Pos)// 发送邮箱2
    {
        if (g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[2] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[2]++;
        }
        else
        {
            //告警
            //拒绝发送
            g_Canx_Error_System[CANx].Its_TX_ERR_FLAG = CAN_FUNC_ERR;
        }
    }
    else
    {
        g_Canx_Error_System[CANx].Its_TX_MAILBOX_ARB_ERR[2] = 0;
    }
    /

    //检测接收FIFOx上溢出
    if ((hcan->Instance->RF0R & CAN_RF0R_FOVR0) >> CAN_RF0R_FOVR0_Pos)// 接收FIFO0
    {
        if (g_Canx_Error_System[CANx].Its_RX_FIFOx_OVR[0] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_RX_FIFOx_OVR[0]++;
        }
        else
        {
            //告警
            //拒绝接收
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }
    }
    else
    {
        g_Canx_Error_System[CANx].Its_RX_FIFOx_OVR[0] = 0;
    }

    if ((hcan->Instance->RF1R & CAN_RF1R_FOVR1) >> CAN_RF1R_FOVR1_Pos)// 接收FIFO1
    {
        if (g_Canx_Error_System[CANx].Its_RX_FIFOx_OVR[1] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_RX_FIFOx_OVR[1]++;
        }
        else
        {
            //告警
            //拒绝接收
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }

    }
    else
    {
        g_Canx_Error_System[CANx].Its_RX_FIFOx_OVR[1] = 0;
    }
    /

    ///检测接收邮箱满
    if ((hcan->Instance->RF0R & CAN_RF0R_FULL0) >> CAN_RF0R_FULL0_Pos)// 接收FIFO0
    {
        if (g_Canx_Error_System[CANx].Its_RX_FIFOx_FULL[0] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_RX_FIFOx_FULL[0]++;
        }
        else
        {
            //告警
            //拒绝接收
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }
    }
    else
    {
        g_Canx_Error_System[CANx].Its_RX_FIFOx_FULL[0] = 0;
    }

    if ((hcan->Instance->RF1R & CAN_RF1R_FULL1) >> CAN_RF1R_FULL1_Pos)// 接收FIFO1
    {
        if (g_Canx_Error_System[CANx].Its_RX_FIFOx_FULL[1] < CANx_ERRx_MAX_TIME)
        {
            g_Canx_Error_System[CANx].Its_RX_FIFOx_FULL[1]++;
        }
        else
        {
            //告警
            //拒绝接收
            g_Canx_Error_System[CANx].Its_RX_ERR_FLAG = CAN_FUNC_ERR;
        }
    }
    else
    {
        g_Canx_Error_System[CANx].Its_RX_FIFOx_FULL[1] = 0;
    }
    /
    hcan->Instance->MSR = CAN_MSR_ERRI; //清除错误中断
}

 

你可能感兴趣的:(STM32)