【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用

本篇开始讲解FlexCAN的使用方法,采用SDK自动生成驱动。

新建工程CAN_Test,具体步骤不再重复,新建完毕,打开Processor Expert界面,在Components Library中添加flexcan,添加时会自动增加辅助模块(若是没有禁用其它版本SDK,则会弹出提示,此处会有多个版本供选择,不同版本兼容性可能有问题)。

【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用_第1张图片

 

添加完,在Components中我们可以看到多了三个组件,其中2个为参考组件。

【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用_第2张图片

接下来,我们要进行配置。

1、配置FlexCAN的IO,选中pin_mux模块,然后在Components Inspector - pin_mux中,设置CAN0的收发引脚。

2、配置时钟,选中clockMain1,在Components Inspector - clockMain1中将外设桥时钟设为50MHz。

3、配置CAN,将PE clock source设置为Peripheral clock,为了确保波特率误差小,PE时钟最好不要太低。另外注意,此处不能设置波特率,默认都是500Kbps,若要调整,只能在代码中手动设置,设置方法较为复杂。

其它不做配置,直接生成代码。

我们不使用CAN中断,采用轮询方式,一般为确保实时性,最多使用一个定时器中断作为任务分配计时,不过多使用中断。

【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用_第3张图片

 

【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用_第4张图片

 

【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用_第5张图片

 

一、CAN函数封装

由于生成的CAN驱动仍然数据分散的底层驱动,我们将CAN的初始化,发送、接收数据封装成通用函数。

初始化中,数组中波特率默认的都是500Kbps的配置,若要修改波特率,我们调用FLEXCAN_DRV_SetBitrate函数即可,函数的参数要通过波特率计算出分频、同步段、传播段、相位缓冲段1、相位缓冲段2。

这里教大家一个快速设置波特率的方法,假设我们要将波特率设置为250Kbps。我们可以先将PE时钟设置高一倍,例如200MHz,生成代码,在Generated_Code的canCom1.c中找到canCom1_InitConfig0,里面有波特率参数,复制出来,然后将PE设置为100MH,生成代码,再调用FLEXCAN_DRV_SetBitrate函数,将刚刚复制的参数传入,波特率就设置为了250Kbps,其它波特率也类似于此。不过不能整除的可能还是要自行计算。

【MPC5744P】S32DS中Processor Expert自动生成代码工具使用教程(五) FlexCAN使用_第6张图片

 

此处我们保持500Kbps波特率,发送ID为:0x00c18064,只接收ID:0x00a180c8

#define ReceiveCANID 0x00c18064
#define SendCANID 0x00a180c8

void FlexCAN_Initial(void)
{
	uint32_t mailbox = 5;
	//FLEXCAN_DRV_SetBitrate(INST_CANCOM1,&canCom1_InitConfig0);
	FLEXCAN_DRV_Init(INST_CANCOM1,&canCom1_State,&canCom1_InitConfig0); //default is 500K

	/*
	 *  CANCLK is Protocol Engine(PE) clock
	 *	CanBaud = CANCLK/(PRESDIV+1)/Tq
	 *	Tq=(1+(PROPSEG+1)+(PSEG1+1)+(PSEG2+1))
	 *	limit:
	 *		4<=PROPSEG+1+PSEG1+1<=16
	 *		2<=PSEG2+1<=8
	 *	if CANCLK=100MHz,
	 *	    CanBaud=500Kbps, when  PRESDIV=9,PROPSEG=7,PSEG1=7,PSEG2=2, RJW=1
	 *	    CanBaud=250Kbps, when  PRESDIV=24,PROPSEG=7,PSEG1=4,PSEG2=1, RJW=1
	 * */
	//const flexcan_time_segment_t baudrate = {.propSeg=7,.phaseSeg1=4,.phaseSeg2=1,.preDivider=24,.rJumpwidth=1};
	//FLEXCAN_DRV_SetBitrate(INST_CANCOM1,&baudrate);
	//EDMA_DRV_Init(&dmaController1_State,&dmaController1_InitConfig0,edmaChnStateArray,edmaChnConfigArray,EDMA_CONFIGURED_CHANNELS_COUNT);

	flexcan_data_info_t dataInfo =
	{
		  .data_length = 8U,
		  .msg_id_type = FLEXCAN_MSG_ID_EXT
	};

	/* Configure RX message buffer with index RX_MSG_ID and RX_MAILBOX */
	FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, mailbox, &dataInfo, 0xc18064);
}

void FlexCAN_SendData(uint8_t * data, uint32_t len)
{
	uint32_t mailbox = 0;
	/* Set information about the data to be sent
	*  - 1 byte in length
	*  - Standard message ID
	*  - Bit rate switch enabled to use a different bitrate for the data segment
	*  - Flexible data rate enabled
	*  - Use zeros for FD padding
	*/
	flexcan_data_info_t dataInfo =
	{
		  .data_length = len,
		  .msg_id_type = FLEXCAN_MSG_ID_EXT
	};

	/* Configure TX message buffer with index TX_MSG_ID and TX_MAILBOX*/
	FLEXCAN_DRV_ConfigTxMb(INST_CANCOM1, mailbox, &dataInfo, SendCANID);

	/* Execute send non-blocking */
	FLEXCAN_DRV_Send(INST_CANCOM1, mailbox, &dataInfo, SendCANID, data);
}


uint8_t FlexCAN_ReceiveData(uint8_t *data)
{
	/* Define receive buffer */
	  flexcan_msgbuff_t recvBuff;
	  uint32_t mailbox = 5;
	  uint32_t status=0;

	  status = ((CAN_0->IFLAG1)>>mailbox)&0x01;
	  //MailBox is receive buffer
	  if (status != 1)
	  {
		  return;
	  }
	  /* Start receiving data in RX_MAILBOX. */
	  FLEXCAN_DRV_Receive(INST_CANCOM1, mailbox, &recvBuff);

	  /* Wait until the previous FlexCAN receive is completed */
	  if(FLEXCAN_DRV_GetTransferStatus(INST_CANCOM1, mailbox) == STATUS_SUCCESS)
	  {

		  /* Check the received message ID and payload */
		  if(recvBuff.msgId == ReceiveCANID)
		  {
			  /* Toggle output value LED1 */
			  //PINS_DRV_TogglePins(PTC, (1 << 12));
			  uint8_t i;
			  for(i=0;i

 

二、测试使用CAN收发功能

我们现在调用函数,进行CAN收发测试。

以下示例代码逻辑为:启动后先初始化时钟和引脚,约1s闪烁红色LED,循环判断接收到0x00c18064的数据,收到数据后将首字节数据+1回馈,并且翻转绿色LED。

void ReceiveCANData()
  {
	  uint8_t data[8] = {0};
	  uint8_t dataLen = 0;
	  if((dataLen=FlexCAN_ReceiveData(data))!=0)
	  {
		  /* Toggle output value LED1 */
		  PINS_DRV_TogglePins(PTC, (1 << 12));

		  data[0] +=1;
		  FlexCAN_SendData(data,dataLen);
	  }

  }
  uint32_t countA=0,countB=0;
int main(void)
{
  /* Write your local variable definition here */

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/

  /* Write your code here */
  /* For example: for(;;) { } */
    CLOCK_DRV_Init(g_clockManConfigsArr[0]);
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS,g_pin_mux_InitConfigArr);
    FlexCAN_Initial();


    //uint8_t canData[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
    for(;;)
    {
    	ReceiveCANData();
    	countA++;
    	if(countA>1000000)
    	{
    		countA=0;
    		countB=countB>10000?0:countB+1;
    		PINS_DRV_TogglePins(PTC,1<<11);
    		//SendCANData(1,0xa180c8,canData,8);
    	}
    }

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

 

收发示例:

 

 

你可能感兴趣的:(MCU,NXP,MPC574X开发)