1、CUBEMAX配置:

时钟以及其他基础配置不在叙述,可以参考前面的文章STM32之CUBEMX及KEIL 5基础配置

主要看一下CAN的配置:

配置中断:

拓展一下时钟知识:CAN挂载在APB1总线上,STM32F103C8T6的APB1总线时钟频率为36MHz

2、程序代码:

定义CAN相关参数:

/* USER CODE BEGIN PTD */
/***************CAN相关参数******************************/
#define CAN_ID ((uint32_t)0x1314)
CAN_RxHeaderTypeDef CanRx;	//接收消息报文信息
CAN_TxHeaderTypeDef CanTx;	//发送消息报文信息
uint8_t RxData[8] = {0};	//接收数据区
uint8_t Flag_Rx = 0;		//接收到数据的标志
uint32_t pTxMailbox = 0;	//发送邮箱盒子
/* USER CODE END PTD */

CAN的基础配置:

/* USER CODE BEGIN PD */
HAL_StatusTypeDef Can_Config(void)
{
	CAN_FilterTypeDef sFilterConfig;

	CanTx.StdId = 0x00;
	CanTx.ExtId = CAN_ID;
	CanTx.IDE = CAN_ID_EXT;		//扩展帧模式
	CanTx.RTR = CAN_RTR_DATA;	//数据帧
	CanTx.DLC = 8;				//数据长度
	CanTx.TransmitGlobalTime = DISABLE;//时间戳

	sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;	//筛选器使能
	sFilterConfig.FilterBank = 0;						//筛选器0
	sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;//指定将分配给过滤器的FIFO(0或1U)。
	sFilterConfig.FilterIdHigh = ((CAN_ID<<3) & 0xFFFF0000)>>16;	//ID的高16位
	sFilterConfig.FilterIdLow = ((CAN_ID<<3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF;	//ID的低16位,过滤接收扩展帧模式、数据帧
	sFilterConfig.FilterMaskIdHigh = 0xFFFF;//高16位掩码,接收到的 ID 高 16 位与过滤器的 ID 高 16 位匹配时,消息才会通过;为0x0000时不做过滤
	sFilterConfig.FilterMaskIdLow = 0xFFFF;//低16位掩码,接收到的 ID 低 16 位与过滤器的 ID 低 16 位匹配时,消息才会通过;为0x0000时不做过滤
	sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;//掩码模式
	sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;//32位
	sFilterConfig.SlaveStartFilterBank = 0;

	if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
	{
		return HAL_ERROR;
	}

	if(HAL_CAN_Start(&hcan) != HAL_OK) //启动CAN
	{
		return HAL_ERROR;
	}

	if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)//激活CAN_IT_RX_FIFO0_MSG_PENDING中断
	{
		return HAL_ERROR;
	}

	return HAL_OK;
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)//报文接收中断
{
	if(HAL_CAN_GetRxMessage(hcan, CAN_FILTER_FIFO0, &CanRx, RxData) == HAL_OK)
	{
		Flag_Rx = 1;
	}

}
/* USER CODE END PD */

MAIN函数中初始化:

  /* USER CODE BEGIN 2 */
  Can_Config();//CAN初始化
  /* USER CODE END 2 */

循环中,配置CAN测试函数,接收到什么数据,就发送什么数据:

  while (1)
  {
	  if(Flag_Rx)//CAN标志位
	  {
		  Flag_Rx = 0;
		  if(HAL_CAN_AddTxMessage(&hcan, &CanTx, RxData, &pTxMailbox) != HAL_OK)
		  {
			  printf("Tx Fail\r\n");
		  }
		  memset(U2RxBuf, 0, 8);
	   }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

3、上位机测试:

使用cangaroo上位机

选择需要的波特率和采样点:点击ok,板载三色灯会亮起,可以发送和接受CAN总线上的数据

数据收发测试图

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐