| 本帖最后由 袁胜富 于 2024-12-17 02:24 编辑 
 #申请原创# 一、CAN基本知识
 CAN(控制局域网),总线分为CAN_H和CAN_L。CAN的数据包的帧ID分为:标准ID(0X00)和拓展ID(0X01),标准帧ID范围:0-0x7FF,拓展ID范围:0-0x1FFFFFFF。帧类型分为:数据帧(0X00)和远程帧(0X01)。数据包组成格式:standard_id(4Bytes)[标准ID]+extended_id(4Bytes)[拓展ID]+id_type(1Byte)[ID类型]+frame_type(1Byte)[帧类型]+dlc(1Byte)[帧数据长度]+data(8Bytes)[数据]。
 CAN在许多领域都有应用,如汽车传感器,BMS,电机控制等。
 [img]static/image/hrline/2.gif" >
 
 二、G32A1465CAN配置流程
 A.配置GPIO
 PIN_SETTINGS_CFG_T g_pinsConfig[NUM_OF_CONFIGURED_PINS0] = {
 {
 //解释为:PME4为CAN0的RX数据接收引脚,不接上下拉电阻,低驱动能力,复用功能5
 .base           = PME,
 .pinPmIdx       = 4U,
 .pullCfg        = PM_INTERNAL_PULL_NOT_ENABLED,
 .drvSel         = PM_LOW_DRIVE_STRENGTH,
 .passiveFilt    = false,
 .mux            = PM_MUX_ALT5,
 .pinLk          = false,
 .intCfg         = PM_DMA_INT_DISABLED,
 .clrInt**      = false,
 .gpioBase       = NULL,
 .digitFilt      = false,
 },
 {
 //解释为:PME5为CAN0的TX数据发送引脚,不接上下拉电阻,低驱动能力,复用功能5
 .base           = PME,
 .pinPmIdx       = 5U,
 .pullCfg        = PM_INTERNAL_PULL_NOT_ENABLED,
 .drvSel         = PM_LOW_DRIVE_STRENGTH,
 .passiveFilt    = false,
 .mux            = PM_MUX_ALT5,
 .pinLk          = false,
 .intCfg         = PM_DMA_INT_DISABLED,
 .clrInt**      = false,
 .gpioBase       = NULL,
 .digitFilt      = false,
 }
 };
 B.配置CAN
  
  
  
  /*最大邮箱3个两个数据接收邮箱,一个数据发送邮箱,工作发送为普通模式,不打开接收缓冲,使用8M时钟作为CAN的时钟源*/
 /*通过用户手册可知:CAN的波特率 = fpclk/((preDiv+1)*(1+(propSeg+phaseSeg1+2)+(phaseSeg2+1)))*/
 
 CAN_USER_CONFIG_T g_canConfig = {
 .maxMbNumber = 3,    /* 2 Rx MBs and 1 Tx MB */
 .operationMode = CAN_MODE_NORMAL,
 .rxFifoEnable = false,
 .rxFifoFilterNum = CAN_RXFIFO_ID_FILTERS_8,
 .rxFifoTransferType = CAN_RXFIFO_USE_INTERRUPT,
 .rxFifoDmaChannel = 0,
 .fdEnable = false,
 .fdPayloadSize = CAN_FD_PAYLOAD_SIZE_16,
 .clockSource = CAN_CLOCK_SOURCE_OSC,
 .bitrate = {
 /*根据手册测试出常用波特率的配置如下,250K bps,500K bps,1Mbps*/
 /*250k bps*/
 //        .preDiv = 1,
 //        .propSeg = 7,
 //        .phaseSeg1 = 4,//propSeg+phaseSeg1 = timeSegment1
 //        .phaseSeg2 = 1,//phaseSeg2 = timeSegment2
 //        .resyncJumpWidth = 2
 /*500kbps*/
 //        .preDiv = 0,
 //        .propSeg = 7,
 //        .phaseSeg1 = 4,//propSeg+phaseSeg1 = timeSegment1
 //        .phaseSeg2 = 1,//phaseSeg2 = timeSegment2
 //        .resyncJumpWidth = 2
 /*1M bps*/
 .preDiv = 0,
 .propSeg = 1,
 .phaseSeg1 = 2,//propSeg+phaseSeg1 = timeSegment1
 .phaseSeg2 = 1,//phaseSeg2 = timeSegment2
 .resyncJumpWidth = 2
 },
 .fdBitrate = {
 .preDiv = 0,
 .propSeg = 0,
 .phaseSeg1 = 0,
 .phaseSeg2 = 0,
 .resyncJumpWidth = 0
 }
 };C.发送邮箱配置
 /*配置为标准帧,8字节长度*/
 /* Configure Tx MB */
 CAN_DATA_INFO_T txMbInfo = {
 .msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
 .dataLen = 8,                 /* Used only to initialize the MB, will be updated when send data */
 .fdEnable = false,            /* Disable CAN FD */
 .isRemote = false};
 CAN_ConfigureTxMb(CAN0_INSTANCE, TX_MB, &txMbInfo, 0);
 D.接收邮箱配置
 /* Use individual Rx masking for the MBs */
 CAN_SetRxMaskType(CAN0_INSTANCE, CAN_RX_MASK_INDIVIDUAL);
 
 /* Configure Rx MB0, it will receive standard frames with ID 1 */
 CAN_DATA_INFO_T rxMb0Info = {
 .msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
 .dataLen = 8,                 /* Max data length for classic CAN is 8 bytes */
 .fdEnable = false,            /* Disable CAN FD */
 .isRemote = false};
 CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_0, &rxMb0Info, RX_CAN_MESSAGE_ID);
 CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_STANDARD, RX_MB_0, 0xFFFFFFFF);
 
 /* Configure Rx MB1, it will receive extended frames with ID 1 */
 CAN_DATA_INFO_T rxMb1Info = {
 .msgIdType = CAN_ID_EXTENDED, /* Extended CAN ID */
 .dataLen = 8,                 /* Max data length for classic CAN is 8 bytes */
 .fdEnable = false,            /* Disable CAN FD */
 .isRemote = false};
 CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_1, &rxMb1Info, RX_CAN_MESSAGE_ID);
 CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_EXTENDED, RX_MB_1, 0x000000);
 
 /* Set the CAN event callback handler */
 CAN_InstallEventCallback(CAN0_INSTANCE, &CanEventCallback, NULL);
 E.设置数据接收结构体变量
 /* Receive CAN frames from MB0 and MB1 */
 CAN_MSG_BUF_T rxFrame0;
 CAN_MSG_BUF_T rxFrame1;
 
 [img]static/image/hrline/2.gif" >
 三、实验
 A.按下按键Key1发送
 /*!
 * @brief This function is called when the KEY1 button is pressed
 */
 void Key1Handler(void)
 {
 /* Send standard CAN frame */
 uint8_t payload[8] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};
 CAN_DATA_INFO_T txDataInfo = {
 .msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
 .dataLen = sizeof(payload),   /* Payload size */
 .fdEnable = false,
 .isRemote = false};
 CAN_SendNonBlocking(CAN0_INSTANCE, TX_MB, &txDataInfo, TX_CAN_MESSAGE_ID_1, payload);
 }
 
 B.按下按键Key2发送
 /* Send extended CAN frame */
 uint8_t payload[7] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
 CAN_DATA_INFO_T txDataInfo = {
 .msgIdType = CAN_ID_EXTENDED, /* Extended CAN ID */
 .dataLen = sizeof(payload),   /* Payload size */
 .fdEnable = false,
 .isRemote = false};
 CAN_SendNonBlocking(CAN0_INSTANCE, TX_MB, &txDataInfo, TX_CAN_MESSAGE_ID_2, payload);
 C.接收邮箱0经过过滤设置,只接收ID为1的标准帧。
 D.接收邮箱1没有经过过滤设置,可以接收范围内合法的所有拓展帧ID。
 
 
 
 [img]static/image/hrline/2.gif" >
 四、实验结果
 A:
 
  B:
 
  C:
 
  D:
 
  
 
 [img]static/image/hrline/2.gif" >
 五、心得体会
 新的MCU需要阅读数据手册和用户手册,知识的学习需要理论和实践才能得到新知。非常感谢极海半导体提供这次机会,在忙里偷闲中参加此次活动,希望和大家一起探讨学习新的知识技术。谢谢官方机会,谢谢大家。
 
 
 |