STM32CubeIDE(CAN)

目录

一、概念

1、简述

[2、CAN 的几种模式](#2、CAN 的几种模式)

二、实践

1、环回模式轮询通信

[1.1 软件配置](#1.1 软件配置)

[1.2 代码编写](#1.2 代码编写)

2、环回模式中断通信

[2.1 软件配置](#2.1 软件配置)

[2.2 代码编写](#2.2 代码编写)


一、概念

1、简述

STM32微控制器系列包含多个型号,其中一些型号集成了CAN(Controller Area Network)控制器,使其可以直接通过硬件接口实现CAN通信。CAN总线是一种多主总线,用于实时应用,例如在汽车、工业自动化和医疗设备中进行数据通信。

2、CAN 的几种模式

CAN(Controller Area Network)通信支持几种不同的操作模式,这些模式主要设计用于系统初始化、调试、故障检测和网络管理。

1. 正常模式(Normal Mode): 这是最常见的模式,在这种模式下,CAN节点可以发送和接收数据。所有的CAN功能都是可用的,节点可以参与总线上的数据交换,包括数据帧和远程帧的发送与接收。这是CAN总线在日常操作中最常用的模式。

2. 环回模式(Loopback Mode): 在环回模式下,节点发送的数据会被立即重定向回到同一节点的接收器。这意味着节点可以发送一个数据帧,并立即在同一节点上接收该帧,而不将其发送到总线上。这种模式主要用于测试CAN硬件和软件的正确性,因为它允许开发者检查发送的数据是否与接收的数据一致,而无需其他网络节点的参与。

3. 静默模式(Silent Mode): 在静默模式下,节点可以接收数据,但是不会向总线发送任何数据。这意味着即使在检测到总线上的数据帧或远程帧时,节点也不会进行应答或发送任何数据。静默模式通常用于监控网络活动,而不干扰网络通信。例如,在进行故障诊断时,工程师可能只想观察网络上的数据流,而不是影响它们。

4.静默环回模式(Silent Loopback Mode):它结合了静默模式和环回模式的特点,即节点既不会向总线发送数据,同时也会将发送的数据在内部进行环回,用于更细致的测试和调试目的。

二、实践

1、环回模式轮询通信

1.1 软件配置

1.2 代码编写

cpp 复制代码
	if(CAN_SetFilters()==HAL_OK)
	{
		printf("ID Filter: Only Odd IDs \r\n");
	}
	if(HAL_CAN_Start(&hcan1)==HAL_OK)
	{
		printf("CAN is start \r\n");
	}
	uint8_t msgID=1;
  while (1)
  {
  	//CAN_TestPoll(msgID++,CAN_RTR_DATA);//数据帧
  	//printf("\r\n \r\n");
  	HAL_Delay(2000);
  	CAN_TestPoll(msgID++,CAN_RTR_REMOTE);//遥控帧
  	printf("\r\n \r\n");
  }
cpp 复制代码
HAL_StatusTypeDef CAN_SetFilters()
{
	CAN_FilterTypeDef canFilter;
	canFilter.FilterBank=0;
	canFilter.FilterMode=CAN_FILTERMODE_IDMASK;
	canFilter.FilterScale=CAN_FILTERSCALE_32BIT;

	canFilter.FilterIdHigh =0x0020;
	canFilter.FilterIdLow = 0x0000;
	canFilter.FilterMaskIdHigh = 0x0020;
	canFilter.FilterMaskIdLow = 0x0000;

	canFilter.FilterFIFOAssignment=CAN_FILTER_FIFO0;
	canFilter.FilterActivation = CAN_FILTER_ENABLE;
	canFilter.SlaveStartFilterBank = 14;

	HAL_StatusTypeDef result = HAL_CAN_ConfigFilter(&hcan1, &canFilter);
	return result;
}

void CAN_TestPoll(uint8_t msgID, uint8_t frameType)
{
	uint8_t txData[8];
	txData[0]=msgID;
	txData[1]=msgID+11;

	CAN_TxHeaderTypeDef TxHeader;
	TxHeader.StdId=msgID;
	TxHeader.RTR=frameType;
	TxHeader.IDE=CAN_ID_STD;
	TxHeader.DLC = 2;
	TxHeader.TransmitGlobalTime =DISABLE;

	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)<1){}

	uint32_t TxMailbox;
	if(HAL_CAN_AddTxMessage(&hcan1, &TxHeader, txData, &TxMailbox)!=HAL_OK)
	{
		printf("Send to mailbox error \r\n");
		return ;
	}

	//uint8_t tempStr[30];
	printf("Send MsgID= %d \r\n",msgID);
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)!=3){}

	//轮询方式接收消息
	HAL_Delay(1);
	if(HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0)!=1)
	{
		printf("Message is not received \r\n");
		return ;
	}
	printf("Message is received \r\n");

	CAN_RxHeaderTypeDef RxHeader;
	uint8_t RxData[8];
	if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData)==HAL_OK)
	{
		printf("StdID=%ld \r\n",RxHeader.StdId);
		printf("RTR(0=Data,2=Remote)=%ld \r\n",RxHeader.RTR);
		printf("IDE(0=Std,4=Ext)=%ld \r\n",RxHeader.IDE);
		printf("DLC(Data Length)=%ld \r\n",RxHeader.DLC);

		if(TxHeader.RTR == CAN_RTR_DATA)
		{
			printf("Data[0] = %d \r\n",RxData[0]);
			printf("Data[1] = %d \r\n",RxData[1]);
		}
	}
}

2、环回模式中断通信

2.1 软件配置

2.2 代码编写

cpp 复制代码
	if(CAN_SetFilters()==HAL_OK)
	{
		printf("ID Filter: Only Odd IDs \r\n");
	}
	if(HAL_CAN_Start(&hcan1)==HAL_OK)
	{
		printf("CAN is start \r\n");
	}
	uint8_t msgID=1;
	__HAL_CAN_ENABLE_IT(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);//使能接收中断
	__HAL_CAN_ENABLE_IT(&hcan1,CAN_IT_RX_FIFO1_MSG_PENDING);
  while (1)
  {
  	  CAN_SendMsg(msgID++,CAN_RTR_DATA);
  	  HAL_Delay(1000);
  	  printf("\r\n \r\n");
  }
cpp 复制代码
HAL_StatusTypeDef CAN_SetFilters()
{
	CAN_FilterTypeDef canFilter;
	//设置FIFO0的筛选器
	canFilter.FilterBank=0;
	canFilter.FilterMode=CAN_FILTERMODE_IDMASK;
	canFilter.FilterScale=CAN_FILTERSCALE_32BIT;
	canFilter.FilterIdHigh =0x0020;
	canFilter.FilterIdLow = 0x0000;
	canFilter.FilterMaskIdHigh = 0x0020;
	canFilter.FilterMaskIdLow = 0x0000;
	canFilter.FilterFIFOAssignment=CAN_FILTER_FIFO0;
	canFilter.FilterActivation = CAN_FILTER_ENABLE;
	canFilter.SlaveStartFilterBank = 14;
	HAL_StatusTypeDef result = HAL_CAN_ConfigFilter(&hcan1, &canFilter);
	if(result!=HAL_OK)
	{
		return result;
	}
	//设置FIFO1的筛选器
	canFilter.FilterBank=1;
	canFilter.FilterIdHigh =0x0000;
	canFilter.FilterIdLow = 0x0000;
	canFilter.FilterMaskIdHigh = 0x0000;
	canFilter.FilterMaskIdLow = 0x0000;
	canFilter.FilterFIFOAssignment=CAN_FILTER_FIFO1;
	result = HAL_CAN_ConfigFilter(&hcan1, &canFilter);
	return result;
}
void CAN_SendMsg(uint8_t msgID, uint8_t frameType)
{
	CAN_TxHeaderTypeDef TxHeader;
	TxHeader.StdId=msgID;
	TxHeader.RTR=frameType;
	TxHeader.IDE=CAN_ID_STD;
	TxHeader.DLC = 4;
	TxHeader.TransmitGlobalTime =DISABLE;
	uint32_t random32bit;
	HAL_RNG_GenerateRandomNumber(&hrng,&random32bit);
	uint8_t txData[8];
	txData[0]= random32bit & 0x000000FF;
	txData[1]=(random32bit & 0x0000FF00)>>8;
	txData[2]=(random32bit & 0x00FF0000)>>16;
	txData[3]=(random32bit & 0xFF000000)>>24;
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)<1){}
	printf("Send MsgID = %d \r\n",msgID);
	uint32_t TxMailbox;
	if(HAL_CAN_AddTxMessage(&hcan1, &TxHeader, txData, &TxMailbox)!=HAL_OK)
	{
		printf("Send to mailbox error \r\n");
		return ;
	}
}
void CAN_ReadMsg(uint32_t FIFO_num)
{
	CAN_RxHeaderTypeDef RxHeader;
	uint8_t RxData[8];
	if(FIFO_num == CAN_RX_FIFO0)
	{
		printf("Message received by FIFO0 \r\n");
		if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData)!=HAL_OK)
		{
			printf("Read FIFO0 error \r\n");
			return ;
		}
	}
	else if(FIFO_num == CAN_RX_FIFO1)
	{
		printf("Message received by FIFO1 \r\n");
		if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO1, &RxHeader, RxData)!=HAL_OK)
		{
			printf("Read FIFO1 error \r\n");
			return ;
		}
	}
	printf("StdID=%ld \r\n",RxHeader.StdId);
	printf("RTR(0=Data,2=Remote)=%ld \r\n",RxHeader.RTR);
	printf("IDE(0=Std,4=Ext)=%ld \r\n",RxHeader.IDE);
	printf("DLC(Data Length)=%ld \r\n",RxHeader.DLC);
	printf("Data = %02X %02X %02X %02X \r\n",RxData[0],RxData[1],RxData[2],RxData[3]);
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	CAN_ReadMsg(CAN_RX_FIFO0);
}

void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	CAN_ReadMsg(CAN_RX_FIFO1);
}
相关推荐
redcocal10 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
辰哥单片机设计13 小时前
门磁模块详解(防盗感应开关 STM32)
stm32·单片机·嵌入式硬件·传感器
夜间去看海13 小时前
基于51单片机的自动清洗系统(自动洗衣机)
嵌入式硬件·51单片机·proteus·洗衣机
yrx02030714 小时前
stm32 IIC总线busy解决方法
stm32·单片机·嵌入式硬件
YHPsophie15 小时前
ATGM331C-5T杭州中科微BDS/GNSS全星座定位授时模块应用领域
经验分享·笔记·单片机·信息与通信·交通物流
Archie_IT16 小时前
【STM32系统】基于STM32设计的SD卡数据读取与上位机显示系统(SDIO接口驱动、雷龙SD卡)——文末资料下载
arm开发·stm32·单片机·嵌入式硬件
辰哥单片机设计16 小时前
1×4矩阵键盘详解(STM32)
stm32·单片机·嵌入式硬件·矩阵·传感器
wmkswd16 小时前
CAN总线-STM32上CAN外设
stm32·单片机·嵌入式硬件
Ruohongxu16 小时前
LAN8720A-CP-TR-ABC QFN-24 以太网收发器芯片
单片机