[活动] 【极海G32A1465测评】6、CAN点灯

[复制链接]
 楼主| sujingliang 发表于 2024-12-20 13:51 | 显示全部楼层 |阅读模式
本帖最后由 sujingliang 于 2024-12-20 18:37 编辑

手头刚好有另一个具有CAN控制器和CAN收发器的开发板Mini-F5333(主控MM32F5333D7P),可以和G32A1465组成一个CAN网络。
对于CAN网络,这两个开发板扮演ECU的角色(控制器在汽车的专业术语叫ECU)

一、建立CAN网络

41.png

ECU1:G32A1465
47.png
ECU2:Mini-F5333
48.png
二、ECU1程序
为了简便起见,ECU1扮演接收方,CAN网络中没有主从设定,任何一个ECU既可以做为发送方也可以做为接收方
1、CAN配置
经典帧配置,原来例程的配置没做修改
  1. CAN_USER_CONFIG_T g_canConfig = {
  2.     .maxMbNumber = 3,    /* 2 Rx MBs and 1 Tx MB */
  3.     .operationMode = CAN_MODE_NORMAL,//CAN_MODE_LOOPBACK,
  4.     .rxFifoEnable = false,
  5.     .rxFifoFilterNum = CAN_RXFIFO_ID_FILTERS_8,
  6.     .rxFifoTransferType = CAN_RXFIFO_USE_INTERRUPT,
  7.     .rxFifoDmaChannel = 0,
  8.     .fdEnable = false,
  9.     .fdPayloadSize = CAN_FD_PAYLOAD_SIZE_16,
  10.     .clockSource = CAN_CLOCK_SOURCE_OSC,
  11.     .bitrate = {
  12.         .preDiv = 1,
  13.         .propSeg = 7,
  14.         .phaseSeg1 = 4,
  15.         .phaseSeg2 = 1,
  16.         .resyncJumpWidth = 3
  17.     },
  18.     .fdBitrate = {
  19.         .preDiv = 0,
  20.         .propSeg = 0,
  21.         .phaseSeg1 = 0,
  22.         .phaseSeg2 = 0,
  23.         .resyncJumpWidth = 0
  24.     }
  25. };
主要是工作模式、波特率、中断配置。
关于波特率,原理参见下图,这里波特率是250kbps,对于CAN来说,已经算高速CAN。
45.png 手册里给了计算公式:
49.png

bitrate=8000000/{[(1+(4+1)+(1+1)+(7+1)]*(1+1)}=8000000/32=250000

2、CAN初始化

  1. /* Initialize the CAN controller, bitrate is 250K */
  2.     CAN_Init(CAN0_INSTANCE, &canState, &g_canConfig);


配置发送报文缓存
  1. /* Configure Tx MB */
  2.     CAN_DATA_INFO_T txMbInfo = {
  3.         .msgIdType  = CAN_ID_STANDARD,   /* Standard CAN ID */
  4.         .dataLen    = 8,        /* Used only to initialize the MB, will be updated when send data */
  5.         .fdEnable   = false,    /* Disable CAN FD */
  6.         .isRemote   = false
  7.     };
  8.     CAN_ConfigureTxMb(CAN0_INSTANCE, TX_MB, &txMbInfo, 0);
配置接收报文缓存
  1. /* Use individual Rx masking for the MBs */
  2.     CAN_SetRxMaskType(CAN0_INSTANCE, CAN_RX_MASK_INDIVIDUAL);

  3.     /* Configure Rx MB0, it will receive standard frames with ID 1 */
  4.     CAN_DATA_INFO_T rxMb0Info = {
  5.         .msgIdType  = CAN_ID_STANDARD,   /* Standard CAN ID */
  6.         .dataLen    = 8,        /* Max data length for classic CAN is 8 bytes */
  7.         .fdEnable   = false,    /* Disable CAN FD */
  8.         .isRemote   = false
  9.     };
  10.     CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_0, &rxMb0Info, RX_CAN_MESSAGE_ID);
  11.     CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_STANDARD, RX_MB_0, 0xFFFFFFFF);
其中#define RX_CAN_MESSAGE_ID   (888U),ECU2会向这个ID发送消息

CAN_ID_STANDARD:11位识别码

3、CAN中断回调函数
在MB0接收到数据后,设置接收标识为真。
  1. void CanEventCallback(
  2.     uint8_t instance,
  3.     CAN_EVENT_TYPE_T eventType,
  4.     uint32_t mbIndex,
  5.     CAN_STATE_T *driverState)
  6. {
  7.     /* A frame was received in the configured Rx MB */
  8.     if (eventType == CAN_EVENT_RX_COMPLETE)
  9.     {
  10.         /* Set the receive complete flags */
  11.         if (mbIndex == RX_MB_0)
  12.         {
  13.             g_mb0ReceiveCompleted = true;
  14.         }
  15.     }
  16. }
4、while(1)
接收到id为888u的数据,打印出来,翻转LED。这里其实不用判断ID,因为如果ID不是888u,ECU1是无法接收的。
  1. while (!exit)
  2.     {
  3.         /* Reset the receive complete flags */
  4.         g_mb0ReceiveCompleted = false;
  5.         g_mb1ReceiveCompleted = false;

  6.         /* Start non-blocking receiving */
  7.         CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_0, &rxFrame0);
  8.         CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_1, &rxFrame1);

  9.         /* Wait until one of the MBs received a CAN frame */
  10.         while ((g_mb0ReceiveCompleted == false)
  11.             && (g_mb1ReceiveCompleted == false));

  12.                                                 
  13.                                 if(g_mb0ReceiveCompleted==true){
  14.                                         if(rxFrame0.messageId==888U){
  15.                                                 for(i=0;i<rxFrame0.dataLen;i++){
  16.                                                         printf("0x%02X,",rxFrame0.data[i]);
  17.                                                 }
  18.                                                 printf("\r\n");
  19.                                                 LED_Toggle(LED_RED);
  20.                                         }
  21.                                 }
  22.     }



三、ECU2程序
MM32的部分简单写一下:
1、初始化
波特率250kbps,配置了几个发送用MB
  1. ...
  2.     FLEXCAN_GetDefaultConfig(&FlexCAN_ConfigStruct);
  3.     FlexCAN_ConfigStruct.baudRate             = 250000; /* 250kbps */
  4.     FlexCAN_ConfigStruct.clkSrc               = Enum_Flexcan_ClkSrc1;
  5.     FlexCAN_ConfigStruct.enableLoopBack       = false;
  6.     FlexCAN_ConfigStruct.disableSelfReception = true;
  7.     FlexCAN_ConfigStruct.enableIndividMask    = true;

  8.     FLEXCAN_Init(FLEXCAN, &FlexCAN_ConfigStruct);
  9.         
  10.          FLEXCAN_TxMbConfig(FLEXCAN, 7, ENABLE);
  11.     FLEXCAN_TxMbConfig(FLEXCAN, 8, ENABLE);
  12.     FLEXCAN_TxMbConfig(FLEXCAN, 9, ENABLE);

  13.     FLEXCAN_TransferCreateHandle(FLEXCAN, &FlexCAN_Handle, FlexCAN_Transfer_Callback, NULL);
  14.         ...

2、while(1)
  1.    uint8_t Buffer[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};

  2.     printf("\r\nTest %s", __FUNCTION__);

  3.     FlexCAN_Configure();

  4.     FlexCAN_SendStandardFrameMessage(888U, Buffer, sizeof(Buffer));
  5.     while (1)
  6.     {
  7.         PLATFORM_LED_Toggle(LED1);
  8.                                 FlexCAN_SendStandardFrameMessage(888U, Buffer, sizeof(Buffer));
  9.         PLATFORM_DelayMS(1000);
  10.     }



每隔1秒,向ID为888U(ECU1)发送buffer内容。

43.png
对应CAN报文:
识别码:888U
DLC:8
数据码:0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88

四、运行效果

1、连线
3.jpg

2、收到CAN数据LED_RED翻转,串口打印收到的信息

tutieshi_480x272_10s.gif








您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部