[经验分享] 【DigiKey“智造万物,快乐不停”创意大赛】 CAN通信测试

TL-LED   2024-1-3 10:26 楼主

测试下CAN通信。

 

一、CAN硬件接口

1.1、硬件电路图

001.png

1.2、引脚配置

002.png

使用FDCAN1接口,需要外接收发器芯片。

 

1.3、硬件连接

005.jpg

 

二、软件

2.1、fdcan.c

#include "main.h"
#include "fdcan/fdcan.h"

FDCAN_HandleTypeDef       g_fdcanx_handle;             /* FDCAN1句柄 */
FDCAN_TxHeaderTypeDef     g_fdcanx_txheade;            /* 发送消息 */
FDCAN_RxHeaderTypeDef     g_fdcanx_rxheade;            /* 接收消息 */

/**
* @brief  FDCAN MSP Initialization
* This function configures the hardware resources used in this example
* @param hfdcan: FDCAN handle pointer
* @retval None
*/
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(hfdcan->Instance==FDCAN1)
  {
  /* USER CODE BEGIN FDCAN1_MspInit 0 */

  /* USER CODE END FDCAN1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
    PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL;
		HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
//    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
//    {
//      Error_Handler();
//    }

    /* Peripheral clock enable */
    __HAL_RCC_FDCAN_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**FDCAN1 GPIO Configuration
    PB9     ------> FDCAN1_TX
    PB8     ------> FDCAN1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN FDCAN1_MspInit 1 */

  /* USER CODE END FDCAN1_MspInit 1 */
  }

}

/**
* @brief FDCAN MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hfdcan: FDCAN handle pointer
* @retval None
*/
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan)
{
  if(hfdcan->Instance==FDCAN1)
  {
  /* USER CODE BEGIN FDCAN1_MspDeInit 0 */

  /* USER CODE END FDCAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_FDCAN_CLK_DISABLE();

    /**FDCAN1 GPIO Configuration
    PB9     ------> FDCAN1_TX
    PB8     ------> FDCAN1_RX
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9|GPIO_PIN_8);

  /* USER CODE BEGIN FDCAN1_MspDeInit 1 */

  /* USER CODE END FDCAN1_MspDeInit 1 */
  }

}


uint8_t fdcan_init(uint16_t presc, uint8_t tsjw, uint16_t ntsg1, uint8_t ntsg2, uint32_t mode) 
{
    FDCAN_FilterTypeDef fdcan_filterconfig;

    HAL_FDCAN_DeInit(&g_fdcanx_handle);                              /* 先清除以前的设置 */
    g_fdcanx_handle.Instance = FDCAN1; 
    g_fdcanx_handle.Init.FrameFormat = FDCAN_FRAME_CLASSIC;          /* 传统模式 */
    g_fdcanx_handle.Init.Mode = mode;                                /* 模式设置  */
    g_fdcanx_handle.Init.AutoRetransmission = DISABLE;               /* 关闭自动重传!传统模式下一定要关闭!!!  */
    g_fdcanx_handle.Init.TransmitPause = DISABLE;                    /* 关闭传输暂停 */
    g_fdcanx_handle.Init.ProtocolException = DISABLE;                /* 关闭协议异常处理 */
    g_fdcanx_handle.Init.NominalPrescaler = presc;                   /* 分频系数 */
    g_fdcanx_handle.Init.NominalSyncJumpWidth = tsjw;                /* 重新同步跳跃宽度 */
    g_fdcanx_handle.Init.NominalTimeSeg1 = ntsg1;                    /* tsg1范围:2~256 */
    g_fdcanx_handle.Init.NominalTimeSeg2 = ntsg2;                    /* tsg2范围:2~128 */
    g_fdcanx_handle.Init.MessageRAMOffset = 0;                       /* 信息RAM偏移 */
    g_fdcanx_handle.Init.StdFiltersNbr = 0;                          /* 标准信息ID滤波器编号 */
    g_fdcanx_handle.Init.ExtFiltersNbr = 0;                          /* 扩展信息ID滤波器编号 */
    g_fdcanx_handle.Init.RxFifo0ElmtsNbr = 1;                        /* 接收FIFO0元素编号 */
    g_fdcanx_handle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;       /* 接收FIFO0元素大小:8字节 */
    g_fdcanx_handle.Init.RxBuffersNbr = 0;                           /* 接收FIFO0元素编号 */
    g_fdcanx_handle.Init.TxEventsNbr = 0;                            /* 发送事件编号 */
    g_fdcanx_handle.Init.TxBuffersNbr = 0;                           /* 发送缓冲编号 */
    g_fdcanx_handle.Init.TxFifoQueueElmtsNbr = 1;                    /* 发送FIFO序列元素编号 */
    g_fdcanx_handle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;  /* 发送FIFO序列模式 */
    g_fdcanx_handle.Init.TxElmtSize = FDCAN_DATA_BYTES_8;            /* 发送大小:8字节 */

    if (HAL_FDCAN_Init(&g_fdcanx_handle) != HAL_OK) 
    {
        return 1;   /* 初始化 */
    }

    fdcan_filterconfig.IdType = FDCAN_STANDARD_ID;                   /* 标准ID */
    fdcan_filterconfig.FilterIndex = 1;                              /* 滤波器索引 */
    fdcan_filterconfig.FilterType = FDCAN_FILTER_RANGE;//FDCAN_FILTER_MASK;               /* 滤波器类型 */
    fdcan_filterconfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;       /* 过滤器0关联到FIFO0 */
    fdcan_filterconfig.FilterID1 = 0x0321;                           /* 32位ID */
    fdcan_filterconfig.FilterID2 = 0x0322;                           /* 如果FDCAN配置为传统模式的话,这里是32位掩码 */
    
     /* 过滤器配置 */
    if (HAL_FDCAN_ConfigFilter(&g_fdcanx_handle, &fdcan_filterconfig) != HAL_OK) 
    {
        return 2;                                                    /* 滤波器初始化 */
    }

    HAL_FDCAN_Start(&g_fdcanx_handle);                               /* 开启FDCAN */
    HAL_FDCAN_ActivateNotification(&g_fdcanx_handle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);

    return 0;
}

uint8_t fdcan_send_msg(uint8_t *msg, uint32_t len)
{
    g_fdcanx_txheade.Identifier = 0x12;                              /* 32位ID */
    g_fdcanx_txheade.IdType = FDCAN_STANDARD_ID;                     /* 标准ID */
    g_fdcanx_txheade.TxFrameType = FDCAN_DATA_FRAME;                 /* 使用标准帧 */
    g_fdcanx_txheade.DataLength = len;                               /* 数据长度 */
    g_fdcanx_txheade.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    g_fdcanx_txheade.BitRateSwitch = FDCAN_BRS_OFF;                  /* 关闭速率切换 */
    g_fdcanx_txheade.FDFormat = FDCAN_CLASSIC_CAN;                   /* 传统的CAN模式 */
    g_fdcanx_txheade.TxEventFifoControl = FDCAN_NO_TX_EVENTS;        /* 无发送事件 */
    g_fdcanx_txheade.MessageMarker = 0;

    if (HAL_FDCAN_AddMessageToTxFifoQ(&g_fdcanx_handle, &g_fdcanx_txheade, msg) != HAL_OK) /* 发送消息 */
    {
        return 1;
    }

    return 0;
}

uint8_t fdcan_receive_msg(uint8_t *buf)
{
    if (HAL_FDCAN_GetRxMessage(&g_fdcanx_handle, FDCAN_RX_FIFO0, &g_fdcanx_rxheade, buf) != HAL_OK)   /* 接收数据 */
    {
        return 0;
    }

    return g_fdcanx_rxheade.DataLength>>16;
}

 

2.2、main.c

#include "main.h"
#include "usart/usart.h"
#include "led/led.h"
#include "sdram/sdram.h"
#include "lcd/dsi_lcd.h"
#include "key/key.h"
#include "fdcan/fdcan.h"

static void MPU_Config(void);
static void SystemClock_Config(void);
static void CPU_CACHE_Enable(void);
static void Error_Handler(void);

int main(void)
{
	uint8_t key_val=0;
	uint8_t fdcan_txdat[20];
	uint8_t fdcan_rxdat[20];
	uint8_t js=0;
  MPU_Config();
  CPU_CACHE_Enable();
  HAL_Init();
  SystemClock_Config();  /* Configure the system clock to 400 MHz */
	usart_init(115200);
	init_sdram();
	init_led();
	led1_on();
	init_key();
	init_lcd();
	fdcan_init(10, 8, 31, 8, FDCAN_MODE_NORMAL);             
	
	while(1)
	{
		js++;
		fdcan_txdat[0]=js;
		fdcan_txdat[1]=0x01;
		fdcan_send_msg(fdcan_txdat, FDCAN_DLC_BYTES_8);
		
		if(fdcan_receive_msg(fdcan_rxdat)!=0)
		{
			printf("rxdat: %2x %2x %2x %2x %2x %2x %2x %2x \r\n",fdcan_rxdat[0],fdcan_rxdat[1],fdcan_rxdat[2],fdcan_rxdat[3],\
																													 fdcan_rxdat[4],fdcan_rxdat[5],fdcan_rxdat[6],fdcan_rxdat[7]);
		}
		HAL_Delay(200);
	}
}

 

三、程序运行

 

3.1、CAN发送数据

003.png

 

3.2、CAN接收数据

004.png

 

本帖最后由 TL-LED 于 2024-1-3 11:04 编辑

回复评论 (1)

CAN接收数据正确测试就成功没啥说的

点赞  2024-1-4 07:29
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复