#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;
}
|