#include "app.h" #include "adc.h" #include "tim.h" #include "gpio.h" #include "modbus.h" /* ADC1_IN5:电流采样 * 采样电阻 0.1 欧姆,放大器增益 10 倍,因此 1V 对应 1A。 * 12 位 ADC,参考电压按 3.3V 计算。 */ #define ADC_REFERENCE_MV 3300U #define ADC_MAX_CODE 4095U #define CURRENT_MAX_MA 2000U /* PWM 电流限幅占空比,范围 1~99,超范围按 99% 处理 */ #define PWM_DUTY_MIN 1U #define PWM_DUTY_MAX 99U #define PWM_DUTY_DEFAULT 99U /* LED 状态灯闪烁时间(单位 ms) */ #define LED_ON_FORWARD_MS 800U #define LED_OFF_FORWARD_MS 200U #define LED_ON_REVERSE_MS 200U #define LED_OFF_REVERSE_MS 800U #define LED_ON_STOP_MS 500U #define LED_OFF_STOP_MS 500U /* 自动定位容许阈值寄存器 */ #define AUTO_POSITION_TOLERANCE_REG 9U #define Encoder_Max 4200 static volatile uint8_t adcConversionDone = 0; static uint16_t lastRegister5 = 0; static void App_UpdateMotor(void); static void App_SetCurrentLimit(uint16_t duty); static void App_UpdateEncoderRegister(void); static void App_ProcessZeroCommand(void); static void App_UpdateLed(void); void App_Init(void) { /* 上电默认:电机停止 */ HAL_GPIO_WritePin(IO_1_GPIO_Port, IO_1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IO_2_GPIO_Port, IO_2_Pin, GPIO_PIN_RESET); /* 状态灯初始熄灭 */ HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); /* 启动编码器读取 */ HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); /* 启动 PWM 输出,并按当前寄存器值设置电流限幅占空比 */ HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); App_SetCurrentLimit(holdingRegisters[3]); /* ADC校准 */ if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) { Error_Handler(); } /* 启动 ADC 中断采集 */ adcConversionDone = 0; if (HAL_ADC_Start_IT(&hadc1) != HAL_OK) { Error_Handler(); } } void App_Process(void) { /* 先处理 Modbus 请求,可能更新寄存器 */ Modbus_Process(); App_UpdateMotor(); /*控制推杆上升下降包含自动和手动*/ App_SetCurrentLimit(holdingRegisters[3]); /*限制推杆电机电流*/ App_UpdateEncoderRegister(); /*获取定时器2计数值为编码器数值存到寄存器2*/ App_ProcessZeroCommand();/*设置当前位置为0*/ App_UpdateLed(); /*指示灯灯光切换*/ /* ADC 单次转换完成后重新启动下一轮转换 */ if (adcConversionDone != 0) { adcConversionDone = 0; HAL_ADC_Start_IT(&hadc1); } } static void App_UpdateMotor(void) { uint8_t io1 = (holdingRegisters[0] != 0) ? 1U : 0U; uint8_t io2 = (holdingRegisters[1] != 0) ? 1U : 0U; uint8_t up = 0U; uint8_t down = 0U; /*自动运行至指定位置,最下面值最大,最上面为0*/ if (holdingRegisters[6] != 0 && holdingRegisters[7] < Encoder_Max) { /* 自动定位模式:根据当前编码器值和目标位置决定运行方向 */ int32_t currentPosition = (int16_t)(uint16_t)__HAL_TIM_GET_COUNTER(&htim2); int32_t targetPosition = (int16_t)holdingRegisters[7]; int32_t positionError = targetPosition - currentPosition; int32_t tolerance = (int32_t)holdingRegisters[AUTO_POSITION_TOLERANCE_REG]; /*寄存器9*/ if (positionError > tolerance) { down = 1U; } else if (positionError < -tolerance) { up = 1U; } } else { /* 手动模式:保持原有 holdingRegisters[0]、[1] 控制逻辑 */ up = (io1 != 0 && io2 == 0) ? 1U : 0U; down = (io1 == 0 && io2 != 0) ? 1U : 0U; } if (up != 0) { /* 正转:IO_1 高,IO_2 低 */ HAL_GPIO_WritePin(IO_1_GPIO_Port, IO_1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(IO_2_GPIO_Port, IO_2_Pin, GPIO_PIN_RESET); } else if (down != 0) { /* 反转:IO_1 低,IO_2 高 */ HAL_GPIO_WritePin(IO_1_GPIO_Port, IO_1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IO_2_GPIO_Port, IO_2_Pin, GPIO_PIN_SET); } else { /* 停止:两路都低 */ HAL_GPIO_WritePin(IO_1_GPIO_Port, IO_1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IO_2_GPIO_Port, IO_2_Pin, GPIO_PIN_RESET); } } static void App_SetCurrentLimit(uint16_t duty) { if (duty < PWM_DUTY_MIN || duty > PWM_DUTY_MAX) { duty = PWM_DUTY_DEFAULT; } __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, duty); } static void App_UpdateEncoderRegister(void) { int32_t enc = (int32_t)__HAL_TIM_GET_COUNTER(&htim2); //holdingRegisters[2] = (uint16_t)(int16_t)enc; holdingRegisters[2] = (int16_t)enc; } static void App_ProcessZeroCommand(void) { if (holdingRegisters[5] != lastRegister5) { lastRegister5 = holdingRegisters[5]; __HAL_TIM_SET_COUNTER(&htim2, 0); } } static void App_UpdateLed(void) { static uint32_t lastToggle = 0; static GPIO_PinState ledState = GPIO_PIN_RESET; uint8_t io1 = (holdingRegisters[0] != 0) ? 1U : 0U; uint8_t io2 = (holdingRegisters[1] != 0) ? 1U : 0U; uint32_t onTime; uint32_t offTime; uint32_t period; uint32_t elapsed; if (io1 != 0 && io2 == 0) { onTime = LED_ON_FORWARD_MS; offTime = LED_OFF_FORWARD_MS; } else if (io1 == 0 && io2 != 0) { onTime = LED_ON_REVERSE_MS; offTime = LED_OFF_REVERSE_MS; } else { onTime = LED_ON_STOP_MS; offTime = LED_OFF_STOP_MS; } period = (ledState == GPIO_PIN_SET) ? onTime : offTime; elapsed = HAL_GetTick() - lastToggle; if (elapsed >= period) { ledState = (ledState == GPIO_PIN_SET) ? GPIO_PIN_RESET : GPIO_PIN_SET; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, ledState); lastToggle = HAL_GetTick(); } } /* ADC 转换完成中断回调:把采样电压换算为电流(mA) */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { if (hadc->Instance != ADC1) { return; } uint32_t raw = HAL_ADC_GetValue(&hadc1); uint32_t voltage_mv = (raw * ADC_REFERENCE_MV) / ADC_MAX_CODE; uint16_t current_ma = (uint16_t)voltage_mv; if (current_ma > CURRENT_MAX_MA) { current_ma = CURRENT_MAX_MA; } holdingRegisters[4] = current_ma; adcConversionDone = 1; }