From e5d4a575f7fc03d6b73df84359d3720eef686652 Mon Sep 17 00:00:00 2001 From: nitiantuhao <2062405236@qq.com> Date: Fri, 13 Mar 2026 13:27:34 +0800 Subject: [PATCH] 1.0 --- Core/Inc/stm32f4xx_it.h | 1 + Core/Src/can.c | 3 +++ Core/Src/gpio.c | 14 +++++++++++- Core/Src/main.c | 50 ++++++++++++++++++++--------------------- Core/Src/stm32f4xx_it.c | 14 ++++++++++++ FDR-Core.ioc | 40 ++++++++++++++++++--------------- 6 files changed, 77 insertions(+), 45 deletions(-) diff --git a/Core/Inc/stm32f4xx_it.h b/Core/Inc/stm32f4xx_it.h index 01d2cb3..ae0f282 100644 --- a/Core/Inc/stm32f4xx_it.h +++ b/Core/Inc/stm32f4xx_it.h @@ -56,6 +56,7 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void CAN1_TX_IRQHandler(void); +void CAN1_RX0_IRQHandler(void); void TIM6_DAC_IRQHandler(void); void OTG_FS_IRQHandler(void); /* USER CODE BEGIN EFP */ diff --git a/Core/Src/can.c b/Core/Src/can.c index 1794b14..02efd1b 100644 --- a/Core/Src/can.c +++ b/Core/Src/can.c @@ -86,6 +86,8 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle) /* CAN1 interrupt Init */ HAL_NVIC_SetPriority(CAN1_TX_IRQn, 2, 0); HAL_NVIC_EnableIRQ(CAN1_TX_IRQn); + HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); /* USER CODE BEGIN CAN1_MspInit 1 */ /* USER CODE END CAN1_MspInit 1 */ @@ -111,6 +113,7 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle) /* CAN1 interrupt Deinit */ HAL_NVIC_DisableIRQ(CAN1_TX_IRQn); + HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn); /* USER CODE BEGIN CAN1_MspDeInit 1 */ /* USER CODE END CAN1_MspDeInit 1 */ diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c index efdefa0..bdfd1af 100644 --- a/Core/Src/gpio.c +++ b/Core/Src/gpio.c @@ -42,13 +42,25 @@ void MX_GPIO_Init(void) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); + + /*Configure GPIO pin : PB2 */ + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } diff --git a/Core/Src/main.c b/Core/Src/main.c index 8fae40b..5fd43c5 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -55,7 +55,6 @@ CAN_RxHeaderTypeDef RxHeader; uint8_t RxData[8]; volatile uint8_t can_rx_flag = 0; // 告诉主程序“有数据来了”的标志位 /* USER CODE END PV */ -/* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); @@ -65,19 +64,23 @@ void SystemClock_Config(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -// 完美解决 USB 忙碌丢包的重定向函数 -// 完美解决 USB 忙碌丢包,且防中断死锁的重定向函数 -int _write(int file, char *ptr, int len) { - uint8_t result = CDC_Transmit_FS((uint8_t*)ptr, len); +extern USBD_HandleTypeDef hUsbDeviceFS; // 引入 USB 状态句柄 - // 使用简单的变量自增来做超时等待,坚决不用 HAL_Delay +int _write(int file, char *ptr, int len) { + // 1. 致命拦截:如果电脑压根没连上 USB,直接丢弃数据,坚决不死等! + if (hUsbDeviceFS.dev_state != USBD_STATE_CONFIGURED) { + return len; + } + + uint8_t result = CDC_Transmit_FS((uint8_t*)ptr, len); uint32_t timeout = 0; - // 50000 只是一个大概的经验值,纯耗费 CPU 周期 - while(result == USBD_BUSY && timeout < 50000) { + // 2. 极短超时:就算 USB 连着但突然卡了,最多循环 5000 次就强行放弃,保命要紧 + while(result == USBD_BUSY && timeout < 5000) { timeout++; result = CDC_Transmit_FS((uint8_t*)ptr, len); } + return len; } /* USER CODE END 0 */ @@ -137,20 +140,18 @@ int main(void) canFilterConfig.SlaveStartFilterBank = 14; HAL_StatusTypeDef fs = HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig); - printf("Filter: %d\r\n", fs); - HAL_StatusTypeDef ss = HAL_CAN_Start(&hcan1); - printf("Start: %d\r\n", ss); + // 这句开启接收中断的函数极其重要,确认它还在! HAL_StatusTypeDef ns = HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); - printf("Notif: %d\r\n", ns); - printf("=== CAN Ready ===\r\n"); + // 💡 修改这里:必须加这一句!给你的电脑 3 秒钟时间去识别 USB 虚拟串口 + HAL_Delay(3000); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ - static uint32_t last_heartbeat = 0; + while (1) { /* USER CODE END WHILE */ @@ -159,12 +160,6 @@ int main(void) // ========================================== // 强制打印 1:每隔 1 秒无条件打印一次(心跳包) // ========================================== - if (HAL_GetTick() - last_heartbeat >= 1000) { - last_heartbeat = HAL_GetTick(); - HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2); - // 只要 USB 串口是好的,你就一定能每秒看到这句话! - printf("System Running... Waiting for CAN...\r\n"); - } // ========================================== // 强制打印 2:原来的 CAN 接收处理逻辑 @@ -172,12 +167,15 @@ int main(void) if (can_rx_flag == 1) { can_rx_flag = 0; // 赶紧先把标志位清零 - // 加了超级醒目的感叹号,防止看漏 - printf("!!! BINGO !!! Got CAN MSG! ID:0x%03lX Data: ", RxHeader.StdId); - for(int i = 0; i < RxHeader.DLC; i++) { - printf("%02X ", RxData[i]); - } - printf("\r\n"); + // 💡 修改这里:用一个数组把要发的话拼起来,只调用一次 printf! + // 这能彻底防止 168MHz 的 CPU 把 USB 虚拟串口瞬间撑爆死机 + char usb_buf[100]; + sprintf(usb_buf, "!!! BINGO !!! Got CAN MSG! ID:0x%03lX Data: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", + RxHeader.StdId, + RxData[0], RxData[1], RxData[2], RxData[3], + RxData[4], RxData[5], RxData[6], RxData[7]); + + printf("%s", usb_buf); } /* USER CODE END WHILE */ } diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c index 949a645..7074a86 100644 --- a/Core/Src/stm32f4xx_it.c +++ b/Core/Src/stm32f4xx_it.c @@ -214,6 +214,20 @@ void CAN1_TX_IRQHandler(void) /* USER CODE END CAN1_TX_IRQn 1 */ } +/** + * @brief This function handles CAN1 RX0 interrupts. + */ +void CAN1_RX0_IRQHandler(void) +{ + /* USER CODE BEGIN CAN1_RX0_IRQn 0 */ + + /* USER CODE END CAN1_RX0_IRQn 0 */ + HAL_CAN_IRQHandler(&hcan1); + /* USER CODE BEGIN CAN1_RX0_IRQn 1 */ + + /* USER CODE END CAN1_RX0_IRQn 1 */ +} + /** * @brief This function handles TIM6 global interrupt, DAC1 and DAC2 underrun error interrupts. */ diff --git a/FDR-Core.ioc b/FDR-Core.ioc index 24eb45d..4e76f4e 100644 --- a/FDR-Core.ioc +++ b/FDR-Core.ioc @@ -34,24 +34,25 @@ Mcu.Pin0=PE5 Mcu.Pin1=PE6 Mcu.Pin10=PA6 Mcu.Pin11=PA7 -Mcu.Pin12=PE9 -Mcu.Pin13=PE11 -Mcu.Pin14=PD12 -Mcu.Pin15=PD13 -Mcu.Pin16=PC6 -Mcu.Pin17=PC7 -Mcu.Pin18=PC8 -Mcu.Pin19=PC9 +Mcu.Pin12=PB2 +Mcu.Pin13=PE9 +Mcu.Pin14=PE11 +Mcu.Pin15=PD12 +Mcu.Pin16=PD13 +Mcu.Pin17=PC6 +Mcu.Pin18=PC7 +Mcu.Pin19=PC8 Mcu.Pin2=PC14-OSC32_IN -Mcu.Pin20=PA11 -Mcu.Pin21=PA12 -Mcu.Pin22=PA13 -Mcu.Pin23=PA14 -Mcu.Pin24=PB8 -Mcu.Pin25=PB9 -Mcu.Pin26=VP_SYS_VS_Systick -Mcu.Pin27=VP_TIM6_VS_ClockSourceINT -Mcu.Pin28=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS +Mcu.Pin20=PC9 +Mcu.Pin21=PA11 +Mcu.Pin22=PA12 +Mcu.Pin23=PA13 +Mcu.Pin24=PA14 +Mcu.Pin25=PB8 +Mcu.Pin26=PB9 +Mcu.Pin27=VP_SYS_VS_Systick +Mcu.Pin28=VP_TIM6_VS_ClockSourceINT +Mcu.Pin29=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS Mcu.Pin3=PC15-OSC32_OUT Mcu.Pin4=PH0-OSC_IN Mcu.Pin5=PH1-OSC_OUT @@ -59,13 +60,14 @@ Mcu.Pin6=PA0-WKUP Mcu.Pin7=PA1 Mcu.Pin8=PA2 Mcu.Pin9=PA3 -Mcu.PinsNb=29 +Mcu.PinsNb=30 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F407VGTx MxCube.Version=6.15.0 MxDb.Version=DB.6.0.150 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.CAN1_RX0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.CAN1_TX_IRQn=true\:2\:0\:true\:false\:true\:true\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true @@ -105,6 +107,8 @@ PA6.Signal=S_TIM3_CH1 PA7.GPIOParameters=GPIO_Label PA7.GPIO_Label=RL_ENC_B PA7.Signal=S_TIM3_CH2 +PB2.Locked=true +PB2.Signal=GPIO_Output PB8.Locked=true PB8.Mode=CAN_Activate PB8.Signal=CAN1_RX