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);
}
相关推荐
Wallace Zhang3 小时前
STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader
stm32·嵌入式硬件·安全
GodKK老神灭4 小时前
STM32 CCR寄存器
stm32·单片机·嵌入式硬件
杰克逊的日记9 天前
MCU编程
单片机·嵌入式硬件
Python小老六9 天前
单片机测ntc热敏电阻的几种方法(软件)
数据库·单片机·嵌入式硬件
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
HX科技10 天前
STM32给FPGA的外挂FLASH进行升级
stm32·嵌入式硬件·fpga开发·flash·fpga升级
Suagrhaha10 天前
驱动入门的进一步深入
linux·嵌入式硬件·驱动
国科安芯10 天前
基于ASP4644多通道降压技术在电力监测系统中集成应用与发展前景
嵌入式硬件·硬件架构·硬件工程
Li Zi10 天前
STM32 ADC(DMA)双缓冲采集+串口USART(DMA)直接传输12位原始数据到上位机显示并保存WAV格式音频文件 收藏住绝对实用!!!
经验分享·stm32·单片机·嵌入式硬件
进击的程序汪10 天前
触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报
linux·网络·嵌入式硬件