我的账户
中国电子DIY

科技成就未来

亲爱的游客,欢迎!

已有账号,请

如尚未注册?

基于BUCK型开关电源的数控恒流源(大于200——2000ma输出范围)

[复制链接]
21509 41
834771730 发表于 2013-8-5 21:51:10 | 只看该作者 |只看大图 |阅读模式 打印 上一主题 下一主题
作品工作原理:
本设计由输入回路、输出回路和MCU控制回路三大部分构成。
直流输入电压(DC)经EMI滤波电路滤除来自输入电源的杂波,MCU数控部分控制输出一个最小电流值,系统稳定后,通过键盘模块输入一个预定的电流值,系统输出电流通过取样电阻得到一个取样电压,经OP07放大后作为反馈电压,反馈电压和输出电流有一个对应关系,反馈电压经12位的ADS7818进行AD转换后交由MCU处理,MCU对采样电压进行中值滤波后,计算出此时电压对应的电流值,并用LCD1602显示出来。同时,MCU将滤波后的取样电压对应的电流值和键盘设置的电流值进行比较,然后通过PID算法,对DAC7611的输出进行控制,DA的输出连接到SG3524开关芯片的参考电压,进而控制PWM从而控制输出电流和设定电流想跟随。由此实现恒流的输出。
作品功能介绍:
本作品作为一个高效的数控恒流电源,真正实现了:
1.     由于使用了BUCK型开关模型,使得输出2000ma时整个系统效率高达87%
2.     负载在5Ω时,输出电流Io在200—2000ma之间实现1ma步进 ;
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #include<math.h>
  4. #define uint unsigned int //预定义一下
  5. #define uchar unsigned char
  6. uint AD;
  7. sbit Bell=P0^3;
  8. sbit rs=P0^2; //1602的数据/指令选择控制线
  9. sbit rw=P0^1; //1602的读写控制线
  10. sbit en=P0^0; //1602的使能控制线
  11. sbit ADCON=P2^7;
  12. sbit ADCLK=P2^5;
  13. sbit ADDATA=P2^6;
  14. sbit CS =P2^4; //输出片选信号
  15. sbit CLK=P2^3; //输出时钟
  16. sbit SDI=P2^2; //输出数据
  17. sbit LD=P2^1; //输出数/模转换过程启动信号
  18. sbit DEC20=P3^0; //看门狗复位
  19. sbit DEC5=P3^1;
  20. sbit ADD20=P3^2;
  21. sbit ADD5=P3^3;
  22. //sbit DEC1=P3^4;
  23. //sbit DEC10=P3^5;
  24. //sbit DEC100=P3^6;
  25. sbit P34=P3^4;
  26. sbit P35=P3^5;
  27. sbit P36=P3^6;
  28. sbit P37=P3^7;
  29. unsigned char flag=0;
  30. uint Vad,Vda,Iset;
  31. long int Va,Ireal;


  32. /*P1口接1602的D0~D7*/
  33. uchar code table[16] ="Iset : mA "; //要显示的内容1放入数组tablel
  34. uchar code table1[16]="Ireal : mA "; //要显示的内容2放入数组table1
  35. uchar Vo[5]="0000";
  36. uchar Io[5]="0000";
  37. /*****延时函数 *****/
  38. void delay(uint n)
  39. {
  40. uint x,y;
  41. for(x=n;x>0;x--)
  42. for(y=210;y>0;y--);
  43. }

  44. unsigned int ADconv()
  45. {
  46. unsigned char i;
  47. uint ADValue=0;
  48. // AD=ADconv();
  49. ADCON=0; //产生的下跳边沿,启动AD转换
  50. _nop_(); //延时给ADS7818以启动转换响应时间
  51. _nop_();
  52. ADCLK=1; //第一个时钟信号
  53. _nop_();
  54. _nop_();
  55. ADCLK=0;
  56. _nop_();
  57. _nop_();
  58. _nop_();
  59. _nop_();
  60. ADCLK=1; //在第二个时钟的上升沿将转换结果移出ADS7818
  61. _nop_();
  62. _nop_(); //准备送后12个时钟脉冲
  63. for(i=0;i<=12;i++)
  64. {
  65. if(ADDATA)
  66. ADValue|=0x001; //末位置1
  67. ADValue=ADValue<<1;
  68. ADCLK=0;
  69. _nop_();
  70. _nop_();
  71. _nop_();
  72. _nop_();
  73. ADCLK=1;
  74. _nop_();
  75. _nop_();
  76. }
  77. ADCON=1; //CONV引脚拉高,为下次转换做准备
  78. ADCLK=0; //本次转换已完成,拉低CLK端,也可以拉高
  79. ADDATA=1; //拉低ADDATA端,回到初始状态
  80. return(ADValue);//返回转换结果

  81. }


  82. /******初始化DAC7611*******/
  83. void init_da(void)
  84. {
  85. LD=0; // 装载引脚置低
  86. CS=1; //片选置高
  87. CLK=1; //时钟置高
  88. SDI=0;
  89. }
  90. /*****时钟脉冲子函数***********/
  91. void clock(void)
  92. {
  93. CLK=0;
  94. _nop_();
  95. CLK=1; //产生一个时钟脉冲
  96. _nop_();
  97. }
  98. /******DAC7611转换***************/
  99. void DAC_7611(uint vol)
  100. {
  101. uint i,j;
  102. vol<<=4;
  103. LD=1; //装载引脚置高
  104. _nop_();
  105. CS=0; //片选拉低,准备转换
  106. for(i=0;i<12;i++)
  107. {
  108. j=vol;
  109. SDI=j&0x8000;
  110. clock();
  111. vol<<=1;
  112. }
  113. CLK=1; // 输出时钟置高
  114. _nop_();
  115. CS=1; //DAC7611片选引脚CS置高
  116. _nop_();
  117. LD=0; //装载引脚LD置低以启动数模转换
  118. _nop_();
  119. _nop_();
  120. _nop_();
  121. _nop_();
  122. _nop_();
  123. _nop_();
  124. _nop_();
  125. _nop_();
  126. _nop_();
  127. _nop_();
  128. _nop_();
  129. _nop_();
  130. _nop_();
  131. _nop_();
  132. _nop_(); //延时一会,使输出模拟电压达到稳定
  133. LD=1; //LD置高
  134. }




  135. void lcd_wcom(uchar com) //1602写命令函数
  136. {
  137. rs=0; //选择指令寄存器
  138. rw=0; //选择写
  139. P1=com; //把命令字送入P2
  140. delay(5); //延时一小会儿,让1602准备接收数据
  141. en=1; //使能线电平变化,命令送入1602的8位数据口
  142. en=0;
  143. }
  144. void lcd_wdat(uchar dat) //1602写数据函数
  145. {
  146. rs=1; //选择数据寄存器
  147. rw=0; //选择写
  148. P1=dat; //把要显示的数据送入P2
  149. delay(5); //延时一小会儿,让1602准备接收数据
  150. en=1; //使能线电平变化,数据送入1602的8位数据口
  151. en=0;
  152. }
  153. void lcd_init() //1602初始化函数
  154. {
  155. lcd_wcom(0x38); //8位数据,双列,5*7字形
  156. lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁
  157. lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
  158. lcd_wcom(0x01); //清屏
  159. }

  160. void InitTimer0(void)
  161. {
  162. TMOD = 0x01;
  163. TH0 = 0x4C;
  164. TL0 = 0x00;
  165. EA = 1;
  166. ET0 = 1;
  167. TR0 = 1;
  168. }

  169. /*********喂狗*******
  170. void dog()
  171. {
  172. RE=0;
  173. _nop_();
  174. _nop_();
  175. RE=1;
  176. } */

  177. void update1602(unsigned int x,unsigned int y)
  178. {
  179. unsigned int _temp=0;
  180. unsigned char i=0;
  181. _temp=x;
  182. if(_temp>=9999)_temp=9999;
  183. Vo[0]=(_temp/1000) + 0x30;//千
  184. Vo[1]=(_temp%1000/100) + 0x30;//百
  185. Vo[2]=(_temp%100/10) + 0x30;//十
  186. Vo[3]=(_temp%10) + 0x30;//个

  187. _temp=y;
  188. if(_temp>=9999)_temp=9999;
  189. Io[0]=(_temp/1000 ) + 0x30;//千
  190. Io[1]=(_temp%1000/100) + 0x30;//百
  191. Io[2]=(_temp%100/10 ) + 0x30;//十
  192. Io[3]=(_temp%10 ) + 0x30;//个

  193. lcd_wcom(0x88); //上排第8位
  194. for(i=0;i<4;i++) //将Vo[]中的数据依次写入1602显示
  195. {
  196. lcd_wdat(Vo[i]);
  197. //delay(200);
  198. }

  199. lcd_wcom(0x80+0x48); //下排第8位
  200. for(i=0;i<4;i++) //将table1[]中的数据依次写入1602显示
  201. {
  202. lcd_wdat(Io[i]);
  203. //delay(200);
  204. }


  205. }

  206. /*******键盘函数******/
  207. void keyscan()
  208. {
  209. uchar keval;
  210. P3=0xfe;
  211. if(P34==0)
  212. keval=13;
  213. if(P35==0)
  214. keval=14;
  215. if(P36==0)
  216. keval=15;
  217. if(P37==0)
  218. keval=16;

  219. P3=0xfd;
  220. if(P34==0)
  221. keval=9;
  222. if(P35==0)
  223. keval=10;
  224. if(P36==0)
  225. keval=11;
  226. if(P37==0)
  227. keval=12;

  228. P3=0xfb;
  229. if(P34==0)
  230. keval=5;
  231. if(P35==0)
  232. keval=6;
  233. if(P36==0)
  234. keval=7;
  235. if(P37==0)
  236. keval=8;

  237. P3=0xf7;
  238. if(P34==0)
  239. keval=1;
  240. if(P35==0)
  241. keval=2;
  242. if(P36==0)
  243. keval=3;
  244. if(P37==0)
  245. keval=4;



  246. }
  247. /*******AD中位值平均滤波******/
  248. #define N 12
  249. char filter()
  250. {
  251. char count,i,j;
  252. int value_buf[N];
  253. uint temp;
  254. int sum=0;
  255. for (count=0;count<N;count++)
  256. {
  257. value_buf[count] =ADconv();
  258. delay(1);
  259. }
  260. for (j=0;j<N-1;j++)
  261. {
  262. for (i=0;i<N-j;i++)
  263. {
  264. if ( value_buf[i]>value_buf[i+1] )
  265. {
  266. temp = value_buf[i] ;
  267. value_buf[i] = value_buf[i+1];
  268. value_buf[i+1] = temp;
  269. }
  270. }
  271. }
  272. for(count=1;count<N-1;count++)
  273. sum += value_buf[count];
  274. return (char)(sum/(N-2));
  275. }

  276. /********主函数 ********/
  277. void main()
  278. {
  279. uint keval;
  280. // uchar ADValue;
  281. uchar n,m=0;
  282. uint Vda=760;
  283. Iset=170;
  284. P37=0;
  285. //Bell=0;
  286. InitTimer0();
  287. lcd_init(); //液晶初始化
  288. lcd_wcom(0x80); //显示地址设为80H(即00H,)上排第一位
  289. for(m=0;m<15;m++) //将table[]中的数据依次写入1602显示
  290. {
  291. lcd_wdat(table[m]);
  292. //delay(200);
  293. }
  294. lcd_wcom(0x80+0x40); //重新设定显示地址为0xc4,即下排第0位
  295. for(n=0;n<15;n++) //将table1[]中的数据依次写入1602显示
  296. {
  297. lcd_wdat(table1[n]);
  298. //delay(200);
  299. }
  300. while(1)
  301. {

  302. //dog();
  303. //P3=0xf0;



  304. init_da();
  305. DAC_7611(Vda);
  306. AD=ADconv();
  307. AD=AD/2;
  308. Vad=(long int)AD*625/512;
  309. if(Vad<820)
  310. {
  311. Bell=1;
  312. //delay(60);
  313. }
  314. if(Vad>900)
  315. {
  316. Bell=0;
  317. }
  318. //AD=filter();
  319. if(Vad<0)
  320. {
  321. Vad=0;
  322. }
  323. if(1080>Vad>0)
  324. {
  325. Ireal=(long int)Vad*3/4-512;
  326. }
  327. if(1080<Vad<1330)
  328. {
  329. Ireal=(long int)Vad*183/250-490;
  330. }
  331. if(1330<Vad<1670)
  332. {
  333. Ireal=(long int)Vad*789/1000-570;
  334. }

  335. if(1670<Vad<1840)
  336. {
  337. Ireal=(long int)Vad*423/500-671;
  338. }
  339. if(1840<Vad<2020)
  340. {
  341. Ireal=(long int)Vad*371/500-484;
  342. }
  343. if(2020<Vad<2290)
  344. {
  345. Ireal=(long int)Vad*421/625-334;
  346. }
  347. if(2290<Vad<2560)
  348. {
  349. Ireal=(long int)Vad*151/200-502;
  350. }
  351. if(2560<Vad<2990)
  352. {
  353. Ireal=(long int)Vad*97/125-561;
  354. }
  355. if(2990<Vad)
  356. {
  357. Ireal=(long int)Vad*161/200-637;
  358. }

  359. if(DEC20==0)
  360. { delay(60);
  361. if(DEC20==0)
  362. {
  363. Iset=Iset-20;
  364. }
  365. }
  366. if(DEC5==0)
  367. {
  368. delay(60);
  369. if(DEC5==0)
  370. {
  371. Iset=Iset-5;
  372. }
  373. }
  374. if(ADD20==0)
  375. { delay(60);
  376. if(ADD20==0)
  377. {
  378. Iset=Iset+20;
  379. }
  380. }
  381. if(ADD5==0)
  382. {
  383. delay(60);
  384. if(ADD5==0)
  385. {
  386. Iset=Iset+5;
  387. }
  388. }


  389. if(Iset>Ireal)
  390. {
  391. Vda++;
  392. }
  393. if(Iset<Ireal)
  394. {
  395. Vda--;
  396. }

  397. if(flag)
  398. {
  399. flag=0;
  400. //RE=1;
  401. //AD=ADconv();
  402. //AD=AD/2;
  403. Vad=(long int)AD*625/512;
  404. // Vad=Va&0xffff;

  405. update1602(Iset,Ireal);
  406. }

  407. } ;

  408. }//动态停机

  409. void Time1() interrupt 1
  410. { uint Vb=0;
  411. static unsigned char i=0;
  412. TH0 = 0x4C;
  413. TL0 = 0x00;
  414. i++;
  415. AD=ADconv();
  416. Vb=Vb+AD;
  417. if(i==20)
  418. {
  419. i=0;
  420. AD=Vb/20;
  421. flag=1;
  422. //AD=Va>>4;
  423. // RE=0;
  424. delay(20);

  425. }
  426. }






复制代码

3.     Ui从12V变到18V时,电流调整率SI =2%  <4% ;
4.     Ui=15V, Io=1000mA,负载在1Ω~5Ω条件下,改变负载电阻,输出电压在10V以内变化时,负载调整率SR=3% <4% ;
5.     Ui=15V,Io=1000mA条件下,具有过压保护功能,动作电压Uoth=11 V ;
6.     排除过压故障后,电源能自动恢复为正常状态 ;
7.     具有输出电流的测量和数字显示功能 ;
8.     输入电压波动范围为8V~20V ;
9.     系统内部使用了二级共模滤波和一级π型滤波,把输出电流的纹波降低至4ma,达到了高端电源的输出性能 ;
10.  更突出的是,此电源还有红外遥控扩展功能和空载声光报警功能。极大地扩大了其适用范围。

功率模块.jpg (83.01 KB, 下载次数: 31)

功率模块

功率模块

控制模块.jpg (38.39 KB, 下载次数: 19)

控制模块

控制模块

整体效果图.jpg (42.21 KB, 下载次数: 36)

整体效果图

整体效果图

IMG_20130805_205036.jpg (93.38 KB, 下载次数: 32)

IMG_20130805_205036.jpg

IMG_20130805_205102.jpg (88.93 KB, 下载次数: 30)

两级运放和一个累加器

两级运放和一个累加器

IMG_20130805_205133.jpg (111.84 KB, 下载次数: 26)

功率模块和键盘模块的印刷板部分

功率模块和键盘模块的印刷板部分

IMG_20130805_205244.jpg (104.51 KB, 下载次数: 26)

下面一层是给各芯片供电的电源模块

下面一层是给各芯片供电的电源模块

IMG_20130805_205419.jpg (64.33 KB, 下载次数: 26)

自制双面板

自制双面板

IMG_20130805_205530.jpg (77.27 KB, 下载次数: 26)

将升压模块取下后

将升压模块取下后

IMG_20130805_205622.jpg (67.66 KB, 下载次数: 26)

升压模块

升压模块

IMG_20130805_205826.jpg (99.78 KB, 下载次数: 17)

数控部分

数控部分

WP_20130805_002.jpg (61.87 KB, 下载次数: 23)

功率部分的PCB打印

功率部分的PCB打印

WP_20130805_003.jpg (53.47 KB, 下载次数: 25)

控制部分PCB

控制部分PCB

WP_20130805_005.jpg (45.91 KB, 下载次数: 22)

制板腐蚀的工具

制板腐蚀的工具

恒流源原理图和数控部分PCB.zip

5.43 MB, 下载次数: 1398, 下载积分: 下载币 -5

自己设计,还望各位大神指教

参与人数 5贡献 +10 刀币 +55 收起 理由
bluemarlin + 10
虫子先生 + 10 + 10
ozhaojie + 10
goodays + 15 看样子效果不错。
diyhome + 10

查看全部评分总评分 : 贡献 +10 刀币 +55

收藏
收藏9
分享
分享
支持
支持1
反对
反对0

精彩评论41

跳转到指定楼层
2#
 楼主| 834771730 发表于 2013-8-5 21:53:16 | 只看该作者
谢谢各位指教,一些简单的功能模块没上传,比如键盘模块,如有需要,可留言...
3#
 楼主| 834771730 发表于 2013-8-5 22:02:08 | 只看该作者
该设计已经拓展了红外控制,只是因为有了键盘输入,红外部分可以正常工作但程序里每加入。有兴趣的可以按原理图做出来,加上红外控制
4#
hw1999 发表于 2013-8-5 22:03:06 | 只看该作者
高手。。。。。。。。。。。。
5#
hyl 发表于 2013-8-5 22:03:25 | 只看该作者
好强大的制作,
焊点还可以做得漂亮点。
6#
 楼主| 834771730 发表于 2013-8-5 22:05:41 | 只看该作者
电路板做出来有一个多月了表面没涂松香或者绝缘漆之类的保护层,加上环境湿热,铜皮已经氧化的有点难看,大家凑活着看吧,有啥问题可以加我QQ(账号既是),我们可以进一步探讨...
7#
luokai 发表于 2013-8-5 22:40:33 | 只看该作者
虽不懂 但觉厉
8#
ozhaojie 发表于 2013-8-5 23:22:23 | 只看该作者
刷一下绝缘漆会更好看
9#
hlmwf1314 发表于 2013-8-7 18:10:22 | 只看该作者
厉害 本人最近也在学习电源
10#
dabaimao 发表于 2013-8-7 18:42:00 | 只看该作者
厉害呀我一直想做一个
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关注我们
中国电子DIY官方微信

客服电话:000-000-0000

客服邮箱:776513803@qq.com

周一至周五 9:00-18:00

公司地址:深圳市南山区美丽湾大厦B座

Powered by Discuz! X3.4@ 2001-2013 Comsenz Inc.