STM32-HAL库09-CAN通讯(loopback模式)

一、所用材料:

STM32F103C6T6最小系统板
STM32CUBEMX(HAL库软件)
MDK5
串口调试助手

二、所学内容:

初步学习如何使用STM32的CAN通讯功能,在本章节主要达到板内CAN通讯的效果,即32发送CAN信息再在CAN接收中断中用串口打印出来。

三、CUBEMX配置:

第一步:老三件套-RCC,SYS,时钟树配置



第二步:串口配置

第三步:CAN配置

关键步骤:

  • 波特率设置:1M bit/s,具体配置如下图
  • TEST MODE - Loopback
  • 打开接收中断RX0

四、MDK5配置:

一、can.h头文件配置

c 复制代码
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __CAN_H__
#define __CAN_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern CAN_HandleTypeDef hcan;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_CAN_Init(void);

/* USER CODE BEGIN Prototypes */
void CANFilter_Config(void);
void CAN1_Send_Test(void);
void CAN_Start_Init(void);
void CAN1_Send(uint8_t* cdata);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __CAN_H__ */

二、can.c源文件配置

c 复制代码
/* Includes ------------------------------------------------------------------*/
#include "can.h"

/* USER CODE BEGIN 0 */
#include "stdio.h"
#include "usart.h"
#include "main.h"
static CAN_TxHeaderTypeDef TxMessage; //CAN发送的消息的消息头
static CAN_RxHeaderTypeDef RxMessage; //CAN接收的消息的消息头
/* USER CODE END 0 */

CAN_HandleTypeDef hcan;

/* CAN init function */
void MX_CAN_Init(void)
{
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 4;
  hcan.Init.Mode = CAN_MODE_LOOPBACK;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_5TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_3TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = DISABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */

  /* USER CODE END CAN_Init 2 */

}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**CAN GPIO Configuration
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* CAN1 interrupt Init */
    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{

  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspDeInit 0 */

  /* USER CODE END CAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_CAN1_CLK_DISABLE();

    /**CAN GPIO Configuration
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);

    /* CAN1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
/*******************
接受信息过滤器
*******************/
 void CANFilter_Config(void)
{
    CAN_FilterTypeDef  sFilterConfig;
    
    sFilterConfig.FilterBank = 0;                       //CAN过滤器编号,范围0-27
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //CAN过滤器模式,掩码模式或列表模式
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //CAN过滤器尺度,16位或32位
    sFilterConfig.FilterIdHigh = 0x000 << 5;			//32位下,存储要过滤ID的高16位
    sFilterConfig.FilterIdLow = 0x0000;					//32位下,存储要过滤ID的低16位
    sFilterConfig.FilterMaskIdHigh = 0x0000;			//掩码模式下,存储的是掩码
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterFIFOAssignment = 0;				//报文通过过滤器的匹配后,存储到哪个FIFO
    sFilterConfig.FilterActivation = ENABLE;    		//激活过滤器
    sFilterConfig.SlaveStartFilterBank = 0;
    
    if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) 
		 {
        Error_Handler();
       }
	else{ printf("HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) is HAL_OK\r\n"); }
}
/*******************
中断接受
*******************/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{

    uint8_t  data[8];
    HAL_StatusTypeDef	status;
    status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);
    if (HAL_OK == status)
	{    
		printf("--->Data Receieve!\r\n");
		printf("RxMessage.StdId is %#x\r\n",  RxMessage.StdId);
		printf("data[0] is 0x%02x\r\n", data[0]);
		printf("data[1] is 0x%02x\r\n", data[1]);
		printf("data[2] is 0x%02x\r\n", data[2]);
		printf("data[3] is 0x%02x\r\n", data[3]);
		printf("data[4] is 0x%02x\r\n", data[4]);
		printf("data[5] is 0x%02x\r\n", data[5]);
		printf("data[6] is 0x%02x\r\n", data[6]);
		printf("data[7] is 0x%02x\r\n", data[7]);		
		printf("<---\r\n");   
	    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);		
    }
}

/*******************
发送函数
*******************/
void CAN1_Send_Test(void)
{
    uint32_t TxMailbox;
    uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};
    TxMessage.IDE = CAN_ID_STD;     //设置ID类型
	 TxMessage.StdId = 0x111;        //设置ID号
    TxMessage.RTR = CAN_RTR_DATA;   //设置传送数据帧
	 TxMessage.DLC = 4;              //设置数据长度
	if (HAL_CAN_AddTxMessage(&hcan, &TxMessage, data, &TxMailbox) != HAL_OK)
		{
        Error_Handler();
     }	
	// else{ printf("HAL_CAN_AddTxMessage(&hcan, &TxMessage, data, &TxMailbox) is HAL_OK\r\n"); }
}

void CAN1_Send(uint8_t* cdata)
{
    uint32_t TxMailbox;
    TxMessage.IDE = CAN_ID_STD;     //设置ID类型
	TxMessage.StdId = 0x111;        //设置ID号
    TxMessage.RTR = CAN_RTR_DATA;   //设置传送数据帧
	TxMessage.DLC = 8;              //设置数据长度	
	if (HAL_CAN_AddTxMessage(&hcan, &TxMessage, cdata, &TxMailbox) != HAL_OK)
	{
        Error_Handler();
    }		
}
/*******************
CAN启动函数
*******************/
void CAN_Start_Init(void)
{
  if (HAL_CAN_Start(&hcan) != HAL_OK) 
    {
        Error_Handler();
     }
  else{ printf("HAL_CAN_Start(&hcan) is HAL_OK\r\n"); }
    
    /* 3. Enable CAN RX Interrupt */
    if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) !=  HAL_OK) {
        Error_Handler();
    }
  else{ printf("HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) is HAL_OK\r\n"); }	
}
/* USER CODE END 1 */

三、main.c文件配置

c 复制代码
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();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  CANFilter_Config();
  CAN_Start_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  CAN1_Send_Test();
	  HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

四、串口打印结果:

五、本文对应代码分享:

https://download.csdn.net/download/qq_45854134/88522530

相关推荐
Zhao136824553913 小时前
DP4330A 与DP4363 测试对比
嵌入式硬件
辛迪聊物业数字化3 小时前
智慧社区小程序落地避坑指南:3类物业方案选型+成本测算,线上服务零翻车
大数据·嵌入式硬件·百度·系统架构
电子科技圈4 小时前
Arm电机控制开发工具哪家强?
arm开发·单片机·嵌入式硬件·设计模式·软件构建
JasmineX-14 小时前
下位机直接控制57步进电机匀速转动
stm32·单片机·嵌入式硬件
聆思科技AI芯片4 小时前
【AI硬件开发上手教程】怎么使用AI编程实现小聆AI语音控制舵机
人工智能·嵌入式硬件·开源·ai编程·智能硬件
abc light5 小时前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
吠品14 小时前
智谱开源 ZCode 之后,真正的考试才开始
单片机·嵌入式硬件·1024程序员节
Chery114016 小时前
高速ADC与精密DAC怎么选?DP9230D与DP8532D应用解析
嵌入式硬件·物联网·射频工程
小李不想当小白19 小时前
SPI通信外设与W25Q64 (硬件SPI)(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
LCG米19 小时前
STM32驱动W5500以太网模块实测:TCP吞吐瓶颈定位、TX指针回绕陷阱与断线重连保活落地
stm32·单片机·嵌入式硬件·tcp/ip