This commit is contained in:
2026-03-10 20:06:01 +08:00
parent fea2f059b2
commit 0e91c86d4c
5 changed files with 53 additions and 39 deletions

View File

@@ -55,7 +55,7 @@ void SVC_Handler(void);
void DebugMon_Handler(void); void DebugMon_Handler(void);
void PendSV_Handler(void); void PendSV_Handler(void);
void SysTick_Handler(void); void SysTick_Handler(void);
void CAN1_RX0_IRQHandler(void); void CAN1_TX_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

@@ -38,10 +38,10 @@ void MX_CAN1_Init(void)
/* USER CODE END CAN1_Init 1 */ /* USER CODE END CAN1_Init 1 */
hcan1.Instance = CAN1; hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 6; hcan1.Init.Prescaler = 21;
hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_5TQ; hcan1.Init.TimeSeg1 = CAN_BS1_6TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_1TQ; hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE; hcan1.Init.AutoBusOff = DISABLE;
@@ -84,8 +84,8 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* CAN1 interrupt Init */ /* CAN1 interrupt Init */
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 2, 0); HAL_NVIC_SetPriority(CAN1_TX_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); HAL_NVIC_EnableIRQ(CAN1_TX_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 */
@@ -110,7 +110,7 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9);
/* CAN1 interrupt Deinit */ /* CAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn); HAL_NVIC_DisableIRQ(CAN1_TX_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

@@ -50,7 +50,11 @@
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */ /* USER CODE BEGIN PV */
/* USER CODE BEGIN PV */
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
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 -----------------------------------------------*/
@@ -62,14 +66,17 @@ void SystemClock_Config(void);
/* Private user code ---------------------------------------------------------*/ /* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */ /* USER CODE BEGIN 0 */
// 完美解决 USB 忙碌丢包的重定向函数 // 完美解决 USB 忙碌丢包的重定向函数
// 完美解决 USB 忙碌丢包,且防中断死锁的重定向函数
int _write(int file, char *ptr, int len) { int _write(int file, char *ptr, int len) {
uint8_t result = CDC_Transmit_FS((uint8_t*)ptr, len); uint8_t result = CDC_Transmit_FS((uint8_t*)ptr, len);
uint16_t timeout = 0;
// 如果 USB 正在忙,最多等 5ms防止死锁 // 使用简单的变量自增来做超时等待,坚决不用 HAL_Delay
while(result == USBD_BUSY && timeout < 5) { uint32_t timeout = 0;
HAL_Delay(1);
result = CDC_Transmit_FS((uint8_t*)ptr, len); // 50000 只是一个大概的经验值,纯耗费 CPU 周期
while(result == USBD_BUSY && timeout < 50000) {
timeout++; timeout++;
result = CDC_Transmit_FS((uint8_t*)ptr, len);
} }
return len; return len;
} }
@@ -116,6 +123,7 @@ int main(void)
MX_CAN1_Init(); MX_CAN1_Init();
/* USER CODE BEGIN 2 */ /* USER CODE BEGIN 2 */
// 1. 初始化 bxCAN 过滤器 (全通) // 1. 初始化 bxCAN 过滤器 (全通)
// 后面的 printf 就能看到了
CAN_FilterTypeDef canFilterConfig; CAN_FilterTypeDef canFilterConfig;
canFilterConfig.FilterBank = 0; canFilterConfig.FilterBank = 0;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
@@ -127,15 +135,17 @@ int main(void)
canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
canFilterConfig.FilterActivation = ENABLE; canFilterConfig.FilterActivation = ENABLE;
canFilterConfig.SlaveStartFilterBank = 14; canFilterConfig.SlaveStartFilterBank = 14;
HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig);
// 2. 启动 CAN 外设 HAL_StatusTypeDef fs = HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig);
HAL_CAN_Start(&hcan1); printf("Filter: %d\r\n", fs);
// 3. 开启 RX FIFO0 接收中断 HAL_StatusTypeDef ss = HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); printf("Start: %d\r\n", ss);
printf("=== F4 CAN Receiver Init OK ===\r\n"); HAL_StatusTypeDef ns = HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
printf("Notif: %d\r\n", ns);
printf("=== CAN Ready ===\r\n");
/* USER CODE END 2 */ /* USER CODE END 2 */
/* Infinite loop */ /* Infinite loop */
@@ -145,7 +155,17 @@ int main(void)
/* USER CODE END WHILE */ /* USER CODE END WHILE */
/* USER CODE BEGIN 3 */ /* USER CODE BEGIN 3 */
// 如果标志位被中断立起来了,说明有新数据
if (can_rx_flag == 1) {
can_rx_flag = 0; // 赶紧先把标志位清零,防止漏掉下一次
// 在主循环里悠哉游哉地通过 USB 打印,爱怎么耗时就怎么耗时
printf("Got MSG! ID:0x%03lX Data: ", RxHeader.StdId);
for(int i = 0; i < RxHeader.DLC; i++) {
printf("%02X ", RxData[i]);
}
printf("\r\n");
}
/* USER CODE END WHILE */ /* USER CODE END WHILE */
} }
/* USER CODE END 3 */ /* USER CODE END 3 */
@@ -199,17 +219,11 @@ void SystemClock_Config(void)
/* USER CODE BEGIN 4 */ /* USER CODE BEGIN 4 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{ {
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
if (hcan->Instance == CAN1) { if (hcan->Instance == CAN1) {
// 1. 光速把数据从 CAN 硬件 FIFO 里捞出来
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) { if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) {
// 收到数据,原样打印出来 // 2. 立起标志位,然后火速退出中断,绝不在这里打印!
printf("Got MSG! ID:0x%03lX Data: ", RxHeader.StdId); can_rx_flag = 1;
for(int i = 0; i < RxHeader.DLC; i++) {
printf("%02X ", RxData[i]);
}
printf("\r\n");
} }
} }
} }

View File

@@ -201,17 +201,17 @@ void SysTick_Handler(void)
/******************************************************************************/ /******************************************************************************/
/** /**
* @brief This function handles CAN1 RX0 interrupts. * @brief This function handles CAN1 TX interrupts.
*/ */
void CAN1_RX0_IRQHandler(void) void CAN1_TX_IRQHandler(void)
{ {
/* USER CODE BEGIN CAN1_RX0_IRQn 0 */ /* USER CODE BEGIN CAN1_TX_IRQn 0 */
/* USER CODE END CAN1_RX0_IRQn 0 */ /* USER CODE END CAN1_TX_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1); HAL_CAN_IRQHandler(&hcan1);
/* USER CODE BEGIN CAN1_RX0_IRQn 1 */ /* USER CODE BEGIN CAN1_TX_IRQn 1 */
/* USER CODE END CAN1_RX0_IRQn 1 */ /* USER CODE END CAN1_TX_IRQn 1 */
} }
/** /**

View File

@@ -2,12 +2,12 @@
CAD.formats= CAD.formats=
CAD.pinconfig= CAD.pinconfig=
CAD.provider= CAD.provider=
CAN1.BS1=CAN_BS1_5TQ CAN1.BS1=CAN_BS1_6TQ
CAN1.CalculateBaudRate=1000000 CAN1.CalculateBaudRate=250000
CAN1.CalculateTimeBit=1000 CAN1.CalculateTimeBit=4000
CAN1.CalculateTimeQuantum=142.85714285714286 CAN1.CalculateTimeQuantum=500.0
CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,Prescaler,BS1 CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,Prescaler,BS1
CAN1.Prescaler=6 CAN1.Prescaler=21
File.Version=6 File.Version=6
GPIO.groupedBy= GPIO.groupedBy=
KeepUserPlacement=false KeepUserPlacement=false
@@ -66,7 +66,7 @@ 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\: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
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false