基于 PIC16F676 的自动稳压器设计
一、系统总体设计
1.1 功能需求
- 自动稳压:输入电压变化时,自动调整输出电压保持稳定
- 过压保护:输入电压超过阈值时自动切断输出
- 欠压保护:输入电压低于阈值时自动切断输出
- 过流保护:输出电流超过阈值时自动切断输出
- 状态指示:LED指示工作状态(正常/过压/欠压/过流)
- 输出电压可调:通过按键或电位器调整输出电压
1.2 系统框图
┌─────────────────────────────────────────────────────────────┐
│ PIC16F676 自动稳压器系统 │
├─────────────────────────────────────────────────────────────┤
│ 输入电源 │ PIC16F676 │ 调整电路 │ 输出电源 │
│ │ │ │ │
│ AC 220V │ • ADC采样 │ • PWM控制 │ • DC输出 │
│ ↓整流滤波 │ • 比较器 │ • 驱动电路 │ • 负载 │
│ DC输入 │ • PWM输出 │ • 开关管 │ │
│ │ • 保护逻辑 │ │ │
└─────────────────────────────────────────────────────────────┘
二、硬件设计
2.1 PIC16F676 引脚分配
PIC16F676 (8引脚 SOIC/DIP)
┌─────────────────────────────┐
│ VDD (Pin 1) │ ← 5V电源
│ GP5/AN4 (Pin 2) │ ← 输出电压采样
│ GP4/AN3 (Pin 3) │ ← 输入电压采样
│ GP3/MCLR/VPP (Pin 4) │ ← 复位/编程
│ GP2/T0CKI/INT/COUT │ → PWM输出/比较器输出
│ GP1/AN1 (Pin 6) │ ← 电流采样/按键输入
│ GP0/AN0 (Pin 7) │ ← 参考电压/按键输入
│ VSS (Pin 8) │ ← 地
└─────────────────────────────┘
2.2 硬件连接图
/******************** 硬件连接定义 ********************/
// 模拟输入引脚
#define VIN_SENSE_PIN 4 // GP3/AN3 - 输入电压采样
#define VOUT_SENSE_PIN 5 // GP4/AN4 - 输出电压采样
#define IOUT_SENSE_PIN 6 // GP1/AN1 - 输出电流采样
#define REF_VOLTAGE_PIN 7 // GP0/AN0 - 参考电压设置
// 输出控制引脚
#define PWM_OUTPUT_PIN 2 // GP2 - PWM输出到驱动电路
#define STATUS_LED_PIN 3 // GP4 - 状态指示LED
// 保护阈值定义(根据实际硬件调整)
#define OVER_VOLTAGE_THRESHOLD 260 // 过压阈值 26.0V
#define UNDER_VOLTAGE_THRESHOLD 90 // 欠压阈值 9.0V
#define OVER_CURRENT_THRESHOLD 100 // 过流阈值 10.0A
#define TARGET_VOLTAGE 120 // 目标输出电压 12.0V
2.3 关键电路设计
2.3.1 电压采样电路
输入电压采样:
Vin ── R1(100k) ──┬── GP3(AN3)
└── R2(10k) ── GND
输出电压采样:
Vout ── R3(100k) ──┬── GP4(AN4)
└── R4(10k) ── GND
电流采样:
Io ── Rshunt(0.1Ω) ──┬── GP1(AN1)
└── GND
2.3.2 PWM驱动电路
PIC GP2 ── R10(1k) ──┬── Q1(2N3904) ── R11(100Ω) ── MOSFET栅极
└── GND
2.3.3 保护指示电路
GP4 ── R12(330Ω) ── LED ── GND
三、软件设计
3.1 系统配置
/**
* @file main.c
* @brief PIC16F676 自动稳压器主程序
* @compiler XC8
*/
#include <xc.h>
#include <stdint.h>
// 配置字设置
#pragma config FOSC = INTRCIO // 内部4MHz振荡器,IO功能
#pragma config WDTE = OFF // 关闭看门狗
#pragma config PWRTE = ON // 上电延时使能
#pragma config MCLRE = OFF // GP3作为IO使用
#pragma config BOREN = ON // 欠压复位使能
#pragma config CP = OFF // 关闭代码保护
// 系统参数
#define _XTAL_FREQ 4000000 // 4MHz内部振荡器
// 全局变量
uint16_t vin_adc = 0; // 输入电压ADC值
uint16_t vout_adc = 0; // 输出电压ADC值
uint16_t iout_adc = 0; // 输出电流ADC值
uint16_t target_voltage = TARGET_VOLTAGE; // 目标电压
uint8_t system_status = 0; // 系统状态:0=正常,1=过压,2=欠压,3=过流
uint8_t pwm_duty = 50; // PWM占空比 (0-100)
// 函数声明
void System_Init(void);
void ADC_Init(void);
void PWM_Init(void);
void Read_Sensors(void);
void Voltage_Control(void);
void Protection_Check(void);
void Update_Status_LED(void);
3.2 系统初始化
/**
* @brief 系统初始化
*/
void System_Init(void) {
// 配置振荡器为4MHz
OSCCAL = 0x80; // 使用出厂校准值
// 配置GPIO
TRISIO = 0b11111000; // GP0-GP2为输出,GP3-GP5为输入
GPIO = 0x00; // 所有输出置低
// 配置模拟引脚
ANSEL = 0b01110000; // GP3,GP4,GP5为模拟输入,其余为数字IO
CMCON = 0x07; // 关闭比较器
// 初始化各模块
ADC_Init();
PWM_Init();
// 延时等待系统稳定
__delay_ms(100);
}
3.3 ADC模块配置
/**
* @brief ADC初始化
*/
void ADC_Init(void) {
ADCON0 = 0x81; // 开启ADC,选择AN0,Fosc/8
ANSEL = 0b01110000; // 配置模拟引脚
__delay_us(10); // ADC稳定时间
}
/**
* @brief 读取ADC值
* @param channel ADC通道 (0-7)
* @return ADC转换结果 (0-1023)
*/
uint16_t ADC_Read(uint8_t channel) {
uint16_t adc_result;
// 选择ADC通道
ADCON0 &= 0xC7; // 清除通道选择位
ADCON0 |= (channel << 3); // 设置新通道
__delay_us(10); // 通道切换稳定时间
// 启动转换
GO_nDONE = 1;
while(GO_nDONE); // 等待转换完成
// 读取结果
adc_result = (ADRESH << 8) | ADRESL;
return adc_result;
}
/**
* @brief 读取所有传感器
*/
void Read_Sensors(void) {
vin_adc = ADC_Read(3); // 读取输入电压 (AN3/GP4)
vout_adc = ADC_Read(4); // 读取输出电压 (AN4/GP5)
iout_adc = ADC_Read(1); // 读取输出电流 (AN1/GP1)
}
3.4 PWM模块配置
/**
* @brief PWM初始化
*/
void PWM_Init(void) {
// 配置Timer2
T2CON = 0x04; // Timer2预分频1:1,后分频1:1
PR2 = 0xFF; // PWM周期 = (PR2+1)*4*Tosc = 256*4/4MHz = 256μs
// 配置CCP1为PWM模式
CCP1CON = 0x0C; // PWM模式
CCPR1L = 128; // 初始占空比50%
// 启动Timer2
TMR2ON = 1;
}
/**
* @brief 设置PWM占空比
* @param duty 占空比 (0-100)
*/
void PWM_SetDuty(uint8_t duty) {
uint16_t pwm_value;
if(duty > 100) duty = 100;
if(duty < 5) duty = 5; // 最小占空比限制
pwm_value = (uint16_t)duty * 1023 / 100; // 转换为10位PWM值
CCPR1L = pwm_value >> 2; // 高8位
CCP1CONbits.DC1B = pwm_value & 0x03; // 低2位
}
3.5 电压控制算法
/**
* @brief 电压控制主逻辑
*/
void Voltage_Control(void) {
int16_t error;
int16_t adjustment;
static int16_t integral = 0;
static int16_t last_error = 0;
// 将ADC值转换为实际电压 (假设参考电压5V)
uint16_t actual_voltage = (vout_adc * 500) / 1023; // 单位:0.1V
// 计算误差
error = target_voltage - actual_voltage;
// PID控制算法
integral += error;
if(integral > 1000) integral = 1000; // 积分限幅
if(integral < -1000) integral = -1000;
adjustment = (error * 2) + (integral / 10) + ((error - last_error) * 1);
// 调整PWM占空比
if(adjustment > 0) {
if(pwm_duty < 95) pwm_duty += 1;
} else if(adjustment < 0) {
if(pwm_duty > 5) pwm_duty -= 1;
}
// 更新PWM
PWM_SetDuty(pwm_duty);
last_error = error;
}
3.6 保护功能
/**
* @brief 保护功能检查
*/
void Protection_Check(void) {
uint16_t vin_voltage, vout_voltage, iout_current;
// 转换ADC值为实际值 (单位:0.1V 或 0.1A)
vin_voltage = (vin_adc * 500) / 1023; // 输入电压 (0.1V)
vout_voltage = (vout_adc * 500) / 1023; // 输出电压 (0.1V)
iout_current = (iout_adc * 500) / 1023; // 输出电流 (0.1A)
// 过压保护
if(vin_voltage > OVER_VOLTAGE_THRESHOLD ||
vout_voltage > OVER_VOLTAGE_THRESHOLD) {
system_status = 1; // 过压状态
PWM_SetDuty(0); // 关闭PWM输出
return;
}
// 欠压保护
if(vin_voltage < UNDER_VOLTAGE_THRESHOLD) {
system_status = 2; // 欠压状态
PWM_SetDuty(0); // 关闭PWM输出
return;
}
// 过流保护
if(iout_current > OVER_CURRENT_THRESHOLD) {
system_status = 3; // 过流状态
PWM_SetDuty(0); // 关闭PWM输出
return;
}
// 恢复正常状态
system_status = 0;
}
/**
* @brief 更新状态LED
*/
void Update_Status_LED(void) {
static uint8_t led_counter = 0;
switch(system_status) {
case 0: // 正常状态 - LED常亮
GP4 = 1;
break;
case 1: // 过压 - LED快闪
if(++led_counter >= 10) {
GP4 = !GP4;
led_counter = 0;
}
break;
case 2: // 欠压 - LED慢闪
if(++led_counter >= 50) {
GP4 = !GP4;
led_counter = 0;
}
break;
case 3: // 过流 - LED灭
GP4 = 0;
break;
}
}
3.7 按键处理(电压调整)
/**
* @brief 按键扫描和处理
*/
void Key_Process(void) {
static uint8_t key_pressed = 0;
uint16_t key_adc;
// 读取参考电压设置引脚
key_adc = ADC_Read(0); // AN0/GP0
// 检测按键
if(key_adc < 100) { // 电压增加按键
if(!key_pressed) {
target_voltage += 5; // 增加0.5V
if(target_voltage > 240) target_voltage = 240;
key_pressed = 1;
}
} else if(key_adc > 400 && key_adc < 600) { // 电压减少按键
if(!key_pressed) {
target_voltage -= 5; // 减少0.5V
if(target_voltage < 50) target_voltage = 50;
key_pressed = 1;
}
} else {
key_pressed = 0;
}
}
3.8 主程序
/**
* @brief 主程序
*/
void main(void) {
// 系统初始化
System_Init();
// 主循环
while(1) {
// 读取传感器数据
Read_Sensors();
// 检查保护状态
Protection_Check();
// 如果系统正常,执行电压控制
if(system_status == 0) {
Voltage_Control();
Key_Process(); // 处理按键输入
}
// 更新状态指示
Update_Status_LED();
// 延时
__delay_ms(10);
}
}
参考代码 采用pic16f676的自动稳压器 www.youwenfan.com/contentcsu/60361.html
四、PCB设计要点
4.1 布局建议
- 功率回路:输入滤波→开关管→输出滤波,路径最短
- 模拟地数字地分离:单点接地,避免干扰
- 散热设计:开关管加散热片,PCB增加铜皮面积
- 高压隔离:输入高压部分与低压控制部分保持安全距离
4.2 关键元件选型
| 元件 | 规格 | 备注 |
|---|---|---|
| 开关管 | IRF540N | N沟道MOSFET,100V/33A |
| 驱动电阻 | 100Ω | 限制栅极电流 |
| 输入电容 | 470μF/400V | 电解电容,滤波 |
| 输出电容 | 1000μF/25V | 低ESR电解电容 |
| 续流二极管 | MUR460 | 快恢复二极管 |
| 采样电阻 | 0.1Ω/5W | 电流采样 |
五、调试与测试
5.1 测试步骤
- 静态测试:检查各点电压,确保无短路
- 空载测试:逐步增加输入电压,观察输出电压稳定性
- 带载测试:接入不同负载,测试稳压性能
- 保护测试:模拟过压、欠压、过流情况
5.2 性能参数
| 参数 | 指标 |
|---|---|
| 输入电压范围 | 15V-30V DC |
| 输出电压范围 | 5V-24V DC可调 |
| 输出电流 | 最大5A |
| 稳压精度 | ±2% |
| 纹波电压 | <50mV |
| 效率 | >85% |
六、功能扩展
6.1 可增加的功能
- 软启动:避免开机冲击电流
- 短路保护:输出短路自动保护
- 温度保护:过热自动降功率
- 数码管显示:显示电压电流值
- 远程控制:通过串口调整参数
6.2 软件优化
- 数字滤波:对ADC采样值进行滤波
- 自适应PID:根据负载调整PID参数
- 故障记录:记录保护事件
- 自诊断:定期检查系统状态
这个基于PIC16F676的自动稳压器设计具有成本低、性能可靠、易于制作的特点,非常适合DIY和小批量生产应用。通过合理的软硬件设计,可以实现专业级的稳压器产品。 ⚡