This commit is contained in:
2026-03-13 13:27:34 +08:00
parent 6fb57b0c72
commit e5d4a575f7
6 changed files with 77 additions and 45 deletions

View File

@@ -56,6 +56,7 @@ void DebugMon_Handler(void);
void PendSV_Handler(void); void PendSV_Handler(void);
void SysTick_Handler(void); void SysTick_Handler(void);
void CAN1_TX_IRQHandler(void); void CAN1_TX_IRQHandler(void);
void CAN1_RX0_IRQHandler(void);
void TIM6_DAC_IRQHandler(void); void TIM6_DAC_IRQHandler(void);
void OTG_FS_IRQHandler(void); void OTG_FS_IRQHandler(void);
/* USER CODE BEGIN EFP */ /* USER CODE BEGIN EFP */

View File

@@ -86,6 +86,8 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
/* CAN1 interrupt Init */ /* CAN1 interrupt Init */
HAL_NVIC_SetPriority(CAN1_TX_IRQn, 2, 0); HAL_NVIC_SetPriority(CAN1_TX_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn); 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 BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */ /* USER CODE END CAN1_MspInit 1 */
@@ -111,6 +113,7 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
/* CAN1 interrupt Deinit */ /* CAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(CAN1_TX_IRQn); HAL_NVIC_DisableIRQ(CAN1_TX_IRQn);
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspDeInit 1 */ /* USER CODE BEGIN CAN1_MspDeInit 1 */
/* USER CODE END CAN1_MspDeInit 1 */ /* USER CODE END CAN1_MspDeInit 1 */

View File

@@ -42,13 +42,25 @@
void MX_GPIO_Init(void) void MX_GPIO_Init(void)
{ {
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */ /* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_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);
} }

View File

@@ -55,7 +55,6 @@ CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8]; uint8_t RxData[8];
volatile uint8_t can_rx_flag = 0; // 告诉主程序“有数据来了”的标志位 volatile uint8_t can_rx_flag = 0; // 告诉主程序“有数据来了”的标志位
/* USER CODE END PV */ /* USER CODE END PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); void SystemClock_Config(void);
@@ -65,19 +64,23 @@ void SystemClock_Config(void);
/* Private user code ---------------------------------------------------------*/ /* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */ /* USER CODE BEGIN 0 */
// 完美解决 USB 忙碌丢包的重定向函数 extern USBD_HandleTypeDef hUsbDeviceFS; // 引入 USB 状态句柄
// 完美解决 USB 忙碌丢包,且防中断死锁的重定向函数
int _write(int file, char *ptr, int len) {
uint8_t result = CDC_Transmit_FS((uint8_t*)ptr, len);
// 使用简单的变量自增来做超时等待,坚决不用 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; uint32_t timeout = 0;
// 50000 只是一个大概的经验值,纯耗费 CPU 周期 // 2. 极短超时:就算 USB 连着但突然卡了,最多循环 5000 次就强行放弃,保命要紧
while(result == USBD_BUSY && timeout < 50000) { while(result == USBD_BUSY && timeout < 5000) {
timeout++; timeout++;
result = CDC_Transmit_FS((uint8_t*)ptr, len); result = CDC_Transmit_FS((uint8_t*)ptr, len);
} }
return len; return len;
} }
/* USER CODE END 0 */ /* USER CODE END 0 */
@@ -137,20 +140,18 @@ int main(void)
canFilterConfig.SlaveStartFilterBank = 14; canFilterConfig.SlaveStartFilterBank = 14;
HAL_StatusTypeDef fs = HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig); HAL_StatusTypeDef fs = HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig);
printf("Filter: %d\r\n", fs);
HAL_StatusTypeDef ss = HAL_CAN_Start(&hcan1); 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); 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 */ /* USER CODE END 2 */
/* Infinite loop */ /* Infinite loop */
/* USER CODE BEGIN WHILE */ /* USER CODE BEGIN WHILE */
static uint32_t last_heartbeat = 0;
while (1) while (1)
{ {
/* USER CODE END WHILE */ /* USER CODE END WHILE */
@@ -159,12 +160,6 @@ int main(void)
// ========================================== // ==========================================
// 强制打印 1每隔 1 秒无条件打印一次(心跳包) // 强制打印 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 接收处理逻辑 // 强制打印 2原来的 CAN 接收处理逻辑
@@ -172,12 +167,15 @@ int main(void)
if (can_rx_flag == 1) { if (can_rx_flag == 1) {
can_rx_flag = 0; // 赶紧先把标志位清零 can_rx_flag = 0; // 赶紧先把标志位清零
// 加了超级醒目的感叹号,防止看漏 // 💡 修改这里:用一个数组把要发的话拼起来,只调用一次 printf
printf("!!! BINGO !!! Got CAN MSG! ID:0x%03lX Data: ", RxHeader.StdId); // 这能彻底防止 168MHz 的 CPU 把 USB 虚拟串口瞬间撑爆死机
for(int i = 0; i < RxHeader.DLC; i++) { char usb_buf[100];
printf("%02X ", RxData[i]); sprintf(usb_buf, "!!! BINGO !!! Got CAN MSG! ID:0x%03lX Data: %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
} RxHeader.StdId,
printf("\r\n"); RxData[0], RxData[1], RxData[2], RxData[3],
RxData[4], RxData[5], RxData[6], RxData[7]);
printf("%s", usb_buf);
} }
/* USER CODE END WHILE */ /* USER CODE END WHILE */
} }

View File

@@ -214,6 +214,20 @@ void CAN1_TX_IRQHandler(void)
/* USER CODE END CAN1_TX_IRQn 1 */ /* 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. * @brief This function handles TIM6 global interrupt, DAC1 and DAC2 underrun error interrupts.
*/ */

View File

@@ -34,24 +34,25 @@ Mcu.Pin0=PE5
Mcu.Pin1=PE6 Mcu.Pin1=PE6
Mcu.Pin10=PA6 Mcu.Pin10=PA6
Mcu.Pin11=PA7 Mcu.Pin11=PA7
Mcu.Pin12=PE9 Mcu.Pin12=PB2
Mcu.Pin13=PE11 Mcu.Pin13=PE9
Mcu.Pin14=PD12 Mcu.Pin14=PE11
Mcu.Pin15=PD13 Mcu.Pin15=PD12
Mcu.Pin16=PC6 Mcu.Pin16=PD13
Mcu.Pin17=PC7 Mcu.Pin17=PC6
Mcu.Pin18=PC8 Mcu.Pin18=PC7
Mcu.Pin19=PC9 Mcu.Pin19=PC8
Mcu.Pin2=PC14-OSC32_IN Mcu.Pin2=PC14-OSC32_IN
Mcu.Pin20=PA11 Mcu.Pin20=PC9
Mcu.Pin21=PA12 Mcu.Pin21=PA11
Mcu.Pin22=PA13 Mcu.Pin22=PA12
Mcu.Pin23=PA14 Mcu.Pin23=PA13
Mcu.Pin24=PB8 Mcu.Pin24=PA14
Mcu.Pin25=PB9 Mcu.Pin25=PB8
Mcu.Pin26=VP_SYS_VS_Systick Mcu.Pin26=PB9
Mcu.Pin27=VP_TIM6_VS_ClockSourceINT Mcu.Pin27=VP_SYS_VS_Systick
Mcu.Pin28=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS Mcu.Pin28=VP_TIM6_VS_ClockSourceINT
Mcu.Pin29=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
Mcu.Pin3=PC15-OSC32_OUT Mcu.Pin3=PC15-OSC32_OUT
Mcu.Pin4=PH0-OSC_IN Mcu.Pin4=PH0-OSC_IN
Mcu.Pin5=PH1-OSC_OUT Mcu.Pin5=PH1-OSC_OUT
@@ -59,13 +60,14 @@ Mcu.Pin6=PA0-WKUP
Mcu.Pin7=PA1 Mcu.Pin7=PA1
Mcu.Pin8=PA2 Mcu.Pin8=PA2
Mcu.Pin9=PA3 Mcu.Pin9=PA3
Mcu.PinsNb=29 Mcu.PinsNb=30
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32F407VGTx Mcu.UserName=STM32F407VGTx
MxCube.Version=6.15.0 MxCube.Version=6.15.0
MxDb.Version=DB.6.0.150 MxDb.Version=DB.6.0.150
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false 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.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.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true NVIC.ForceEnableDMAVector=true
@@ -105,6 +107,8 @@ PA6.Signal=S_TIM3_CH1
PA7.GPIOParameters=GPIO_Label PA7.GPIOParameters=GPIO_Label
PA7.GPIO_Label=RL_ENC_B PA7.GPIO_Label=RL_ENC_B
PA7.Signal=S_TIM3_CH2 PA7.Signal=S_TIM3_CH2
PB2.Locked=true
PB2.Signal=GPIO_Output
PB8.Locked=true PB8.Locked=true
PB8.Mode=CAN_Activate PB8.Mode=CAN_Activate
PB8.Signal=CAN1_RX PB8.Signal=CAN1_RX