STM32CubeIDE——CAN中断接收、阻塞发送

目录

一、CAN模块配置流程

1.1 图形化界面设置can的波特率和相关工作模式

1.2 代码设置can的滤波器和中断

二、代码详解

2.1 CAN信息发送函数

2.2 CAN信息接收函数

2.3 main()函数

2.4 CAN接收回调函数

三、 总结


硬件条件:带有CAN总线接口的STM32开发板/工控板。

实现功能:

  1. stm32轮询发送can信息(数据帧、标准帧);
  2. stm32在中断回调中接收刚刚自己发出的can信息。

本文默认读者已经有了如下的基本知识和技能:

  • 对can协议和stm32的bxCAN有了一定的了解,如Time Quantum、四种工作模式、过滤器及其配置参数的意义等;
  • 会在stm32cubeide中图形化配置芯片的调试串口、时钟和代码自动生成。

下面直接开始工程(工程中只讲述与can有关的地方)。

一、CAN模块配置流程

本文以STM32F103C8T6芯片为例。

STM32中CAN的配置分为两大部分:图形化界面设置can的波特率、相关工作模式和中断优先级;代码设置can的滤波器和使能FIFO中断。现具体讲述着两大部分。

1.1 图形化界面设置can的波特率和相关工作模式

  1. 首先,使能can模块;
  2. 接着调整“Prescaler(for Time Quantum)”参数、“Time Quanta in Bit Segment 1”参数和“Time Quanta in Bit Segment 2”参数,使得波特率Baud Rate达到合适的值;
  3. 然后在Operating Mode选项中选择回环模式(当然工作模式的选择要看具体应用了);
  4. 之后,“Parameter Settings”页面里剩下的其它参数,如果没有什么特殊需求的话,保持默认就可以了。见图1-1。
图1-1

     5. 进入"NVIC Settings"中勾选RX0的中断使能,如图1-2;并在软件左侧NVIC栏里设置它的中断优先级,如图1-3。

图1-2

  

图1-3

     6. 到这里,图形化页面里能配置的都配置完了。当然,can滤波器的配置还没有进行,这是在下一个部分里。

1.2 代码设置can的滤波器和中断

在软件自动生成的代码里找到can.c文件,这里面是工程对can配置的部分信息,与刚才图形化界面里我们的配置信息保持一致。

图个方便,我们直接在void MX_CAN_Init(void)函数里添加上滤波器的配置并使能对应的接收FIFO中断,如图1-3。这里别忘了在该函数外面定义需要的结构体变量!!!

图1-3

到此,can的配置全部OK。

现在只需要在main()里调用函数HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan),就可以开启can使它工作了。

二、代码详解

2.1 CAN信息发送函数

要想can发送信息,需要用到函数:HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox),我在这里把它进行再封装一下,变得更好用:

CAN_TxHeaderTypeDef Tx_pHeader;
/*
 * @brief: CAN Send Message.
 * @param: "TxData[]" stored the message of ready to send, which length must between 0 and 8.
 * @param: "length" stored the number of the data (one data is 8 bit) of ready to send.
 * @retval: Tx_Error: send error; other: the mailbox which has been used, this parameter can be a CAN_TX_MAILBOX0,
 * 																						   CAN_TX_MAILBOX1,
 * 																						   CAN_TX_MAILBOX2.
 */
uint32_t CAN_TX_Message(uint8_t TxData[], uint8_t length)
{

	uint32_t TxMailboxNumber = 0x00000000U;    // 存储本次发送所使用邮箱的邮箱号

	Tx_pHeader.StdId = 0x000;    // 以此ID发送
	Tx_pHeader.ExtId = 0x0000;    // 扩展ID(此处无用)
	Tx_pHeader.IDE = CAN_ID_STD;    // 标准帧
	Tx_pHeader.RTR = CAN_RTR_DATA;    // 数据帧
	Tx_pHeader.DLC = length;    // 发送数据的长度
	Tx_pHeader.TransmitGlobalTime = DISABLE;

	if(HAL_CAN_AddTxMessage(&hcan, &Tx_pHeader, TxData, &TxMailboxNumber) != HAL_OK)
	{
		return Tx_Error;
	}
	return TxMailboxNumber;
}

2.2 CAN信息接收函数

同样,接受can上的信息,需要用到函数:HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]),我也对其进行再封装:


CAN_RxHeaderTypeDef Rx_pHeader;
/*
 * @brief: CAN Receive Message.
 * @param: "RxData[]" will store the message which has been received, which length must between 0 and 8.
 * @retval: receive status.
 */
uint32_t CAN_RX_Message(uint8_t RxData[])
{

	uint8_t aData[8];    // 缓存接收到的信息

	Rx_pHeader.StdId = 0x000;	// 接收ID(此处无用,can接收所有的ID号)
	Rx_pHeader.ExtId = 0x0000;
	Rx_pHeader.IDE = CAN_ID_STD;	// 接收标准帧
	Rx_pHeader.DLC = 8;		// 接收8个8bit数据
	Rx_pHeader.RTR = CAN_RTR_DATA;	// 接收数据帧
	Rx_pHeader.FilterMatchIndex = 0;	// 使用0号过滤器
	Rx_pHeader.Timestamp = 0;

	if(HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &Rx_pHeader, aData) != HAL_OK)
	{
		return Rx_Error;
	}
	else
	{
		// 取出接收到的信息
		for(uint8_t i = 0; i<Rx_pHeader.DLC; i++)
		{
			RxData[i] = aData[i];
		}
		return Rx_OK;
	}
}

2.3 main()函数

/* USER CODE BEGIN PV */
uint8_t TxData[8] = {0};    // 缓存待发送的信息
uint8_t length = 0x00;    // 待发送信息的长度
/* USER CODE END PV */

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();
  /* USER CODE BEGIN 2 */
  TxData[7] = 0x1a;    // 给定待发送的信息
  TxData[6] = 0x1b;
  TxData[5] = 0x1c;
  TxData[4] = 0x1d;
  TxData[3] = 0x1e;
  TxData[2] = 0x1f;
  TxData[1] = 0x10;
  TxData[0] = 0x11;
  length = 0x08;    // 更新待发送信息的数据长度
  if (HAL_CAN_Start(&hcan) != HAL_OK)    // 开启CAN
  {
	  Error_Handler();
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if (CAN_TX_Message(TxData, length) == Tx_Error)    // 轮询方式发送CAN信息
	  {
		  Error_Handler();
	  }
	  HAL_Delay(500);    // 延时0.5s
  }
  /* USER CODE END 3 */
}

2.4 CAN接收回调函数

回调函数是中断后执行的用户函数,can的回调函数有多个。想知道can每一个回调函数的信息,请到最后一章中找答案。

因为之前在滤波器中配置使用FIFO0进行接收信息,所以这里一定要用FIFO0对应的回调函数:

/* USER CODE BEGIN PV */
uint8_t RxData[8] = {0};    // 缓存接收到的信息
/* USER CODE END PV */

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    // 判断是哪一路的CAN发生了中断
	if(hcan->Instance == CAN1)
	{
		if(CAN_RX_Message(RxData) != Rx_OK)
		{
            // 接收信息失败
			printf("MCU Received CAN Data ERROR!!!");
            printf("\n\r");
			printf("\n\r");
		}
		else
		{
            // 接受信息成功,处理数据
			printf("MCU Received CAN Data: ");
			for(uint8_t i = 0; i<8; i++)
			{
				printf("%d ", RxData[i]);
			}
            printf("\n\r");
			printf("\n\r");
		}
	}
}

三、 总结

stm32的can配置和使用流程在stm32cubeide软件中是这样的:

  1. ioc文件里图形化使能can并配置其波特率、工作模式、中断优先级;
  2. 自动生成代码后,在can.c文件里添加滤波器的配置并使能FIFO中断;
  3. 在main.c文件下的main()里先启动can,然后发送信息;
  4. 在main.c文件下的main()外用户自定义中断回调函数。

我遇到的错误点总结:

  1. 没有启动can,can是发不出信息、接收不到信息的。——阅读了stm32f1xx_hal_can.c文件中对can外设的说明,发现了该问题并解决。
  2. 没有使能FIFO中断,can是不会中断的。——用中断回调函数控制LED亮灭,并进行全速调试,发现了该问题并解决。
  3. 回调函数的函数名使用错误(因为有多个用途不同的函数名),can中断后无事发生。——通过软件的单步调试,发现了该问题并解决。

所有与can相关的函数,它们的功能,传递参数的含义、类型、取值,返回值等;所有与can相关的结构体,它们的定义,成员变量的含义、类型、取值等,或是其它更多的信息。这些请自行在工程里的这两个文件中进行查阅:

  • 30
    点赞
  • 149
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
Stm32CubeIDE是一款由ST微电子公司开发的集成开发环境(IDE),用于开发基于ST微电子的STM32单片机系列产品。该软件提供了丰富的工具和功能,方便开发人员进行嵌入式软件开发。 STM32CubeIDE 103 CAN是指在STM32CubeIDE软件中进行CAN总线相关开发。CAN(Controller Area Network)是一种常用的实时通信协议,广泛应用于汽车、工业控制以及其他需要高可靠性和实时性的领域。 在STM32CubeIDE 103 CAN中,开发人员可以使用软件提供的CAN相关库函数和API,快速编写CAN通信程序。通过这些库函数和API,开发人员可以方便地实现CAN消息的发送接收,设置CAN帧的参数和标识符等。 在进行CAN开发时,需先在STM32CubeMX软件中进行硬件配置,选择要使用的CAN通道,并设置相应的参数。然后,在STM32CubeIDE中创建一个新的工程,并选择相应的板级支持包和库文件。 在编写代码时,可以使用STM32CubeIDE提供的Code Generator工具,自动生成CAN相关的初始化代码和处理函数。然后,根据实际需求,进行自定义的修改和编写。 在完成代码编写后,可以使用STM32CubeIDE提供的调试工具,如更断点、观察表等,对代码进行调试和测试。最后,将代码下载到目标设备上运行,进行实际的CAN通信测试和验证。 总之,通过STM32CubeIDE 103 CAN,开发人员可以在方便和高效的开发环境中进行CAN总线相关的开发,快速实现嵌入式CAN通信功能。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觅道無涯-千知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值