【5744】MPC5744入门笔记(2)CAN实验

0. 目录

1. 引言

为什么在入门笔记第2篇就直接写can,而是跳过了GPIO、uart这些常用外设呢?
原因很简单,因为我最急着要用。
作为车载产品,can肯定是最先调通的。
而这一系列文章就是调通一个外设,总结一个。
而已。

2. 实验

2.1 环境

  • 软件环境 : S32DS for power v2.1 (RTM3.0.0)
  • 硬件环境 : DEVKIT-MPC5744P (MPC5744P-BGA257)

2.2 准备工作

先是熟悉一下demo的流程,在样例中找到一个can_pal_mpc5744p。
简单实测了一下,利用cantest下发0x2为ID的can报文,1 1 1 1 1 1 1 1,板上的灯会变化颜色。
看了一个代码的调用流程,OK没问题,走起来。
要注意是,要通过12V电源供电,usb供电是不够can使用的。(修改供电还需要改跳线帽)

2.3 can实验

2.3.1 引脚

代码中用的是Can0(PB0 、PB1)

2.3.2 步骤

  1. 新建工程
    File-New-S32DS application project。
    在这里插入图片描述

  2. 双击 .pe文件,双击componets。
    打开组件库,添加can_pal。
    在这里插入图片描述
    can_pal的参数就不修改了,使用默认的can0和500k。
    然后修改pin_mux,把的引脚设置上。
    在这里插入图片描述

  3. 生成代码
    在这里插入图片描述
    点击后会在/Generated_Code文件夹下生成对应的配置代码。其实就是一些数组和参数,在调用/SDK/platform里面的接口时会用到这些。

  4. 添加自己的用户代码,实现自己的功能。

2.3.3 代码

为了方便显示,这里我将所有相关代码都写在了main.c中,并且没有封装接口,直接调用的都是pal库的接口。
以下实现了最简单的收发,当收到ID为0x2,且报文第一个字节是0x2时,会发送can报文出来。


#include "Cpu.h"
#include "typedefs.h"

Uint8 g_BootLoaderVer[4]  = {19,11,28,1};

#define TX_MAILBOX  (1UL)
#define RX_MAILBOX  (0UL)

can_buff_config_t buffCfg =			//Can缓冲区域配置
{
        .enableFD = false,
        .enableBRS = false,
        .fdPadding = 0U,
        .idType = CAN_MSG_ID_STD,
        .isRemote = false
};

int main(void)
{
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();      
  #endif

    CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_FORCIBLE);
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);
    CAN_Init(&can_pal1_instance, &can_pal1_Config0);

	/* Configure RX buffer with index RX_MAILBOX */
	CAN_ConfigRxBuff(&can_pal1_instance, RX_MAILBOX, &buffCfg, 0x02);			//只收

      while(1)
      {
    	  can_message_t recvMsg;
    	  CAN_Receive(&can_pal1_instance, RX_MAILBOX, &recvMsg);

    	  if(recvMsg.id == 0x02 && recvMsg.data[0]== 2)
    	  {
			  /* Configure TX buffer with index TX_MAILBOX*/
			  CAN_ConfigTxBuff(&can_pal1_instance, TX_MAILBOX, &buffCfg);

			  /* Prepare message to be sent */
			  can_message_t message =					//Can消息配置
			  {
				  .cs = 0U,
				  .id = 0xaa,
				  .data[0] = g_BootLoaderVer[0],
				  .data[1] = g_BootLoaderVer[1],
				  .data[2] = g_BootLoaderVer[2],
				  .data[3] = g_BootLoaderVer[3],
				  .length = 4U
			  };
			  /* Send the information via CAN */
			  CAN_Send(&can_pal1_instance, TX_MAILBOX, &message);
			  while(CAN_GetTransferStatus(&can_pal1_instance, TX_MAILBOX) == STATUS_BUSY);
    	  }
      }

}

2.3.4 代码解析

代码写的很简单,没有做任何封装,就是用系统函数 。
初始化时钟,初始化引脚,初始化Can。
CAN_Init。
配置接收和发送的mailbox
CAN_ConfigRxBuff,CAN_ConfigTxBuff。
然后收发即可。
CAN_Receive,CAN_Send。

比较值得一记录的就是
CAN_ConfigRxBuff和CAN_ConfigTxBuff这两个接口,稍微难懂一点。

CAN_ConfigRxBuff

我们先看下函数接口,

status_t CAN_ConfigRxBuff(const can_instance_t * const                               instance,
                        uint32_t buffIdx,
                        const can_buff_config_t *config,
                        uint32_t acceptedId)

里面做了什么?
根据初始化实例的类型是CAN_INST_TYPE_FLEXCAN还是CAN_INST_TYPE_MCAN来判断调用不同的接口。
用的比较多是FLEXCAN。
下一步调用

status = FLEXCAN_DRV_ConfigRxMb((uint8_t) instance->instIdx,
                                        (uint8_t) buffIdx,
                                        &dataInfo,
                                        acceptedId);

在下一步继续调用FLEXCAN_SetRxMsgBuff。

status_t FLEXCAN_SetRxMsgBuff(
    CAN_Type * base,
    uint32_t msgBuffIdx,
    const flexcan_msgbuff_code_status_t *cs,
    uint32_t msgId)

把msgId拼接完放到flexcan_mb[1](FLEXCAN_GetMsgBuffRegion获取)中,其实就是RAMn寄存器。

2.3.5 实现一个buffer接收所有的CanID

使用CAN_ConfigTxBuff接口实现

can_buff_config_t g_CanBufferConfig =					//Can buff 配置,目前接受和发送buffer都用这个配置
{
        .enableFD = false,
        .enableBRS = false,
        .fdPadding = 0U,
        .idType = CAN_MSG_ID_STD,
        .isRemote = false
};



void CAN_Config()
{
	CAN_ConfigRxBuff(&can_pal1_instance, RX_MAILBOX, &g_CanBufferConfig, 0x00);			//只收
	CAN_SetRxFilter(&can_pal1_instance,FLEXCAN_MSG_ID_STD, RX_MAILBOX,0x0);
	CAN_ConfigTxBuff(&can_pal1_instance, TX_MAILBOX, &g_CanBufferConfig);
}


int main(void)
{

  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif


    CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_FORCIBLE);
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);
    CAN_Init(&can_pal1_instance, &can_pal1_Config0);
    CAN_Config();


      while(1)
      {
    	  can_message_t recvMsg;
    	  CAN_Receive(&can_pal1_instance, RX_MAILBOX, &recvMsg);

    	  if(recvMsg.data[0]== 2)
    	  {
    		  CAN0_Send(recvMsg.id,g_BootLoaderVer,4);
    	  }
      }

}
发布了25 篇原创文章 · 获赞 7 · 访问量 5116

猜你喜欢

转载自blog.csdn.net/tao475824827/article/details/103299741