MPC5744 使用S32 DS中的PE组件自动生成代码(四)CAN通信

配置底层

1、按照之前讲的,根据硬件设计配置引脚
在这里插入图片描述
2、添加CAN模块。在模块库中将flexcan模块添加到【Components】中。
在这里插入图片描述
3、双击该模块配置相关属性
在这里插入图片描述
4、更改一下CAN的时钟,和module clock匹配
在这里插入图片描述
5、配置好了,按照之前讲的在【Project】选项卡中选择生成PE代码,这样CAN的底层就配置好了。

代码实现

1、回调函数。回调函数的定义要在初始化之前,不然初始化创建回调函数的时候找不到源

flexcan_msgbuff_t gCan0RxBuff[CAN0_RX_NUM];  //CAN0
uint8_t ucCan0Rxstate[CAN0_RX_NUM] = {0,0};
uint8_t ucCan0Txstate[CAN0_TX_NUM] = {0,0,0,0,0};

static void CAN0_CallBack(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, struct FlexCANState *driverState)
{
	if (eventType == FLEXCAN_EVENT_TX_COMPLETE)
	{
		if (buffIdx < CAN0_TX_NUM)
		{
			ucCan0Txstate[buffIdx] = 0;
		}
	}
	else if (eventType == FLEXCAN_EVENT_RX_COMPLETE)
	{
		ucCan0Rxstate[buffIdx] = 1;
		FLEXCAN_DRV_Receive(INST_CANCOM0, buffIdx, &gCan0RxBuff[buffIdx]);
	}
}

2、初始化函数

void vCan0Init(void)
{
	uint8_t i = 0;
	flexcan_data_info_t stCanData;
	stCanData.data_length = 0x08;
	stCanData.is_remote = 0;

	FLEXCAN_DRV_Init(INST_CANCOM0, &canCom0_State, &canCom0_InitConfig0);  //初始化
	FLEXCAN_DRV_InstallEventCallback(INST_CANCOM0, CAN0_CallBack, NULL);//创建回调函数

	//can0接收初始化  每个通道接收固定的ID。
	stCanData.msg_id_type = FLEXCAN_MSG_ID_STD;   //ID为标准ID
	FLEXCAN_DRV_ConfigRxMb(INST_CANCOM0, 0, &stCanData, 0x110);  //设置接收通道0,接收ID为0x110的CAN信息
	FLEXCAN_DRV_Receive(INST_CANCOM0, 0, &gCan0RxBuff[0]);  //0通道的数据存在这里
	ucCan0Rxstate[0] = 0;  //非0为接收到数据

	stCanData.msg_id_type = FLEXCAN_MSG_ID_STD;   //ID为标准ID
	FLEXCAN_DRV_ConfigRxMb(INST_CANCOM0, 1, &stCanData, 0x120);  //设置接收通道1,接收ID为0x110的CAN信息
	FLEXCAN_DRV_Receive(INST_CANCOM0, 1, &gCan0RxBuff[1]);  //1通道的数据存在这里
	ucCan0Rxstate[1] = 0;  //非0为接收到数据

	//发送初始化  发送的通道可以重复,只要不和接收通道重复就行
	for (i = 0;i < CAN0_TX_NUM;i++)
	{
		ucCan0Txstate[i] = 0;
	}
}

3、CAN线程处理函数

uint16_t usCnt=0;
void vCanHandle(void)
{
	uint8_t ucTxData[8]={0};
	uint8_t ucI=0;
	static uint16_t ucIndex=2;
	flexcan_data_info_t stTxDataInf;

	stTxDataInf.data_length = 8;
	stTxDataInf.is_remote = 0x00;
	stTxDataInf.msg_id_type = FLEXCAN_MSG_ID_STD;

	//接收报文 再回复  注意发送通道不可以和接收通道重复
	if(ucCan0Rxstate[0] == 1)  //ID 0x110
	{
		ucCan0Rxstate[0] = 0;
		for(ucI=0; ucI<8; ucI++)
		{
			ucTxData[ucI] = ucI;
		}
		FLEXCAN_DRV_Send(INST_CANCOM0, 4, &stTxDataInf, 0x110, ucTxData);
		ucCan0Txstate[0]=1;
	}
	if(ucCan0Rxstate[1] == 1)	//ID 0x120
	{
		ucCan0Rxstate[1] = 0;
		for(ucI=0; ucI<8; ucI++)
		{
			ucTxData[ucI] = ucI+0x10;
		}
		FLEXCAN_DRV_Send(INST_CANCOM0, 5, &stTxDataInf, 0x120, ucTxData);
		ucCan0Txstate[1]=1;
	}
	//定时自动上传   发送报文的通道随便设置,只要不占用接收通道的就行
	if(usCnt++ %150 ==0)
	{
		usCnt=0;
		if(ucCan0Txstate[ucIndex] == 0)
		{
			for(ucI=0; ucI<8; ucI++)
			{
				ucTxData[ucI] = ucI+(0x10*ucIndex);
			}
			FLEXCAN_DRV_Send(INST_CANCOM0, ucIndex, &stTxDataInf, 0x120+ucIndex, ucTxData);

			ucCan0Txstate[ucIndex]=1;

			if(++ucIndex > 4)
			{
				ucIndex=2;
			}
		}
	}
}

4、初始化和主函数

void vSysInit(void)
{
	CLOCK_DRV_Init(g_clockManConfigsArr[0]);  //初始化时钟
	PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);  //初始化引脚
	PINS_DRV_WritePin(PTF,0x08,1);  //开电源模块
	vADCInit();
	vUartInit();
	vCan0Init();
	PIT_DRV_Init(INST_PIT, &pit_InitConfig);  // PIT initialize, system tick
	//通道0
	PIT_DRV_ConfigChannel(INST_PIT, pit_ChnConfig0.hwChannel, pit_ChnConfig0.period, pit_ChnConfig0.periodUnit);
	PIT_DRV_EnableChannelInterrupt(INST_PIT, pit_ChnConfig0.hwChannel);
	PIT_DRV_StartChannel(INST_PIT, pit_ChnConfig0.hwChannel);
	INT_SYS_EnableIRQ(PIT_Ch0_IRQn);
	INT_SYS_SetPriority(PIT_Ch0_IRQn,1);
}
int main(void)
{
	vSysInit();
	while(1)
	{
		vRS485Handle();
		AdcSampleTask();
		vCanHandle();
	}
}
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值