电子产品世界 » 论坛首页 » 电子DIY » 拆解+DIY » ±20V可调稳压电源(带电压同步显示),附代码


共8条 1/1 1 跳转至

±20V可调稳压电源(带电压同步显示),附代码

高工
2013-10-15 10:21:50    评分


水平有限,画电压表电路图有压力,有机会尽量补上
发出来给新手看一下,写了一下制作过程中遇到的一些问题,有些错误的地方请大家提出来


电源参数:
可调电压范围±0.02V~±20V
纹波<1mV
0-7V输出1A电流
7-12V输出0.5A电流
(变压器功率20W



电压表参数:
测量范围0~±20V
正电压误差<0.1V
负电压误差<0.08V   (我比较懒,这个误差还可以调下程序缩小的,但是第一个小电压表把我折腾的够呛的,所以电路焊好之后,程序大致上那样就没管它了)



 (因没有电子负载,用5V直流电机和12V直流电机作负载测试最大电流,7V时最大输出1A电流,12V时最大输出0.5A电流,电流超过此标准输出电压mv级减小。分析原因:变压器功率不足,散热片散热能力不够。)



  电路图采用的是LM317LM337基本应用电路,稍微作了一些修改。由于LM317的基准电压是1.25V,输出电压下限为1.25V,所以需要在它的输出接地端需要外加一个-1.25V的电压来抵消它的基准电压,从而实现输出0V起调;LM337同理,在电位器和地之间接一个1.25V的电压来抵消-1.25V,这里使用了21.235V的电压基准,就是图中的LM385-1.2,与之串联的电阻和LED分别用来限流和做指示灯。关于电容的选择,104用来减少高频干扰,焊接电路时离稳压片输入端越近越好;4.7uf的小电容用来稳定稳压片的工作;2200uf大电容,用来滤低频波,使输出电压平滑稳定,如果需要输出大电流需要加大电容容量,并加大功率三极管扩大输出电流。


     关于数码管电压实时显示,使用的是STC15F204EA单片机(单片机自带8通道10AD转换功能),电压表供电由该电源提供,使用LM7815LM7815稳压给运放供电,使用LM7805稳压给单片机供电;考虑到成本,使用单片机自带AD功能。关于单片机外围电路,因为此单片机只能采样不超过他的工作电压的电压,单片机正电压采样电路用电阻分压来扩大它的测量范围,为了提高精度,当采样电压小于4.1V时自动切换AD通道由单片机直接采样;负电压的采样,用的是反相比例运算电路,放大倍数为0.209倍,所测电压经反相运算放大后再送到单片机I/O口。电压基准使用的是TL431,电压为2.5V。数码管显示部分,带有小数点自动切换功能,数码管位选由单片机控制138译码器实现,段选直接由单片机I/O口控制。


实际制作这个电压表的时候,开始是先做了一个简易的只能测量正电压的电压表,熟悉了AD转换之后,又开始做双显示正负电压的电压表,制作过程中,遇到很多问题,也学到了很多。数码管显示暗淡,需要外加驱动电路,后来在芯片手册里看到STC15F204EA带有强推挽输出,所以就在程序里设置了I/O推挽的输出,免去了数码管驱动电路;然后就是数码管消隐,刚开始做的时候显示的数字很不清晰,然后在网上看了一些关于数码管消隐的例程,知道了消隐的原理之后,修改程序把显示部分做好了;还有就是运放的使用,刚开始做的时候,使用的是一般的音频运放,运放工作很不稳定,无法稳定输出,在论坛问了一些网友,按他们推荐的去买了个仪表用运放,然后把电路板上的运放电路那块拆了,重新焊上新运放,焊好之后,用电压表测量,0输入的时候饱和输出,就是一直输出最大电压VCC,不知道什么原因,又去网上看一些运放电路的知识,偶然看到了运放供电需要加去耦电容,然后尝试着在供电两端各加了一个10uf电容,再测输出,为零点几毫伏了,然后调节调0电阻,使输出为0,给运放加上输入信号,慢慢调节输入电压,和运算电路输出电压比较,放大倍数一直是0.209很稳定,运放工作正常。


下面是制作过程中的拍的几张图片


电源



第一次做的电压表。。。。




两个数码管洞洞板不好焊,只能这样先处理数码管






万用表只有一个。。。所以那个小电压表也上场了





[font='宋体']











秀秀我的书桌,工具不多,暂时够用了~~








[电压表程序,自己胡乱写的,哪位高手能帮忙改一下,提高一下效率


  1. #include<stc15f204ea.h>
  2. #include<intrins.h>
  3. #define    ADC_POWER       0x80                  //ADC 电源控制位
  4. #define    ADC_FLAG        0x10                  //ADC 完成标志
  5. #define    ADC_START       0x08                  //ADC 启动控制位
  6. #define    ADC_speed_LL    0x00                  //540 时钟
  7. #define    ADC_speed_L     0x20                  //360 时钟
  8. #define    ADC_speed_H     0x40                  //180 时钟
  9. #define    ADC_speed_HH    0x60                  // 90 时钟
  10. typedef unsigned long  ul;
  11. void delay(unsigned int x);  //函数声明
  12. void LCD_one(ul LedNumVal);  //函数声明
  13. void LCD_two(ul LedNumVal);  //函数声明
  14. void Delay1ms();             //函数声明
  15. void Delay150us();           //函数声明
  16. void AD_Init();             //函数声明
  17. ul ADC(unsigned char m);     //函数声明
  18. void Delay200us();         //函数声明
  19. unsigned char code   Disp_Tab[] = {0xd7,0x11,0xcd,0x5d,0x1b,0x5e,0xde,0x15,0xdf,0x5f};  //  数组   0-9
  20. unsigned char code   dispbit[8]={0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0};              //  位选控制 8位
  21.                                                                                         
  22. /************主函数**********************/
  23. void main()
  24. {
  25. ul V1,V2,Int_V1,Int_V2,Int_V1S,Int_V2S,Vcc, Vcc_S;
  26. unsigned char m,M;
  27. P3M1=0x00;
  28. P3M0=0xff;                  //设置P3口强推挽输出
  29. AD_Init();                 //AD初始化
  30. M=1;
  31.               
  32. while(1)
  33. {
  34.     Int_V1S=0;    
  35.     Int_V2S=0;
  36.     Vcc_S=0;
  37.     m=0;
  38.     
  39.     
  40.        if(M==0)                      
  41.     {
  42.         for(m;m<10;m++)
  43.     {
  44.     
  45.     
  46.         Delay200us();            //采样电压等待时间
  47.     
  48.         Int_V1S += ADC(6);
  49.         Delay200us();
  50.         Int_V2S += ADC(3);
  51.         Delay200us();
  52.         Vcc_S += ADC(7);    
  53.         Int_V1 = Int_V1S/10;
  54.         Int_V2 = Int_V2S/10;
  55.         Vcc = Vcc_S/10;        //采样10次电压求平均值
  56.         
  57.     }
  58.     V1=2500*Int_V1/Vcc;
  59.         V2=25*488*Int_V2/Vcc;
  60.     LCD_one(V1);                   //电压显示
  61.     LCD_two(V2);
  62.     if(2500*Int_V1/Vcc>4000)M=1;
  63.     
  64.      }    
  65.      if(M==1)                     //这里的if语句实现量程转换 M==0时ADC通道6-P1.6直接采样电压
  66.     {                             //                         M==1时ADC通道4-P1.4采样电阻分压后的电压
  67.         for(m;m<10;m++)
  68.     {
  69.     
  70.     
  71.         Delay200us();          //采样电压等待时间
  72.         Int_V1S += ADC(4);
  73.         Delay200us();
  74.         Int_V2S += ADC(3);
  75.         Delay200us();
  76.         Vcc_S += ADC(7);    
  77.         Int_V1 = Int_V1S/10;
  78.         Int_V2 = Int_V2S/10;
  79.         Vcc = Vcc_S/10;         //采样10次电压求平均值
  80.         
  81.     }
  82.     V1=2500*5*Int_V1/Vcc;
  83.         V2=25*488*Int_V2/Vcc;
  84.     LCD_one(V1);                //电压显示
  85.     LCD_two(V2);
  86.     if(25*496*Int_V1/Vcc<4000) M=0;
  87.     
  88.      }                
  89.      }    
  90.      }                          
  91.     
  92.         
  93. /*******数码管显示函数*************/
  94. void LCD_one(ul LedNumVal)
  95. {  
  96.    unsigned int LedOut[4];                                //变量定义
  97.     
  98.         if(LedNumVal>9999)
  99.     {
  100.      LedOut[0]=Disp_Tab[LedNumVal%100000/10000];            // 千位          
  101.      LedOut[1]=Disp_Tab[LedNumVal%10000/1000]|0x20;         // 百位    
  102.          LedOut[2]=Disp_Tab[LedNumVal%1000/100];        // 十位
  103.          LedOut[3]=Disp_Tab[LedNumVal%100/10];            // 个位
  104.     }
  105.      if(LedNumVal<10000)    
  106.     {        
  107.      LedOut[0]=Disp_Tab[LedNumVal%10000/1000]|0x20;            // 千位          
  108.      LedOut[1]=Disp_Tab[LedNumVal%1000/100];          // 百位    
  109.          LedOut[2]=Disp_Tab[LedNumVal%100/10];            // 十位
  110.          LedOut[3]=Disp_Tab[LedNumVal%10];            // 个位                  
  111.     }                                //  if语句 实现 小数点自动切换
  112.                 
  113.                 
  114.     P3=LedOut[3];
  115.     P2=dispbit[0];
  116.     P10=1;
  117.     delay(500);
  118.     P10=0;
  119.     
  120.     
  121.     
  122.     P3=LedOut[2];
  123.     P2=dispbit[1];
  124.     P10=1;
  125.     delay(500);
  126.     P10=0;
  127.     
  128.     P3=LedOut[1];
  129.     P2=dispbit[2];
  130.     P10=1;
  131.     delay(500);
  132.     P10=0;
  133.     
  134.     
  135.     P3=LedOut[0];
  136.     P2=dispbit[3];
  137.     P10=1;
  138.     delay(500);
  139.     P10=0;
  140.     
  141.                         
  142.     
  143.   }  
  144.   void LCD_two(ul LedNumVal)
  145. {  
  146.    unsigned int LedOut[4];                            //变量定义
  147.     
  148.         if(LedNumVal>9999)
  149.     {
  150.      LedOut[0]=0x08;                                   //显示负号
  151.      LedOut[1]=Disp_Tab[LedNumVal%100000/10000];                      
  152.      LedOut[2]=Disp_Tab[LedNumVal%10000/1000]|0x20;                    
  153.          LedOut[3]=Disp_Tab[LedNumVal%1000/100];                
  154.                         
  155.     }
  156.      if(LedNumVal<10000)    
  157.     {        
  158.      LedOut[0]=0x08;
  159.      LedOut[1]=Disp_Tab[LedNumVal%10000/1000]|0x20;                  
  160.      LedOut[2]=Disp_Tab[LedNumVal%1000/100];                      
  161.          LedOut[3]=Disp_Tab[LedNumVal%100/10];                    
  162.                                               
  163.     }                             //  if语句 实现 小数点自动切换
  164.                 
  165.                 
  166.     P3=LedOut[3];
  167.     P2=dispbit[4];
  168.     P10=1;
  169.     delay(500);
  170.     P10=0;
  171.     
  172.     
  173.     
  174.     P3=LedOut[2];
  175.     P2=dispbit[5];
  176.     P10=1;
  177.     delay(500);
  178.     P10=0;
  179.     
  180.     P3=LedOut[1];
  181.     P2=dispbit[6];
  182.     P10=1;
  183.     delay(500);
  184.     P10=0;
  185.     
  186.     
  187.     P3=LedOut[0];
  188.     P2=dispbit[7];
  189.     P10=1;
  190.     delay(500);
  191.     P10=0;
  192.     
  193.                         
  194.     
  195.   }  
  196. /***********AD初始化***************/
  197. void AD_Init()
  198. {
  199. P1M1=0xfe;
  200. P1M0=0x08;    //设置高阻和开漏,ADC采样运放输出端电压时需要断开相应I/O口内部上拉,即开漏输入
  201. ADC_RES=0x00;
  202. ADC_RESL=0x00;
  203. P1ASF=0xfe;
  204. ADC_CONTR=ADC_POWER|ADC_speed_LL;
  205. Delay1ms();    
  206. }
  207. /*********电压采样*********/
  208. ul ADC(unsigned char m)
  209. {
  210.     if(m==3)
  211.     {
  212.         ADC_CONTR &=0xf8;        //清空通道
  213.         ADC_CONTR |=0x03;     //更换通道
  214.         Delay150us();         //更换通道延时
  215.     }    
  216.     if(m==4)
  217.     {
  218.         ADC_CONTR &=0xf8;
  219.         ADC_CONTR |=0x04;
  220.         Delay150us();
  221.     }    
  222.     if(m==6)
  223.     {
  224.         ADC_CONTR &=0xf8;
  225.         ADC_CONTR |=0x06;
  226.         Delay150us();
  227.     }
  228.     if(m==7)
  229.     {
  230.         ADC_CONTR &=0xf8;
  231.         ADC_CONTR |=0x07;
  232.         Delay150us();
  233.     }    
  234.     ADC_CONTR |=ADC_START;           //开启AD转换
  235.     _nop_();
  236.     _nop_();
  237.     _nop_();
  238.     _nop_();
  239.     while(!(ADC_CONTR & 0x10));  
  240.     ADC_CONTR &= ~ADC_FLAG;
  241.     ADC_RES = (ADC_RES<<2)|ADC_RESL;   //高八位按位左移2位与低两位结果按位或运算得到10位转换结果
  242.     return ADC_RES;               //返回10位AD转换结果
  243. }
  244. /*******************延时函数**********/
  245. void delay(unsigned int x)
  246. {
  247.         char j;
  248.         for(x; x> 0; x--)
  249.         for(j = 400; j > 0; j--);
  250. }
  251. void Delay1ms()        //@12.000MHz
  252. {
  253.     unsigned char i, j;
  254.     i = 2;
  255.     j = 239;
  256.     do
  257.     {
  258.         while (--j);
  259.     } while (--i);
  260. }
  261. void Delay150us()        //@12.000MHz
  262. {
  263.     unsigned char i, j;
  264.     i = 2;
  265.     j = 189;
  266.     do
  267.     {
  268.         while (--j);
  269.     } while (--i);
  270. }
  271. void Delay200us()        //@12.000MHz
  272. {
  273.     unsigned char i;
  274.     _nop_();
  275.     i = 97;
  276.     while (--i);
  277. }



关键词: 可调     稳压电源     电压     同步     显示     代码     电压表         

菜鸟
2015-08-03 22:54:11    评分
2楼

楼主,可否加个qq,有的地方不懂想跟你交流


菜鸟
2016-05-29 13:17:25    评分
3楼
不错啊

菜鸟
2016-06-10 21:53:09    评分
4楼
很厉害

专家
2016-06-10 23:23:54    评分
5楼
不错的DIY。支持一下。

菜鸟
2016-10-01 17:01:09    评分
6楼
不明觉厉

专家
2016-12-02 07:47:35    评分
7楼
厉害

工程师
2016-12-06 16:33:27    评分
8楼
围观下,呵呵!收藏了

共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]