基于GD32F103CBT6单片机,通过PID算法利用PWM驱动气泵和电磁阀进行负压调节,请提供当负压超出安全范围时调用的中断处理程序代码
时间: 2024-02-22 10:59:51 浏览: 103
基于gd32f103的PID算法源代码.zip
当负压超出安全范围时,可以通过ADC采集负压传感器的数值,与设定的安全范围进行比较,如果超出安全范围,则触发中断处理程序,关闭气泵和电磁阀,以保护系统和用户的安全。
以下是基于GD32F103CBT6单片机的中断处理程序代码示例:
```c
#include "gd32f10x.h"
#include "gd32f10x_adc.h"
#include "gd32f10x_timer.h"
#define PWM_PERIOD (9999) // PWM周期
#define PWM_PULSE (5000) // PWM占空比
#define ADC_CHANNEL (ADC_CHANNEL_0) // ADC通道
#define ADC_SAMPLE_TIME (ADC_SAMPLETIME_55POINT5) // ADC采样时间
#define PRESSURE_MAX (1000) // 最大负压值
#define PRESSURE_MIN (500) // 最小负压值
#define P_COEFFICIENT (1.0f) // P系数
#define I_COEFFICIENT (0.1f) // I系数
#define D_COEFFICIENT (0.05f) // D系数
float pressure_setpoint = 800.0f; // 设定值
float pressure_actual = 0.0f; // 实际值
float pressure_error = 0.0f; // 误差值
float pressure_error_last = 0.0f; // 上一次误差值
float pressure_integral = 0.0f; // 积分值
uint16_t pwm_pulse = PWM_PULSE; // PWM占空比
void adc_init(void);
void timer_init(void);
void pwm_init(void);
void pid_control(void);
void adc_init(void)
{
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
adc_special_function_config(ADC_SCAN_MODE, DISABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
adc_regular_channel_config(0, ADC_CHANNEL, ADC_SAMPLE_TIME);
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
adc_enable();
adc_calibration_enable();
}
void timer_init(void)
{
rcu_periph_clock_enable(RCU_TIMER0);
timer_deinit(TIMER0);
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
timer_deinit(TIMER0);
timer_struct_para_init(&timer_initpara);
timer_initpara.prescaler = SystemCoreClock / 1000000 - 1;
timer_initpara.period = PWM_PERIOD;
timer_initpara.direction = TIMER_COUNTER_UP;
timer_initpara.alignment = TIMER_OC_MODE_PWM1;
timer_initpara.repetition_counter = 0;
timer_initpara.clock_division = TIMER_CKDIV_DIV1;
timer_init(TIMER0, &timer_initpara);
timer_oc_struct_para_init(&timer_ocinitpara);
timer_ocinitpara.oc_mode = TIMER_OC_MODE_PWM1;
timer_ocinitpara.oc_polarity = TIMER_OC_POLARITY_HIGH;
timer_ocinitpara.oc_pulse = pwm_pulse;
timer_output_mode_config(TIMER0, TIMER_CH_0, &timer_ocinitpara);
timer_auto_reload_shadow_enable(TIMER0);
timer_enable(TIMER0);
}
void pwm_init(void)
{
rcu_periph_clock_enable(RCU_GPIOB);
gpio_mode_set(GPIOB, GPIO_MODE_AF_PP, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_0);
}
void pid_control(void)
{
float pressure_setpoint_last = pressure_setpoint;
pressure_actual = adc_regular_data_read(ADC0) * 3.3f / 4096.0f * 1000.0f; // 读取ADC采样值并转换为负压值
pressure_error = pressure_setpoint - pressure_actual; // 计算误差值
pressure_integral += pressure_error; // 计算积分值
if (pressure_integral > PRESSURE_MAX)
{
pressure_integral = PRESSURE_MAX;
}
else if (pressure_integral < PRESSURE_MIN)
{
pressure_integral = PRESSURE_MIN;
}
float pressure_derivative = pressure_error - pressure_error_last; // 计算微分值
pressure_error_last = pressure_error;
float pid_output = P_COEFFICIENT * pressure_error + I_COEFFICIENT * pressure_integral + D_COEFFICIENT * pressure_derivative; // 计算PID输出值
if (pid_output > 100.0f)
{
pid_output = 100.0f;
}
else if (pid_output < 0.0f)
{
pid_output = 0.0f;
}
pwm_pulse = (uint16_t)(pid_output / 100.0f * PWM_PERIOD); // 计算PWM占空比
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, pwm_pulse); // 更新PWM占空比
if (pressure_actual > PRESSURE_MAX || pressure_actual < PRESSURE_MIN) // 如果负压超出安全范围,则触发中断处理程序
{
timer_disable(TIMER0); // 关闭PWM输出
// 关闭气泵和电磁阀
// ...
// 执行其他操作
pressure_setpoint = pressure_setpoint_last; // 重置设定值
pressure_actual = 0.0f; // 重置实际值
pressure_error = 0.0f; // 重置误差值
pressure_error_last = 0.0f; // 重置上一次误差值
pressure_integral = 0.0f; // 重置积分值
timer_enable(TIMER0); // 重新开启PWM输出
// 开启气泵和电磁阀
// ...
}
}
void TIMER0_IRQHandler(void)
{
if (timer_interrupt_flag_get(TIMER0, TIMER_INT_CH0) != RESET)
{
timer_interrupt_flag_clear(TIMER0, TIMER_INT_CH0);
}
}
int main(void)
{
adc_init();
timer_init();
pwm_init();
while (1)
{
pid_control();
}
}
```
在以上示例代码中,当负压超出安全范围时,会触发中断处理程序,关闭气泵和电磁阀,并执行其他操作,以确保系统和用户的安全。
阅读全文