基于stm32的数控线性稳压电源,恒压恒流电源资料。 极具学习和设计参考价值,已验证,资料包括源程序,原理图,pcb等设计资料! 本设计采用220V市电输入工频变压器,将220V交流电压降为24V交流电

这个用STM32搞的数控电源有点意思,硬件和程序都整得挺实在。拆开电路板看架构,220V市电进来先过工频变压器降到24V交流,全桥整流配个4700uF大电容,怼出来32V左右的直流电。这里有个坑要注意——工频变压器虽然皮实,但体积重量感人,现在有些DIYer喜欢用开关电源前级替代,不过线性稳压的后级方案倒是稳妥。

核心调压部分玩的是运放+PMOS的经典套路。运放当比较器用,同相端接反馈分压,反相端接DLC5615的DA输出。当DA输出2V时,假设分压比是1:15,那输出电压就是2*(15+1)=32V?别急,实际分压电阻得用精密电阻配,不然DA的LSB步进会漂移。

看段驱动PMOS的关键代码:

void SetVoltage(float targetV){
    uint16_t dac_value = (uint16_t)(targetV * 61.44); // 30V对应1843(0x733)
    TLC5615_Write(dac_value);
}

这61.44的系数怎么来的?TLC5615是10位DA,基准2.048V。当DA输出V_dac时,电源输出电压Vout = V_dac * (R1+R2)/R2。假设分压电阻是10K+150K,那系数就是(160/10) * (2.048/2.0)=16.384。但代码里用61.44明显不对,估计实际分压比是33:1,可能硬件实际用了不同阻值——这提醒我们调压时必须实测分压电阻。

恒流模式更有意思。0.1Ω采样电阻上压降V=0.1*I,用LM358放大20倍后进STM32的ADC。注意这里运放的偏置电压会直接影响测量精度,代码里得做校准:

#define CURRENT_OFFSET 82 // 零点偏移量
uint16_t ReadCurrentADC(void){
    uint32_t sum = 0;
    for(uint8_t i=0;i<16;i++){
        sum += ADC_Read(ADC_CH_CURRENT);
    }
    return (sum >>4) - CURRENT_OFFSET; 
}

采样16次取平均能有效抑制工频干扰,但CURRENT_OFFSET这个偏移量需要上电时自动校准,而不是写死。更好的做法是开机时短接输出端,自动记录零点AD值。

过流保护用硬件比较器实现很聪明。当电流采样电压超过电位器设定值时,比较器翻转触发外部中断。代码里中断服务程序直接掐断输出:

void EXTI9_5_IRQHandler(void){
    if(EXTI_GetITStatus(EXTI_Line8)){
        MOSFET_OFF();
        BEEP_ALARM(3); 
        EXTI_ClearITPendingBit(EXTI_Line8);
    }
}

注意这里没做消抖,万一比较器临界振荡可能误触发。硬件上加个100pF电容到地会更稳妥。

温度检测用NTC时,代码里的温度计算公式要注意:

float TempCalc(uint16_t adc_val){
    float Rt = 10000.0 * (4095.0/adc_val -1); // 10K NTC
    float T = 1/(1/298.15 + log(Rt/10000)/3950.0); 
    return T -273.15; 
}

这个公式基于B=3950的NTC,实际器件参数可能有偏差。更专业的做法应该做两点校准,在25度和50度时记录AD值做线性修正。

主控逻辑的状态机切换是亮点:

typedef enum {CV_MODE, CC_MODE} WorkMode;
WorkMode currentMode = CV_MODE;

void ModeSwitch(void){
    static uint8_t lastKey = 0;
    if(KEY_MODE_TRIGGERED()){
        currentMode = (currentMode == CV_MODE)? CC_MODE : CV_MODE;
        LCD_ShowMode(currentMode);
    }
}

模式切换时要处理DAC输出的平滑过渡,突然切变可能导致输出冲击电流。可以加个渐变过渡:

void ModeTransition(){
    float target = (currentMode == CV_MODE) ? setVoltage : setCurrent*loadResistance;
    for(float v=currentOutput; v!=target; v+=step){
        SetVoltage(v);
        Delay(10);
    }
}

当然实际要考虑环路稳定性,别整成慢动作。

这套方案最妙的其实是上位机交互部分。用VS做的监控程序通过串口发指令,协议设计要讲究帧结构:

// 通信协议帧格式: 
// 0xAA | CMD | DataH | DataL | Checksum
void SendVoltageSetting(float voltage){
    uint16_t data = voltage *10; // 0.1V分辨率
    UART_SendByte(0xAA);
    UART_SendByte(CMD_SET_VOL);
    UART_SendByte(data >>8);
    UART_SendByte(data &0xFF);
    UART_SendByte(CheckSum());
}

校验和用异或还是CRC?实际测试发现用累加和就能满足要求,毕竟不是高速通信。

最后说个硬件上的隐患——PMOS管在低压差时功耗惊人。比如输出5V/1A时,管压降27V,功耗27W!必须加大散热片,或者改进电路做成多级调整。不过作为学习项目,能跑起来已经够本,真做产品还得换Buck拓扑。

拆开这个数控电源的外壳,电路板上的每个模块都藏着工程师的巧思。咱们先看电源转换部分——220V市电经过工频变压器降到24V交流,全桥整流后接了个10000μF的电解电容。别小看这个滤波电容,实测空载时电压能冲到34V左右,足够支撑30V的最大输出电压。

核心控制用STM32F103C8T6,这货的12位ADC和定时器资源正合适做精密控制。电压设定部分用TLC5615这个10位DAC,虽然分辨率差点意思,但配合补偿够用了。上段DAC初始化的代码:

void TLC5615_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    TLC5615_CS_High();
    TLC5615_SCLK_Low();
}

这里把PB12(CS)、PB13(SCLK)、PB15(DIN)配置成推挽输出模式。注意SPI时序要严格对应TLC5615的时序要求,特别是数据高位在前的特点。

电压反馈环路由LM358运放驱动IRF9540这个P沟道MOS管。运放的同相端接DAC输出,反相端接输出电压分压(用0.1%精度的金属膜电阻)。当输出电压波动时,运放会动态调整MOS管的导通程度,相当于一个硬件级的PID控制器。

电流采样用了0.1Ω/5W的锰铜电阻,配合AD620仪表放大器。这个设计有个坑——采样电阻的走线必须开尔文连接,否则接触电阻会导致测量误差。放大后的电压信号直接进STM32的ADC1通道8:

uint16_t Get_Current(void) {
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}

过流保护电路是硬件+双保险。比较器LM393随时监控电流信号,一旦超过电位器设定的阈值,立即触发外部中断。中断服务函数里直接关断MOS管,响应时间控制在5μs以内:

void EXTI9_5_IRQHandler(void) {
    if(EXTI_GetITStatus(EXTI_Line8) != RESET) {
        Output_Disable(); // 立即关闭输出
        BEEP_Alert(3);    // 三声急促报警
        EXTI_ClearITPendingBit(EXTI_Line8);
    }
}

温度检测用MF58系列NTC,分压电路接在ADC1通道9。做了线性化处理,通过查表法将ADC值转换为实际温度。当散热片温度超过60℃时,会自动降低输出电流直到温度回落。

LCD1602的驱动代码里有个小技巧——通过PWM控制背光亮度。用TIM3的CH3输出PWM,用户长按菜单键时可以调节屏幕亮度:

void LCD_Backlight(uint8_t brightness) {
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = brightness * 10;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);
}

上位机用C#开发,通过虚拟串口与电源通信。协议定义得很简洁:每帧包含起始符0xAA、命令字、数据、校验和。例如设置电压的命令帧:
AA 01 01 2C 00 D7
(01代表电压设置,012C对应300即30.0V,校验和D7)

调试时发现个有趣现象——当快速切换CV/CC模式时,运放偶尔会产生自激振荡。最后在MOS管的GS极之间并联10kΩ电阻,并在运放输出端串47Ω电阻才消除震荡。

这个项目最值得借鉴的是硬件保护与控制的有机结合。比如过流触发时,硬件比较器立即动作,同时中断记录故障信息。这种混合架构既保证了响应速度,又保留了故障诊断能力。
基于stm32的数控线性稳压电源,恒压恒流电源资料。
极具学习和设计参考价值,已验证,资料包括源程序,原理图,pcb等设计资料!
本设计采用220V市电输入工频变压器,将220V交流电压降为24V交流电压,经过全桥整流加电容滤波,输出约32V直流电压.可调输出电压方案采用线性稳压调整器方案,即运放处于比较调整状态,运放输出驱动P型MOS管,电压输出端由电阻分压反馈至运放同相输入端,运放反相输入端由STM32单片机控制TLC5615数模转换器输入模拟电压,根据运放构成比较器原理,运放的同相端和反相端始终趋向于电压相等的特性,不断调整MOS管的导通状态,从而可以实现STM32单片机通过控制数模转换器DA的输出,进而控制直流电压的输出大小.以上为作为电压源输出的方案介绍.
???作为电流源输出,需要在后级输出采用0.1欧采样电阻来采样电流,采样电流经运放放大后送至单片机AD进行计算,单片机即可获得实际输出电流大小,由此根据设定电流值大小进行比较判断再控制DA输出,即可修正输出电流与设置电流一致.采样经放大的电流一部分又经运放组成比较器电路,采样电流与电位器可设置的比较电压进行比较,当电流大于比较电压,即可改变运放输出的高低电平状态,运放输出接单片机IO口,单片机将此IO设置为外部中断触发模式,目的为实现过流时快速响应并切断输出.调节电位器即可调整过流值大小.
???液晶显示采用LCD1602,报警方式采用蜂鸣器LED声光报警.关键发热部位的温度通过NTC热敏电阻来采集,具有采集温度范围宽的优点.本机引出STM32单片机的串口接口,便于利用上位机进行控制。
对电路和程序稍加升级,该电源板兼容了稳流输出的功能,最后采用VS制作对应的数据采集上位机,能够更加适应实际的应用。
具体功能:
1、输出电压:范围 0V ~30.0V,输入交流220V,直接插220V市电即可;
2、步进0.1V,纹波 ?30mV;
3、最大输出电流:1.5A;
4、液晶LCD1602显示;
5、由“加、减”两键控制输出电压步进增减;
6、关键器件温度检测,超过60度声光报警。
7、具有输出过流保护,过流值大小通过电位器可调。
8、具有恒流输出和恒压输出两种模式,按键切换。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐