STM32CubeMX工程配置——STM32F103C8T6 CAN通信

一、STM32CubeMX工程配置
二、代码

板子芯片是STM32F103C8T6 

一、STM32CubeMX工程配置

1.配置SYS:选择烧录方式和定时的时钟源

2.选择晶振作为时钟源,IWDG可以不设置

3.配置时钟,我板子用的是8M晶振 

4.激活CAN,设置500K波特率

5.使能CAN接收中断

二、代码

1.can.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    can.c
  * @brief   This file provides code for the configuration
  *          of the CAN instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "can.h"

/* USER CODE BEGIN 0 */
/** 新增 ************/
#include "usart.h"

extern CAN_TxHeaderTypeDef Can_Tx;
extern uint8_t Txdata[8];
extern CAN_HandleTypeDef hcan;
/*******************************************************************************/ 
uint8_t can_recieve_flag = 0;
uint8_t can_recieve = 0;
CAN_TxHeaderTypeDef       			  Can_Tx;    //CAN发送的消息的消息头
static CAN_RxHeaderTypeDef        Can_Rx;    //CAN接收的消息的消息头

uint8_t Rxdata[8];													 //CAN接收缓冲区
uint8_t Txdata[8] = {0x45,0x22,0x33};				 //CAN发送缓冲区
/******************************************************************************/ 

/* USER CODE END 0 */

CAN_HandleTypeDef hcan;

/* CAN init function */
void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */

  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 9;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_3TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_4TQ;
  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(CAN1_RX1_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX1_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(CAN1_RX1_IRQn);
  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
/** 新增 ************/
/**
  ******************************************************************************
  * @brief  CAN_User_Init
  * @param  hcan 
  * @return None
  * @note  
  ******************************************************************************
  */
void CAN_User_Init(CAN_HandleTypeDef* hcan )   //用户初始化函数
{
  CAN_FilterTypeDef  sFilterConfig;
  HAL_StatusTypeDef  HAL_Status;
  sFilterConfig.FilterActivation = ENABLE;  	//激活过滤器
  sFilterConfig.FilterBank = 1;                       //过滤器1
  sFilterConfig.FilterMode =  CAN_FILTERMODE_IDMASK;  //设为掩码模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;    //设为32位
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;    //接收到的报文放入到FIFO0中
  sFilterConfig.FilterIdHigh = 0;   //基本ID放入到STID中// 0x000 << 5;			//32位下,存储要过滤ID的高16位
  sFilterConfig.FilterIdLow  = 0;
  sFilterConfig.FilterMaskIdHigh =0;
  sFilterConfig.FilterMaskIdLow  =0;
  sFilterConfig.SlaveStartFilterBank  = 0;
 
  HAL_Status=HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
  HAL_Status=HAL_CAN_Start(hcan);  //开启CAN
 
  if(HAL_Status!=HAL_OK)
		{
			//	printf("开启CAN失败\r\n");
		}
  HAL_Status=HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
  if(HAL_Status!=HAL_OK)
	 {
	//printf("开启挂起中段允许失败\r\n");
  }
}
/**
  ******************************************************************************
  * @brief  sendOrder 发送命令函数
	* @paramStdId 			标准帧ID
	* @paramExtId 			扩展帧ID  当标志位 IDE为CAN_ID_STD时 扩展帧无效
	* @paramIDE 				扩展帧标志位  CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
	* @paramRTR  			0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
	* @paramDLC  			数据长度
  * @return None
  * @note  
  ******************************************************************************
  */

void sendOrder(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC)
{
	uint32_t pTxMailbox = 0;
 
	Can_Tx.StdId = StdId;//标准ID
	Can_Tx.ExtId = ExtId;//扩展ID
	Can_Tx.IDE = IDE;//CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
	Can_Tx.RTR = RTR;					//0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
	Can_Tx.DLC = DLC;					//数据长度
	HAL_CAN_AddTxMessage(&hcan,&Can_Tx,Txdata,&pTxMailbox);
 
}
/**
  ******************************************************************************
  * @brief  sendOrder 	发送消息函数
	* @param  StdId 			标准帧ID
	* @param  ExtId 			扩展帧ID  当标志位 IDE为CAN_ID_STD时 扩展帧无效
	* @param  IDE 				扩展帧标志位  CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
	* @param  RTR  			0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
	* @param  DLC  			数据长度
	* @param  data 			发送的数据
  * @return None
  * @note  
  ******************************************************************************
  */
void sendmessage(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC,float send_data)
{
	uint32_t pTxMailbox = 0;
	Can_Tx.StdId = StdId;//标准ID
	Can_Tx.ExtId = ExtId;//扩展ID
	Can_Tx.IDE = IDE;//CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
	Can_Tx.RTR = RTR;					//0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
	Can_Tx.DLC = DLC;					//数据长度
																/* 将浮点数转化成4个字节存在tdata[4]----tdata[7]中 */
	send_data=send_data*100;
		Txdata[4] = (int)send_data&0x00ff;
		Txdata[3] = (int)send_data>>8;
		Txdata[1] = 0x01;
		printf("TX ID:0x%X\r\n",Can_Tx.StdId);
	printf("TX DATA:%02X%02X%02X%02X%02X%02X%02X%02X\r\n",Txdata[0],Txdata[1],Txdata[2],Txdata[3],Txdata[4],Txdata[5],Txdata[6],Txdata[7]);
	HAL_CAN_AddTxMessage(&hcan,&Can_Tx,Txdata,&pTxMailbox);
}
/**
  ******************************************************************************
  * @brief  cantxtest 测试发送的数据
  * @param  None
  * @return None
  * @note  
  ******************************************************************************
  */

void cantxtest(void)
{
				/* can 发送数据 */
                Txdata[0]=0x01;
                Txdata[1]=0x02;
		        Txdata[2]=0x03;
                Txdata[3]=0x04;
		        Txdata[4]=0x05;
                Txdata[5]=0x06;
		        Txdata[6]=0x07;
			    Txdata[6]=0x08;
	  			sendOrder(0x123,0,CAN_ID_STD,0,8);
}
/**
  ******************************************************************************
  * @brief  canrxtest 测试接收的数据
  * @param  None
  * @return None
  * @note  
  ******************************************************************************
  */
void canrxtest(void)
{
			can_recieve =HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &Can_Rx, Rxdata);
			if(!can_recieve)
			{
				can_recieve = 1;
				if (Can_Rx.StdId == 0x123 && Can_Rx.RTR == CAN_RTR_DATA && Can_Rx.IDE == CAN_ID_STD && Can_Rx.DLC == 8) 
				{
					// 接收到的CAN消息符合预期,进行处理
					// do something ...
					printf("can接收消息成功\r\n");
					printf("can_recieve_flag:%d\r\n",can_recieve_flag);
					printf("RX DATA: %02X%02X%02X%02X%02X%02X%02X%02X\r\n",Rxdata[0],Rxdata[1],Rxdata[2],Rxdata[3],Rxdata[4],Rxdata[5],Rxdata[6],Rxdata[7]);
				}
			}
		}


/* USER CODE END 1 */

2.can.h

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    can.h
  * @brief   This file contains all the function prototypes for
  *          the can.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* 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 sendmessage(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC,float send_data);
void sendOrder(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC);
void CAN_User_Init(CAN_HandleTypeDef* hcan );   //用户初始化函数
void cantxtest(void);
void canrxtest(void);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __CAN_H__ */

 3.main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "can.h"
#include "dma.h"
#include "i2c.h"
#include "iwdg.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ad7142.h"
#include "24cxx.h"
#include "delay.h"
#include "spi.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
extern IWDG_HandleTypeDef hiwdg;

/* adc variables **********************************************************/

/* adc_dma variables **********************************************************/
uint16_t ADC1_Value_DMA[10];

/* can variables **********************************************************/

/* Private variables **********************************************************/
static uint8_t 	s_vu8SysSched0Tmr = 0;
static uint8_t 	s_vu8SysSched1Tmr = 0;
static uint16_t s_vu16SysSched2Tmr = 0;
static uint16_t s_vu16SysSched3Tmr = 0;
static uint16_t s_vu8SysSched4Tmr = 0;

/* Private function **********************************************************/

/**
  ******************************************************************************
  * @brief  s_TimVarInit
  * @param  None
  * @return None
  * @note  task time  initialize
  ******************************************************************************
  */
static void s_TimVarInit(void)
{
	/*---task time  initialize---*/
	s_vu8SysSched0Tmr = 0;
	s_vu8SysSched1Tmr = 0;
	s_vu16SysSched2Tmr = 0;
	s_vu16SysSched3Tmr = 0;
	s_vu8SysSched4Tmr = 0;
}

/**
  ******************************************************************************
  * @brief  s_MainSysVarInit
  * @param  None
  * @return None
  * @note  task time  initialize 
  ******************************************************************************
  */

static void s_MainSysTickCfg(void)
{
    /* This example shows how to configure the SysTick to generate a time base equal to
       1 ms. The system clock is set to 24 MHz on Value line devices and to 72 MHz on
       other devices, the SysTick is clocked by the AHB clock (HCLK).
       prm == (N.[ms] * SystemCoreClock / 1000).
    */
    if (SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC))
    {
        /* Capture error */
        while (1);
    }
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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_DMA_Init();
  MX_ADC1_Init();
  MX_CAN_Init();
  MX_I2C1_Init();
  MX_SPI2_Init();
  MX_USART1_UART_Init();
  MX_IWDG_Init();
  /* USER CODE BEGIN 2 */
	/* timer *******************************************************************/
		s_MainSysTickCfg();
		s_TimVarInit();
	/* r_adc *******************************************************************/
		HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC1_Value_DMA, 10);
	/* can *******************************************************************/
		CAN_User_Init(&hcan);
	/* SPI *******************************************************************/
			AD7124ChInt0();
			AD7142Init();
	/* IIC *******************************************************************/

	
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
		
		/* WDG clear *******************************************************************/
		HAL_IWDG_Refresh(&hiwdg);


	 /* private function *************************************************************/
//		 GetResAdValue();

		/* can rx function ***************************************************************/
				canrxtest();
		/* spi function ******************************************************************/

    	if(s_vu8SysSched0Tmr >= OS_TIMER_200MS)
			{	
					s_vu8SysSched0Tmr = 0;	
					cantxtest();
					SpiSendAdcVal();
			}
		#if 0	
		/* can tx function *****************************************************************/
			if(s_vu8SysSched1Tmr >= OS_TIMER_250MS)
			{	
					s_vu8SysSched1Tmr = 0;
					cantxtest();
			}	
							
			/* I2C function *****************************************************************/

			if(s_vu16SysSched2Tmr >= OS_TIMER_800MS)
			{	
					s_vu16SysSched2Tmr = 0;
					i2c1_test();
			}
		#endif
			/* led function *****************************************************************/
			if(s_vu16SysSched3Tmr >= OS_TIMER_300MS)
			{	
					s_vu16SysSched3Tmr = 0;	
					HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_15);

			/* ad function *****************************************************************/	

						PrintResAdValue();
				
			}	
	
		/* iic function *****************************************************************/

  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */



/**
  ******************************************************************************
  * @brief  SysTickISR
  * @param  None
  * @return None
  * @note  
  ******************************************************************************
  */
void SysTickISR(void)
{
	if (s_vu8SysSched0Tmr != 0xFF)
	{ 
		s_vu8SysSched0Tmr++;    
	}

	if (s_vu8SysSched1Tmr != 0xFF)   
	{ 
		s_vu8SysSched1Tmr++;    
	}

	if (s_vu16SysSched2Tmr != 0xFFFF)   
	{ 
		s_vu16SysSched2Tmr++;    
	}

	if (s_vu16SysSched3Tmr != 0xFFFF)   
	{ 
		s_vu16SysSched3Tmr++;    
	}
	
		if (s_vu8SysSched4Tmr != 0xFF)   
	{ 
		s_vu8SysSched4Tmr++;    
	}
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

作者:安妮细水长流

物联沃分享整理
物联沃-IOTWORD物联网 » STM32CubeMX工程配置——STM32F103C8T6 CAN通信

发表回复