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 */
作者:安妮细水长流