ac7811---can1

本例程使用的是快恢复,一旦发生canbusoff后立刻重新初始化can。
ac7811官方例程中写的比较全面,有快恢复和慢恢复,可参考。

typedef struct
{
    unsigned char Data[8];
    unsigned long int ID;
    unsigned char DataLength;
}MCU_CAN_MSG;

//做个循环队列
#define CANBuffMaxLength 8	//CAN接收队列长度
MCU_CAN_MSG g_MCU_CAN_RXBuff[CANBuffMaxLength];
uint8_t g_MCU_CAN_RXFull = 0;	//0-CAN接收队列未满	1-CAN接收队列已满
uint8_t g_MCU_CAN_RXFront = 0;	//接收缓冲区队头
uint8_t g_MCU_CAN_RXRear = 0;	//接收缓冲区队尾
/**
  * 描述  	CAN帧出队
  * 输入  	CAN帧数据地址
  * 返回  	1 正常
  * 	0  队列无数据
  */
uint8_t CAN_Receive(MCU_CAN_MSG *data)
{
    if ((g_MCU_CAN_RXFull == 0) && (g_MCU_CAN_RXRear == g_MCU_CAN_RXFront))
    {
        return 0;//队列已空,没有数据
    }
    *data = g_MCU_CAN_RXBuff[g_MCU_CAN_RXFront];//数据出列队

    g_MCU_CAN_RXFront++;
    if (g_MCU_CAN_RXFront >= CANBuffMaxLength)
    {
        g_MCU_CAN_RXFront = 0;
    }
    g_MCU_CAN_RXFull = 0;	//队列未满

    return 1;
}
/**
  * 描述  	CAN帧入队
  * 输入  	CAN帧数据
  * 返回  	1 正常
  * 	0  队列已满
  */
uint8_t CAN_AddRxData(MCU_CAN_MSG data)
{
    if (g_MCU_CAN_RXFull == 1)
    {
        return 0;	//队列已满
    }
    g_MCU_CAN_RXBuff[g_MCU_CAN_RXRear] = data;	//数据入队列

    g_MCU_CAN_RXRear++;
    if (g_MCU_CAN_RXRear >= CANBuffMaxLength)
    {
        g_MCU_CAN_RXRear = 0;
    }

    if (g_MCU_CAN_RXRear == g_MCU_CAN_RXFront)
    {
        g_MCU_CAN_RXFull = 1;	//队列满
    }
    return 1;
}
/**
* @prototype CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam)
*
* @param[in] ...
* @return	 ...
*
* @brief  	 CAN1 module interrupt handler.
*			 CAN1中断处理函数.
*/
int32_t CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam)
{
	MCU_CAN_MSG CAN_RxData;
	if (event & CAN_EVENT_BUSERROR)         /* 发生错误后,打印错误消息,仅用于调试 */
	{
      //  printf("CAN[%d]e: wparam: %x  lparam: %x\r\n", event, wparam, lparam);
	}

	if (event & CAN_EVENT_RECVMSG)
	{
		if(CAN_IsMsgInReceiveBuf((CAN_Type*)lparam))
        {
            CAN_MessageRead((CAN_Type*)lparam, &g_recvCANMsgInfo);
			if((g_recvCANMsgInfo.ID == 0x200)
			||(g_recvCANMsgInfo.ID == 0x201)
			||(g_recvCANMsgInfo.ID == 0x202)
			||(g_recvCANMsgInfo.ID == 0x18aabbcc))
			{
				CAN_RxData.ID = g_recvCANMsgInfo.ID;			
				CAN_RxData.DataLength = g_recvCANMsgInfo.DLC;
				memcpy(CAN_RxData.Data, &g_recvCANMsgInfo.Data[0], 8);
				CAN_AddRxData(CAN_RxData);	//软件层实现can队列		
			}
        }
	}
	else if (event & CAN_EVENT_ERROR)
	{
		
		if (CAN1->BIT.BUSOFF & 0x01)//BUS OFF
		{
			
				CAN1_Config();//快恢复,重新初始化can1
		}
	}

	return 1;
}

void CAN1_Config(void)
{
	CAN_Config canConfig = {0};
	CAN_BaudrateConfig canBandrateConfig = {0};
	
	GPIO_SetFunc(CAN1_TX, GPIO_FUNC_2);//设置CAN1引脚复用功能
	GPIO_SetFunc(CAN1_RX, GPIO_FUNC_2);

	// GPIO_SetDir(GPIO_PD5, GPIO_OUTPUT);//设置CAN1收发器控制为IO控制   有的项目需要,根据自己实际情况来
	// do{GPIO_ResetPinBits(GPIO_PD5);}while(0);
	
	/*
	设置波特率为500K,采样点为81.25%.
	tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
	BandRate 	= (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
	SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
	在已经知道波特率与采样点的情况下,经过计算后:tSeg1 = 13,tSeg2 = 3.
	 */
	canBandrateConfig.S_PRESC 	= 5;//分频后时钟为8M.
	canBandrateConfig.S_SEG_1 	= 11;
	canBandrateConfig.S_SEG_2 	= 2;
	canBandrateConfig.S_SJW 	= 2;//满足S_SJW <= tSeg2即可.
	
	/* 
	16个过滤器中,可随意选择使用哪个,并制定其过滤模式,制定其过滤ID的类型.
	如果一个过滤器只需要接收一个ID,直接可将其设置CODE模式,然后根据ID类型设置过滤类型.
	如果一个过滤器需要接收多个ID,将其设置为MASK模式,并根据这几个ID的实际类型设置过滤ID类型,如果既有STD又有EXT,则应选择FILTER_IDE_STD_EXT_BOTH.
	此处加宏是为了更清楚的说明各种设置是否有效,在实际应用中,可将各种组合放在一起使用.
	 */
	CAN_SetFilterParam(0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY,0x200);//使用CODE模式只接收STD帧
	CAN_SetFilterParam(1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, 0x201);//使用CODE模式只接收STD帧
	CAN_SetFilterParam(2, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, 0x202);//使用CODE模式只接收STD帧
	
	CAN_SetFilterParam(3, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, 0x18aabbcc);//使用CODE模式只接收EXT帧
	canConfig.interruptEnable = TRUE;//使能中断
	canConfig.canMode = CAN_MODE_NORMAL;
	canConfig.autoReset = FALSE;//禁止自动复位,自动恢复正常.....................注意此处
	canConfig.filterList = g_canFilterTab;//赋值过滤器设置list
	
	CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
	CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);
}

CAN_FilterControl 	g_canFilterTab[CAN_MAX_FILTER_NUM] = 
{
	{ 0, 0, 0x00000000, 0x00000000},    
    { 1, 0, 0x00000000, 0x00000000},    
    { 2, 0, 0x00000000, 0x00000000},
    { 3, 0, 0x00000000, 0x00000000},
    { 4, 0, 0x00000000, 0x00000000},
    { 5, 0, 0x00000000, 0x00000000},
    { 6, 0, 0x00000000, 0x00000000},
    { 7, 0, 0x00000000, 0x00000000},
    { 8, 0, 0x00000000, 0x00000000},    
    { 9, 0, 0x00000000, 0x00000000},    
    {10, 0, 0x00000000, 0x00000000},   
    {11, 0, 0x00000000, 0x00000000},
    {12, 0, 0x00000000, 0x00000000},
    {13, 0, 0x00000000, 0x00000000},
    {14, 0, 0x00000000, 0x00000000},
    {15, 0, 0x00000000, 0x00000000},
};

uint32_t 	g_canFilterMask[3] = {0x5FFFFFFF,  0x7FFFFFFF,  0x1FFFFFFF};//只接收标准帧 只接收扩展帧 接收两种数据帧
/**
* @prototype CAN_SetFilterParam(uint8_t filterNum, uint8_t filterEn, CAN_FilterMode_TypeDef filterMode, CAN_FilterMask_TypeDef filterMask, uint32_t ID)
*
* @param[in] filterNum:过滤器编码,0到15可用.
* @param[in] filterEn:过滤器使能状态,1使能,0禁能
* @param[in] filterMode:CAN_FilterMode_TypeDef已定义.
* @param[in] filterMask:参考CAN_FilterMask_TypeDef.
* @param[in] ID
* @return	 void
*
* @brief  	 Initalize CAN filter.
*			 初始化CAN过滤器,当filterMode选择FILTER_CODE_MODE时,每个过滤器过滤一个ID,否则,使用MASK模式,过滤的多个ID的组合.
*/
void CAN_SetFilterParam(uint8_t filterNum, uint8_t filterEn, CAN_FilterMode_TypeDef filterMode, CAN_FilterMask_TypeDef filterMask, uint32_t ID)
{
	g_canFilterTab[filterNum].enable = filterEn;
	g_canFilterTab[filterNum].code = ID;
	
	if (filterMode == CAN_FILTER_MASK_MODE)
	{
		g_canFilterTab[filterNum].mask = (g_canFilterMask[filterMask] & ~ID);//进行掩码屏蔽
	}
	else
	{
		g_canFilterTab[filterNum].mask = (g_canFilterMask[filterMask] & CAN_CLEAR_ALL_ID_BIT);//进行ID屏蔽,就是ID必须与设置的ID一模一样,才接收
	}
}

/*****进行can报文处理***/
while(0x1 == CAN_Receive(&receive1_msg))//can1 标准帧和扩展帧
	{
		can1_receive_ID = receive1_msg.ID;
		can1_rx_data[0] = receive1_msg.Data[0];
		can1_rx_data[1] = receive1_msg.Data[1];
		can1_rx_data[2] = receive1_msg.Data[2];
		can1_rx_data[3] = receive1_msg.Data[3];
		can1_rx_data[4] = receive1_msg.Data[4];
		can1_rx_data[5] = receive1_msg.Data[5];
		can1_rx_data[6] = receive1_msg.Data[6];
		can1_rx_data[7] = receive1_msg.Data[7];
		if(can1_receive_ID == 0x200)
		{
		}
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值