行业资讯

dac_control.c

发布时间:2026/7/31 4:02:30
dac_control.c /** file dac_control.c brief 直接调用 HAL_DAC 的 DAC 输出与 PI 控制实现。 */#include dac_control.hstatic uint8_t DAC_Control_IsNumber(float value){return ((value 0.0f) || (value 0.0f)) ? 1U : 0U;}static uint8_t DAC_Control_IsReady(const DAC_Control_t *control){return ((control ! NULL) (control-initialized ! 0U) (control-hdac ! NULL) (control-hdac-Instance ! NULL)) ? 1U : 0U;}static float DAC_Control_Clamp(float value, float min_value, float max_value, uint8_t *clamped){if (value min_value) { if (clamped ! NULL) *clamped 1U; return min_value; }if (value max_value) { if (clamped ! NULL) *clamped 1U; return max_value; }return value;}/* 电压 - 12位码值 - HAL_DAC_SetValue这是唯一真正写 PA4 的位置。 */static DAC_ControlStatus_t DAC_Control_WriteOutput(DAC_Control_t *control, float voltage){uint8_t clamped 0U;uint32_t raw_value;voltage DAC_Control_Clamp(voltage, control-output_min, control-output_max, clamped);raw_value (uint32_t)((voltage * (float)control-full_scale / control-vref_voltage) 0.5f);if (raw_value control-full_scale) raw_value control-full_scale;if (HAL_DAC_SetValue(control-hdac, control-channel, DAC_ALIGN_12B_R, raw_value) ! HAL_OK)return DAC_CONTROL_HAL_ERROR;control-output_voltage voltage;return (clamped ! 0U) ? DAC_CONTROL_CLAMPED : DAC_CONTROL_OK;}DAC_ControlStatus_t DAC_Control_Init(DAC_Control_t *control, DAC_HandleTypeDef *hdac,uint32_t channel, float vref_voltage, uint32_t full_scale,float output_min_voltage, float output_max_voltage){if ((control NULL) || (hdac NULL) || (hdac-Instance NULL) ||((channel ! DAC_CHANNEL_1) (channel ! DAC_CHANNEL_2)) ||(DAC_Control_IsNumber(vref_voltage) 0U) || !(vref_voltage 0.0f) ||(full_scale 0U) || (DAC_Control_IsNumber(output_min_voltage) 0U) ||(DAC_Control_IsNumber(output_max_voltage) 0U) || (output_min_voltage 0.0f) ||!(output_max_voltage output_min_voltage) || (output_max_voltage vref_voltage))return DAC_CONTROL_INVALID_ARGUMENT;control-hdac hdac;control-channel channel;control-vref_voltage vref_voltage;control-full_scale full_scale;control-target_voltage 0.0f;control-output_voltage 0.0f;control-output_min output_min_voltage;control-output_max output_max_voltage;control-kp 0.0f;control-ki 0.0f;control-integral 0.0f;control-closed_loop 0U;control-pi_first_update 0U;control-initialized 1U;return DAC_CONTROL_OK;}DAC_ControlStatus_t DAC_Control_Start(DAC_Control_t *control){if (DAC_Control_IsReady(control) 0U) return DAC_CONTROL_NOT_READY;if (HAL_DAC_Start(control-hdac, control-channel) ! HAL_OK) return DAC_CONTROL_HAL_ERROR;return DAC_Control_WriteOutput(control, control-output_min);}DAC_ControlStatus_t DAC_Control_Stop(DAC_Control_t *control){if (DAC_Control_IsReady(control) 0U) return DAC_CONTROL_NOT_READY;if (HAL_DAC_SetValue(control-hdac, control-channel, DAC_ALIGN_12B_R, 0U) ! HAL_OK)return DAC_CONTROL_HAL_ERROR;if (HAL_DAC_Stop(control-hdac, control-channel) ! HAL_OK) return DAC_CONTROL_HAL_ERROR;control-output_voltage 0.0f;control-closed_loop 0U;control-pi_first_update 0U;control-integral 0.0f;return DAC_CONTROL_OK;}DAC_ControlStatus_t DAC_Control_SetPI(DAC_Control_t *control, float kp, float ki){if (DAC_Control_IsReady(control) 0U) return DAC_CONTROL_NOT_READY;if ((DAC_Control_IsNumber(kp) 0U) || (DAC_Control_IsNumber(ki) 0U) ||(kp 0.0f) || (ki 0.0f)) return DAC_CONTROL_INVALID_ARGUMENT;control-kp kp;control-ki ki;return DAC_CONTROL_OK;}DAC_ControlStatus_t DAC_Control_SetTarget(DAC_Control_t *control, float target_voltage){if (DAC_Control_IsReady(control) 0U) return DAC_CONTROL_NOT_READY;if (DAC_Control_IsNumber(target_voltage) 0U) return DAC_CONTROL_INVALID_ARGUMENT;control-target_voltage target_voltage;return DAC_CONTROL_OK;}DAC_ControlStatus_t DAC_Control_SetOpenLoopVoltage(DAC_Control_t *control, float voltage){if (DAC_Control_IsReady(control) 0U) return DAC_CONTROL_NOT_READY;if (DAC_Control_IsNumber(voltage) 0U) return DAC_CONTROL_INVALID_ARGUMENT;control-closed_loop 0U;control-pi_first_update 0U;control-integral 0.0f;return DAC_Control_WriteOutput(control, voltage);}DAC_ControlStatus_t DAC_Control_EnableClosedLoop(DAC_Control_t *control, float target_voltage){DAC_ControlStatus_t status DAC_Control_SetTarget(control, target_voltage);if (status ! DAC_CONTROL_OK) return status;control-integral 0.0f;control-closed_loop 1U;control-pi_first_update 1U;return DAC_CONTROL_OK;}void DAC_Control_DisableClosedLoop(DAC_Control_t *control){if (DAC_Control_IsReady(control) 0U) return;control-closed_loop 0U;control-pi_first_update 0U;control-integral 0.0f;}DAC_ControlStatus_t DAC_Control_Update(DAC_Control_t *control, float measured_voltage, float dt_seconds){float error;float integral_candidate;float output_candidate;uint8_t clamped 0U;if (DAC_Control_IsReady(control) 0U) return DAC_CONTROL_NOT_READY;if ((DAC_Control_IsNumber(measured_voltage) 0U) ||(DAC_Control_IsNumber(dt_seconds) 0U) || !(dt_seconds 0.0f))return DAC_CONTROL_INVALID_ARGUMENT;if (control-closed_loop 0U) return DAC_CONTROL_OK;error control-target_voltage - measured_voltage;/** main 先用开环把 DAC 调到安全工作点后再切闭环。若一切换就清积分并计算* kp*error输出会从原电压突然跳到一个很小值。这里首周期保持已有输出* 后续周期才按 PI 调节因此示波器上不会看到切换瞬间的大幅跌落。*/if (control-pi_first_update ! 0U){/* 令 kp*error ki*integral 恰好等于当前输出实现无扰切换。 */if (control-ki 0.0f){control-integral (control-output_voltage - control-kp * error) / control-ki;}control-pi_first_update 0U;return DAC_Control_WriteOutput(control, control-output_voltage);}integral_candidate control-integral error * dt_seconds;output_candidate control-kp * error control-ki * integral_candidate;output_candidate DAC_Control_Clamp(output_candidate, control-output_min,control-output_max, clamped);/* 输出没有饱和时积分若饱和但误差正把输出拉回范围也允许积分。 */if ((clamped 0U) || ((output_candidate control-output_max) (error 0.0f)) ||((output_candidate control-output_min) (error 0.0f)))control-integral integral_candidate;return DAC_Control_WriteOutput(control, output_candidate);}float DAC_Control_GetOutputVoltage(const DAC_Control_t *control){return (DAC_Control_IsReady(control) ! 0U) ? control-output_voltage : 0.0f;}float DAC_Control_GetTargetVoltage(const DAC_Control_t *control){return (DAC_Control_IsReady(control) ! 0U) ? control-target_voltage : 0.0f;}