这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 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
  2. #include
  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. void main()
  23. {
  24. ul V1,V2,Int_V1,Int_V2,Int_V1S,Int_V2S,Vcc, Vcc_S;
  25. unsigned char m,M;
  26. P3M1=0x00;
  27. P3M0=0xff; //设置P3口强推挽输出
  28. AD_Init(); //AD初始化
  29. M=1;
  30. while(1)
  31. {
  32. Int_V1S=0;
  33. Int_V2S=0;
  34. Vcc_S=0;
  35. m=0;
  36. if(M==0)
  37. {
  38. for(m;m<10;m++)
  39. {
  40. Delay200us(); //采样电压等待时间
  41. Int_V1S += ADC(6);
  42. Delay200us();
  43. Int_V2S += ADC(3);
  44. Delay200us();
  45. Vcc_S += ADC(7);
  46. Int_V1 = Int_V1S/10;
  47. Int_V2 = Int_V2S/10;
  48. Vcc = Vcc_S/10; //采样10次电压求平均值
  49. }
  50. V1=2500*Int_V1/Vcc;
  51. V2=25*488*Int_V2/Vcc;
  52. LCD_one(V1); //电压显示
  53. LCD_two(V2);
  54. if(2500*Int_V1/Vcc>4000)M=1;
  55. }
  56. if(M==1) //这里的if语句实现量程转换 M==0时ADC通道6-P1.6直接采样电压
  57. { // M==1时ADC通道4-P1.4采样电阻分压后的电压
  58. for(m;m<10;m++)
  59. {
  60. Delay200us(); //采样电压等待时间
  61. Int_V1S += ADC(4);
  62. Delay200us();
  63. Int_V2S += ADC(3);
  64. Delay200us();
  65. Vcc_S += ADC(7);
  66. Int_V1 = Int_V1S/10;
  67. Int_V2 = Int_V2S/10;
  68. Vcc = Vcc_S/10; //采样10次电压求平均值
  69. }
  70. V1=2500*5*Int_V1/Vcc;
  71. V2=25*488*Int_V2/Vcc;
  72. LCD_one(V1); //电压显示
  73. LCD_two(V2);
  74. if(25*496*Int_V1/Vcc<4000) M=0;
  75. }
  76. }
  77. }
  78. /*******数码管显示函数*************/
  79. void LCD_one(ul LedNumVal)
  80. {
  81. unsigned int LedOut[4]; //变量定义
  82. if(LedNumVal>9999)
  83. {
  84. LedOut[0]=Disp_Tab[LedNumVal%100000/10000]; // 千位
  85. LedOut[1]=Disp_Tab[LedNumVal%10000/1000]|0x20; // 百位
  86. LedOut[2]=Disp_Tab[LedNumVal%1000/100]; // 十位
  87. LedOut[3]=Disp_Tab[LedNumVal%100/10]; // 个位
  88. }
  89. if(LedNumVal<10000)
  90. {
  91. LedOut[0]=Disp_Tab[LedNumVal%10000/1000]|0x20; // 千位
  92. LedOut[1]=Disp_Tab[LedNumVal%1000/100]; // 百位
  93. LedOut[2]=Disp_Tab[LedNumVal%100/10]; // 十位
  94. LedOut[3]=Disp_Tab[LedNumVal%10]; // 个位
  95. } // if语句 实现 小数点自动切换
  96. P3=LedOut[3];
  97. P2=dispbit[0];
  98. P10=1;
  99. delay(500);
  100. P10=0;
  101. P3=LedOut[2];
  102. P2=dispbit[1];
  103. P10=1;
  104. delay(500);
  105. P10=0;
  106. P3=LedOut[1];
  107. P2=dispbit[2];
  108. P10=1;
  109. delay(500);
  110. P10=0;
  111. P3=LedOut[0];
  112. P2=dispbit[3];
  113. P10=1;
  114. delay(500);
  115. P10=0;
  116. }
  117. void LCD_two(ul LedNumVal)
  118. {
  119. unsigned int LedOut[4]; //变量定义
  120. if(LedNumVal>9999)
  121. {
  122. LedOut[0]=0x08; //显示负号
  123. LedOut[1]=Disp_Tab[LedNumVal%100000/10000];
  124. LedOut[2]=Disp_Tab[LedNumVal%10000/1000]|0x20;
  125. LedOut[3]=Disp_Tab[LedNumVal%1000/100];
  126. }
  127. if(LedNumVal<10000)
  128. {
  129. LedOut[0]=0x08;
  130. LedOut[1]=Disp_Tab[LedNumVal%10000/1000]|0x20;
  131. LedOut[2]=Disp_Tab[LedNumVal%1000/100];
  132. LedOut[3]=Disp_Tab[LedNumVal%100/10];
  133. } // if语句 实现 小数点自动切换
  134. P3=LedOut[3];
  135. P2=dispbit[4];
  136. P10=1;
  137. delay(500);
  138. P10=0;
  139. P3=LedOut[2];
  140. P2=dispbit[5];
  141. P10=1;
  142. delay(500);
  143. P10=0;
  144. P3=LedOut[1];
  145. P2=dispbit[6];
  146. P10=1;
  147. delay(500);
  148. P10=0;
  149. P3=LedOut[0];
  150. P2=dispbit[7];
  151. P10=1;
  152. delay(500);
  153. P10=0;
  154. }
  155. /***********AD初始化***************/
  156. void AD_Init()
  157. {
  158. P1M1=0xfe;
  159. P1M0=0x08; //设置高阻和开漏,ADC采样运放输出端电压时需要断开相应I/O口内部上拉,即开漏输入
  160. ADC_RES=0x00;
  161. ADC_RESL=0x00;
  162. P1ASF=0xfe;
  163. ADC_CONTR=ADC_POWER|ADC_speed_LL;
  164. Delay1ms();
  165. }
  166. /*********电压采样*********/
  167. ul ADC(unsigned char m)
  168. {
  169. if(m==3)
  170. {
  171. ADC_CONTR &=0xf8; //清空通道
  172. ADC_CONTR |=0x03; //更换通道
  173. Delay150us(); //更换通道延时
  174. }
  175. if(m==4)
  176. {
  177. ADC_CONTR &=0xf8;
  178. ADC_CONTR |=0x04;
  179. Delay150us();
  180. }
  181. if(m==6)
  182. {
  183. ADC_CONTR &=0xf8;
  184. ADC_CONTR |=0x06;
  185. Delay150us();
  186. }
  187. if(m==7)
  188. {
  189. ADC_CONTR &=0xf8;
  190. ADC_CONTR |=0x07;
  191. Delay150us();
  192. }
  193. ADC_CONTR |=ADC_START; //开启AD转换
  194. _nop_();
  195. _nop_();
  196. _nop_();
  197. _nop_();
  198. while(!(ADC_CONTR & 0x10));
  199. ADC_CONTR &= ~ADC_FLAG;
  200. ADC_RES = (ADC_RES<<2)|ADC_RESL; //高八位按位左移2位与低两位结果按位或运算得到10位转换结果
  201. return ADC_RES; //返回10位AD转换结果
  202. }
  203. /*******************延时函数**********/
  204. void delay(unsigned int x)
  205. {
  206. char j;
  207. for(x; x> 0; x--)
  208. for(j = 400; j > 0; j--);
  209. }
  210. void Delay1ms() //@12.000MHz
  211. {
  212. unsigned char i, j;
  213. i = 2;
  214. j = 239;
  215. do
  216. {
  217. while (--j);
  218. } while (--i);
  219. }
  220. void Delay150us() //@12.000MHz
  221. {
  222. unsigned char i, j;
  223. i = 2;
  224. j = 189;
  225. do
  226. {
  227. while (--j);
  228. } while (--i);
  229. }
  230. void Delay200us() //@12.000MHz
  231. {
  232. unsigned char i;
  233. _nop_();
  234. i = 97;
  235. while (--i);
  236. }



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

菜鸟
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 跳转至

回复

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