123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * File Name : freertos.c
- * Description : Code for freertos applications
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2025 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 "FreeRTOS.h"
- #include "task.h"
- #include "main.h"
- #include "cmsis_os.h"
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "adc.h"
- #include "dma.h"
- #include "i2c.h"
- #include "tim.h"
- #include "queue.h"
- /* USER CODE END Includes */
- /* Private typedef -----------------------------------------------------------*/
- typedef StaticQueue_t osStaticMessageQDef_t;
- /* USER CODE BEGIN PTD */
- /* USER CODE END PTD */
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
- typedef enum
- {
- Close_output,
- Close_input,
- Open1_input,
- Open2_input,
- default_Hall
- } hallADC;
- hallADC Hallmode;
- DeviceParams_t g_deviceParams;
- /* USER CODE END PD */
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
- //ADC变量定义
- uint16_t AD_Value[5] = {0};
- uint16_t AD1, AD2, AD3, AD4, AD5 = 0;
- int i,adc;
- float AD1_Vol,AD2_Vol,AD3_Vol,AD4_Vol,AD5_Vol,AD5_I;
- extern uint16_t Valve_status; // 阀状态0000关0001开
- float pid_output = 0.0f;
- extern uint16_t Running_time; // 运行时长
- extern uint32_t Motor_speed; // 电机转速
- extern uint32_t Motor_current; // 电机电流
- extern uint32_t Magnetic_angle; // 磁角度
- extern uint32_t hall_data[4]; // 霍尔1到4的数据
- extern uint8_t dataReceive485[BUFFER_SIZE485]; // 485串口接收缓冲区
- extern uint16_t uartIRQ_rx_len ; // 485串口接收数据长度
- float Motor_cur = 0.0f; // 电机电流
- float Motor_spe = 0.0f; // 电机转速
- extern float delta_time; // 读取角度间隔时间(毫秒)
- extern int32_t freq; // 定时器1频率
- uint32_t period_buffer[CAPTURE_DEPTH]; // PWM周期
- uint32_t high_buffer[CAPTURE_DEPTH]; // PWM高电平时间
- sysmode Systemmode;
- /* USER CODE END PM */
- /* Private variables ---------------------------------------------------------*/
- /* USER CODE BEGIN Variables */
- /* USER CODE END Variables */
- /* Definitions for HighestTask */
- osThreadId_t HighestTaskHandle;
- const osThreadAttr_t HighestTask_attributes = {
- .name = "HighestTask",
- .stack_size = 128 * 4,
- .priority = (osPriority_t) osPriorityRealtime,
- };
- /* Definitions for ReadTask */
- osThreadId_t ReadTaskHandle;
- const osThreadAttr_t ReadTask_attributes = {
- .name = "ReadTask",
- .stack_size = 128 * 4,
- .priority = (osPriority_t) osPriorityNormal,
- };
- /* Definitions for DealTask */
- osThreadId_t DealTaskHandle;
- const osThreadAttr_t DealTask_attributes = {
- .name = "DealTask",
- .stack_size = 512 * 4,
- .priority = (osPriority_t) osPriorityNormal,
- };
- /* Definitions for CommonTask */
- osThreadId_t CommonTaskHandle;
- const osThreadAttr_t CommonTask_attributes = {
- .name = "CommonTask",
- .stack_size = 128 * 4,
- .priority = (osPriority_t) osPriorityBelowNormal,
- };
- /* Definitions for MotorTask */
- osThreadId_t MotorTaskHandle;
- const osThreadAttr_t MotorTask_attributes = {
- .name = "MotorTask",
- .stack_size = 256 * 4,
- .priority = (osPriority_t) osPriorityNormal,
- };
- /* Definitions for uart485rxqueue */
- osMessageQueueId_t uart485rxqueueHandle;
- uint8_t uart485queueBuffer[ 16 * sizeof( Uart485Rx_msg ) ];
- osStaticMessageQDef_t uart485queueControlBlock;
- const osMessageQueueAttr_t uart485rxqueue_attributes = {
- .name = "uart485rxqueue",
- .cb_mem = &uart485queueControlBlock,
- .cb_size = sizeof(uart485queueControlBlock),
- .mq_mem = &uart485queueBuffer,
- .mq_size = sizeof(uart485queueBuffer)
- };
- /* Private function prototypes -----------------------------------------------*/
- /* USER CODE BEGIN FunctionPrototypes */
- //void uart_enable(void);
- //void Restart_UART1_DMA(void);
- float Read_MT6813_Angle(void);
- void pack_hall_data(void) ;
- void pack_Magnetic_angle(void);
- void pack_Motor_current(void); // 电机电流
- void pack_Motor_speed(void); // 电机转速
- /* USER CODE END FunctionPrototypes */
- void HighestLEDTask(void *argument);
- void ReaddataTask(void *argument);
- void DealcallbackTask(void *argument);
- void CommonPrintTask(void *argument);
- void MotorControlTask(void *argument);
- void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
- /**
- * @brief FreeRTOS initialization
- * @param None
- * @retval None
- */
- void MX_FREERTOS_Init(void) {
- /* USER CODE BEGIN Init */
- printf("API2_ELE 0612\r\n");
- Systemmode = Debugmode; // 调试模式
-
- load_params_from_flash(); // 从内部flash读取传感器参数
- Set_485_Baudrate(g_deviceParams.Serial_baud_rate);
- Restart_UART1_DMA();
-
- /* USER CODE END Init */
- /* USER CODE BEGIN RTOS_MUTEX */
- /* add mutexes, ... */
- /* USER CODE END RTOS_MUTEX */
- /* USER CODE BEGIN RTOS_SEMAPHORES */
- /* add semaphores, ... */
- /* USER CODE END RTOS_SEMAPHORES */
- /* USER CODE BEGIN RTOS_TIMERS */
- /* start timers, add new ones, ... */
- /* USER CODE END RTOS_TIMERS */
- /* Create the queue(s) */
- /* creation of uart485rxqueue */
- uart485rxqueueHandle = osMessageQueueNew (16, sizeof(Uart485Rx_msg), &uart485rxqueue_attributes);
- /* USER CODE BEGIN RTOS_QUEUES */
- /* add queues, ... */
- /* USER CODE END RTOS_QUEUES */
- /* Create the thread(s) */
- /* creation of HighestTask */
- HighestTaskHandle = osThreadNew(HighestLEDTask, NULL, &HighestTask_attributes);
- /* creation of ReadTask */
- ReadTaskHandle = osThreadNew(ReaddataTask, NULL, &ReadTask_attributes);
- /* creation of DealTask */
- DealTaskHandle = osThreadNew(DealcallbackTask, NULL, &DealTask_attributes);
- /* creation of CommonTask */
- CommonTaskHandle = osThreadNew(CommonPrintTask, NULL, &CommonTask_attributes);
- /* creation of MotorTask */
- MotorTaskHandle = osThreadNew(MotorControlTask, NULL, &MotorTask_attributes);
- /* USER CODE BEGIN RTOS_THREADS */
- /* add threads, ... */
- /* USER CODE END RTOS_THREADS */
- /* USER CODE BEGIN RTOS_EVENTS */
- /* add events, ... */
- /* USER CODE END RTOS_EVENTS */
- }
- /* USER CODE BEGIN Header_HighestLEDTask */
- /**
- * @brief Function implementing the HighestTask thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_HighestLEDTask */
- void HighestLEDTask(void *argument)
- {
- /* USER CODE BEGIN HighestLEDTask */
- /* Infinite loop */
- LEDStatus_t current_status;
- uint8_t last_status = 0;
- uint32_t runtimecount = 0;
- for(;;)
- {
-
- if(Hallmode == Close_output)
- current_status = LED_WARNING_1;
- else if(Hallmode == Close_input)
- current_status = LED_WARNING_2;
- else if(Hallmode == Open1_input)
- current_status = LED_WARNING_3;
- else if(Hallmode == Open2_input)
- current_status = LED_WARNING_4;
- else
- current_status = LED_NORMAL;
- if(Motormode == MOTOR_OVERCURRENT)
- current_status = LED_WARNING_5;
-
- if(Systemmode == IAPbootloader)
- current_status = LED_IAP;
-
- // 只有当状态发生变化时才调用
- if (current_status != last_status)
- {
- last_status = current_status;
- UpdateLEDStatus(current_status);
- }
- LED_FlashHandler(&led_green);
- LED_FlashHandler(&led_red);
- if(runtimecount > 100)
- {
- runtimecount = 0;
- Running_time ++ ;
- if(Running_time > 65535)
- Running_time = 0;
- }
- runtimecount++;
- osDelay(10);
- }
- /* USER CODE END HighestLEDTask */
- }
- /* USER CODE BEGIN Header_ReaddataTask */
- /**
- * @brief Function implementing the ReadTask thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_ReaddataTask */
- void ReaddataTask(void *argument)
- {
- /* USER CODE BEGIN ReaddataTask */
- /* Infinite loop */
- /*角度PWM输入捕获*/
- // HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
- // HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
- // HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
- // HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
- HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_1, period_buffer, CAPTURE_DEPTH);
- HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_2, high_buffer, CAPTURE_DEPTH);
- /*ADC多通道读取*/
- ADC_Enable (&hadc1);
- HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED); // 启动ADC校准(单端模式)消除ADC的偏移误差 ADC_DIFFERENTIAL_ENDED ADC_SINGLE_ENDED
- HAL_ADC_Start_DMA(&hadc1,(uint32_t *) AD_Value, 5); // 启动ADC并通过DMA搬运数据
-
- for(;;)
- {
- // Read_MT6813_Angle(); // PWM中断读取角度
- // read_angle(); // 硬件iic读取角度
- pack_Magnetic_angle(); // 组包到 Magnetic_angle 用于MODBUS发送
- pack_Motor_speed(); // 组包到 Motor_speed 用于MODBUS发送
-
- AD1 = AD_Value[0];
- AD2 = AD_Value[1];
- AD3 = AD_Value[2];
- AD4 = AD_Value[3];
- AD5 = AD_Value[4];
-
- AD1_Vol = (float) AD1 / 4096 * (float) 3.3;
- AD2_Vol = (float) AD2 / 4096 * (float) 3.3;
- AD3_Vol = (float) AD3 / 4096 * (float) 3.3;
- AD4_Vol = (float) AD4 / 4096 * (float) 3.3;
- AD5_Vol = (float) AD5 / 4096 * (float) 3.3;
-
- if( AD5_Vol > 3.3f )
- AD5_Vol = 0.0f;
- AD5_I = AD5_Vol / 0.5f;
- Motor_cur = AD5_I;
- pack_hall_data(); // 组包到 hall_data 用于MODBUS发送
- pack_Motor_current(); // 组包到 Motor_current 用于MODBUS发送
-
- if(AD1_Vol > 1.6f && AD1_Vol < 2.0f && AD2_Vol > 2.5f && AD4_Vol > 1.1f && AD4_Vol < 1.5f)
- {
- // 拉杆关 电机伸出到位
- Hallmode = Close_output;
- Valve_status = 0;
- }
- else if(AD1_Vol > 1.6f && AD1_Vol < 2.0f && AD2_Vol > 2.5f && AD4_Vol > 1.5f && AD4_Vol < 2.0f)
- {
- // 拉杆关 电机缩回到位
- Hallmode = Close_input;
- Valve_status = 1;
- }
- else if(AD1_Vol < 1.0f && AD2_Vol > 1.0f && AD2_Vol < 1.4f && AD4_Vol > 1.6f && AD4_Vol < 2.0f)
- {
- // 拉杆开 电机缩回到位
- Hallmode = Open1_input;
- Valve_status = 1;
- }
- else if(AD1_Vol > 1.2f && AD1_Vol < 1.6f && AD2_Vol > 0.9f && AD2_Vol < 1.3f && AD4_Vol > 1.6f && AD4_Vol < 2.0f)
- {
- // 拉杆开 电机缩回到位
- Hallmode = Open2_input;
- Valve_status = 1;
- }else{
- Hallmode = default_Hall;
- Valve_status = 1;
- }
-
- osDelay(5);
- }
- /* USER CODE END ReaddataTask */
- }
- /* USER CODE BEGIN Header_DealcallbackTask */
- /**
- * @brief Function implementing the DealTask thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_DealcallbackTask */
- void DealcallbackTask(void *argument)
- {
- /* USER CODE BEGIN DealcallbackTask */
- /* Infinite loop */
-
-
-
- for(;;)
- {
- Process_Uart485callback(); // 处理485指令应答
- osDelay(20);
- }
- /* USER CODE END DealcallbackTask */
- }
- /* USER CODE BEGIN Header_CommonPrintTask */
- /**
- * @brief Function implementing the CommonTask thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_CommonPrintTask */
- void CommonPrintTask(void *argument)
- {
- /* USER CODE BEGIN CommonPrintTask */
- /* Infinite loop */
- for(;;)
- {
- target_angle_deg = pidMotor1Speed.target_val;
- diff_Angle = pidMotor1Speed.err;
-
- // printf("target=[%.2f] cur=[%.2f] diff=[%.2f] pid_output=[%.2f] Magnet:[%s] Motor_spe[%.2f] delta_time[%.2f]\r\n",
- // target_angle_deg, cur_angle_deg, diff_Angle ,pid_output ,no_mag_flag ? "NO" : "YES" ,Motor_spe ,delta_time);
- printf("cur_angle_deg=[%.2f] Motor_spe[%.2f] Motor_cur[%.3f]\r\n", cur_angle_deg,Motor_spe,Motor_cur);
- osDelay(200);
-
- // printf("AD1_Vol:[%.3f], AD2_Vol:[%.3f], AD3_Vol:[%.3f], AD4_Vol[%.3f], AD5_Vol[%.3f], Motor_cur[%.3f]\r\n",
- // AD1_Vol, AD2_Vol, AD3_Vol, AD4_Vol, AD5_Vol, Motor_cur);
-
- if(Hallmode == Close_output)
- {
- printf("Close output \r\n"); // 拉杆关 电机伸出到位
- }
- if(Hallmode == Close_input)
- {
- printf("Close input \r\n"); // 拉杆关 电机收回到位
- }
- if(Hallmode == Open1_input)
- {
- printf("Open1 input \r\n"); // 拉杆开一档 电机收回到位
- }
- if(Hallmode == Open2_input)
- {
- printf("Open2 input \r\n"); // 拉杆开二挡 电机收回到位
- }
- if(Hallmode == default_Hall)
- {
- printf("default_Hall \r\n"); // 拉杆开 电机收回到位
- }
- }
- /* USER CODE END CommonPrintTask */
- }
- /* USER CODE BEGIN Header_MotorControlTask */
- /**
- * @brief Function implementing the MotorTask thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_MotorControlTask */
- void MotorControlTask(void *argument)
- {
- /* USER CODE BEGIN MotorControlTask */
- /* Infinite loop */
- HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); // 启动电机 CH1 PWM(控制 IN1)
- HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); // 启动电机 CH2 PWM(控制 IN2)
- uint16_t overcurrent_timer_ms = 0; // 记录过流持续时间
- PID_init();
-
- for(;;)
- {
- // 电机角度 cur_angle_deg(0到360度)
- // 电机转速 Motor_spe (-400到+400)
- // 电机电流 Motor_cur (正常是0.01,堵转最高是到0.035)
- // 目标速度 target_speed
-
- // Motor_Angle_Current_PID_Control();
- if(use_pid_control)
- {
- if (Motor_cur > 0.035f )
- {
- if (overcurrent_timer_ms < 1500)
- {
- overcurrent_timer_ms += 10; // 每10ms调用一次
- }
- else
- {
- // 过流超时,停转
- Motormode = MOTOR_OVERCURRENT;
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
- }
- }
- else
- {
- // 电流恢复正常,清零计时器
- overcurrent_timer_ms = 0;
- }
- // Motor_PID_Control();
- // Motor_Angle_Current_PID_Control();
- int16_t pwm_output = PID_Incremental_Calc(&pidMotor1Speed, pidMotor1Speed.target_speed, Motor_spe);
- // 起动门槛限制
- if (abs(pwm_output) < 350 && pidMotor1Speed.target_speed != 0)
- pwm_output = (pwm_output > 0) ? 500 : -500;
- if (Motormode == MOTOR_FORWARD)
- Motor_Forward(pwm_output);
- if (Motormode == MOTOR_REVERSE)
- Motor_Reverse(pwm_output);
- if (Motormode == MOTOR_STOPPED)
- {
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
- }
-
- }
-
- // float pwm_Speed = PID_Incremental_Calc(&pidMotor1Speed,1000,Motor_spe);
- // __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, pwm_Speed); //电机正转
-
- if(Hallmode != Close_output)
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
-
- if(Hallmode != Open1_input && Hallmode != Open2_input && Hallmode != Close_input)
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
- osDelay(10);
- }
- /* USER CODE END MotorControlTask */
- }
- /* Private application code --------------------------------------------------*/
- /* USER CODE BEGIN Application */
- float Read_MT6813_Angle(void)
- {
- uint32_t high_time = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2); // 高电平宽度
- uint32_t period = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1)+1; // 周期
- if (period == 0) return 0.0f;
- float duty = (float)high_time / period;
- cur_angle_deg = duty * 360.0f;
-
- return angle;
- }
- void pack_hall_data(void)
- {
- memcpy(&hall_data[0], &AD1_Vol, sizeof(float)); // float --> uint32_t(IEEE754位一致)
- memcpy(&hall_data[1], &AD2_Vol, sizeof(float));
- memcpy(&hall_data[2], &AD3_Vol, sizeof(float));
- memcpy(&hall_data[3], &AD4_Vol, sizeof(float));
- }
- void pack_Magnetic_angle(void)
- {
- memcpy(&Magnetic_angle, &cur_angle_deg, sizeof(float)); // float --> uint32_t
- }
- void pack_Motor_speed(void) // 电机转速
- {
- memcpy(&Motor_speed, &Motor_spe, sizeof(float)); // float --> uint32_t
- }
- void pack_Motor_current(void) // 电机电流
- {
- memcpy(&Motor_current, &Motor_cur, sizeof(float)); // float --> uint32_t
- }
-
- void JumpToBootloader(void)
- {
- uint32_t i;
- void (*SysMemBootJump)(void);
- uint32_t BootAddr = 0x1FFF0000; // STM32L431 系统 Bootloader 起始地址
- /* 关闭全局中断 */
- __disable_irq();
- /* 关闭 SysTick */
- SysTick->CTRL = 0;
- SysTick->LOAD = 0;
- SysTick->VAL = 0;
- /* 复位 RCC 时钟设置 */
- HAL_RCC_DeInit();
- /* 禁用所有 NVIC 中断 */
- for (i = 0; i < 8; i++) {
- NVIC->ICER[i] = 0xFFFFFFFF;
- NVIC->ICPR[i] = 0xFFFFFFFF;
- }
- /* 重新允许中断(尽管之后马上跳转) */
- __enable_irq();
- /* 重新映射系统内存到 0x00000000 */
- __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
- /* 设置 MSP(Main Stack Pointer) */
- __set_MSP(*((uint32_t *)BootAddr));
- /* 设置 CONTROL 寄存器,切换为特权级、使用 MSP */
- __set_CONTROL(0);
- /* 获取 Bootloader 的复位向量地址(入口地址) */
- SysMemBootJump = (void (*)(void)) (*((uint32_t *)(BootAddr + 4)));
- /* 跳转到系统 Bootloader */
- SysMemBootJump();
- /* 此处不应再返回 */
- while (1);
- }
- /* USER CODE END Application */
|