- #include <xc.h>
- // 定义PID参数
- double kp = 0.5; // 比例系数
- double ki = 0.2; // 积分系数
- double kd = 0.1; // 微分系数
- // 定义PID变量
- double setpoint = 40.0; // 目标温度设定值
- double integral = 0.0; // 积分项
- double last_error = 0.0; // 上一次误差值
- // 定义PWM相关变量
- unsigned int duty_cycle = 0; // PWM占空比
- unsigned int pwm_period = 1000; // PWM周期
- // ADC初始化
- void ADC_Init() {
- ADCON0 = 0b00000001; // 设置ADC转换通道和使能ADC模块
- ADCON1 = 0b00001110; // 设置ADC输入和参考电压
- ADCON2 = 0b10111110; // 设置ADC时钟和转换时钟周期
- ADRESH = 0; // 清零高字节寄存器
- ADRESL = 0; // 清零低字节寄存器
- ADCON0bits.GO = 1; // 启动ADC转换
- }
- // PWM初始化
- void PWM_Init() {
- CCP1CON = 0b00001100; // 选择PWM模式,无输出反转
- CCPR1L = 0; // 设置初始PWM占空比为0
- PR2 = pwm_period; // 设置PWM周期
- T2CON = 0b00000100; // 启动定时器2,选择预分频器为1
- }
- // PID控制函数
- void PID_Control() {
- // 读取温度值
- ADCON0bits.GO = 1; // 启动ADC转换
- while (ADCON0bits.GO); // 等待ADC转换完成
- unsigned int temp = ADRESH; // 读取高字节寄存器值
- temp = (temp << 8) + ADRESL; // 读取完整的ADC值
- // 计算误差
- double error = setpoint - temp;
- // 计算PID输出
- double output = kp * error + ki * integral + kd * (error - last_error);
- // 更新PWM占空比
- duty_cycle = output;
- }
- // 更新PWM占空比
- void Update_PWM_DutyCycle() {
- unsigned int temp_duty = (unsigned int)(duty_cycle * pwm_period);
- // 防止溢出
- if (temp_duty > pwm_period)
- temp_duty = pwm_period;
- // 更新PWM占空比
- CCPR1L = temp_duty >> 2;
- CCP1CONbits.DC1B = temp_duty & 0x03;
- }
- int main() {
- // 初始化ADC和PWM
- ADC_Init();
- PWM_Init();
- while (1) {
- // 执行PID控制
- PID_Control();
- // 更新PWM占空比
- Update_PWM_DutyCycle();
- }
- return 0;
- }
|