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);
}
相关推荐
可待电子单片机设计定制(论文)2 小时前
【STM32设计】数控直流稳压电源的设计与实现(实物+资料+论文)
stm32·嵌入式硬件·mongodb
march_birds2 小时前
FreeRTOS 与 RT-Thread 事件组对比分析
c语言·单片机·算法·系统架构
小麦嵌入式3 小时前
Linux驱动开发实战(十一):GPIO子系统深度解析与RGB LED驱动实践
linux·c语言·驱动开发·stm32·嵌入式硬件·物联网·ubuntu
触角010100014 小时前
STM32F103低功耗模式深度解析:从理论到应用实践(上) | 零基础入门STM32第九十二步
驱动开发·stm32·单片机·嵌入式硬件·物联网
昊虹AI笔记4 小时前
使用STM32CubeMX和Keil在STM32上创建并运行一个简单的FreeRTOS多任务程序
stm32·单片机·嵌入式硬件
王光环5 小时前
单片机使用printf,不用微库
单片机·嵌入式硬件
LS_learner5 小时前
小智机器人关键函数解析,Application::OutputAudio()处理音频数据的输出的函数
人工智能·嵌入式硬件
西城微科方案开发6 小时前
体重秤PCBA电路方案组成结构
单片机·嵌入式硬件
深圳市青牛科技实业有限公司6 小时前
「青牛科技 」GC4931P/4938/4939 12-24V三相有感电机驱动芯片 对标Allegro A4931/瑞盟MS4931
科技·单片机·扫地机器人吸尘·筋膜枪电机·驱动轮电机·服务机器人驱动轮电机·工业机器人减速电机
集和诚JHCTECH6 小时前
集和诚携手Intel重磅发布BRAV-7820边缘计算新品,为车路云一体化场景提供强大算力支撑
人工智能·嵌入式硬件·边缘计算