水平有限,画电压表电路图有压力,有机会尽量补上
发出来给新手看一下,写了一下制作过程中遇到的一些问题,有些错误的地方请大家提出来
电源参数:
可调电压范围±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级减小。分析原因:变压器功率不足,散热片散热能力不够。)
电路图采用的是LM317和LM337基本应用电路,稍微作了一些修改。由于LM317的基准电压是1.25V,输出电压下限为1.25V,所以需要在它的输出接地端需要外加一个-1.25V的电压来抵消它的基准电压,从而实现输出0V起调;LM337同理,在电位器和地之间接一个1.25V的电压来抵消-1.25V,这里使用了2个1.235V的电压基准,就是图中的LM385-1.2,与之串联的电阻和LED分别用来限流和做指示灯。关于电容的选择,104用来减少高频干扰,焊接电路时离稳压片输入端越近越好;4.7uf的小电容用来稳定稳压片的工作;2200uf大电容,用来滤低频波,使输出电压平滑稳定,如果需要输出大电流需要加大电容容量,并加大功率三极管扩大输出电流。
关于数码管电压实时显示,使用的是STC15F204EA单片机(单片机自带8通道10位AD转换功能),电压表供电由该电源提供,使用LM7815和LM7815稳压给运放供电,使用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='宋体']
秀秀我的书桌,工具不多,暂时够用了~~
[电压表程序,自己胡乱写的,哪位高手能帮忙改一下,提高一下效率
- #include<stc15f204ea.h>
- #include<intrins.h>
- #define ADC_POWER 0x80 //ADC 电源控制位
- #define ADC_FLAG 0x10 //ADC 完成标志
- #define ADC_START 0x08 //ADC 启动控制位
- #define ADC_speed_LL 0x00 //540 时钟
- #define ADC_speed_L 0x20 //360 时钟
- #define ADC_speed_H 0x40 //180 时钟
- #define ADC_speed_HH 0x60 // 90 时钟
- typedef unsigned long ul;
- void delay(unsigned int x); //函数声明
- void LCD_one(ul LedNumVal); //函数声明
- void LCD_two(ul LedNumVal); //函数声明
- void Delay1ms(); //函数声明
- void Delay150us(); //函数声明
- void AD_Init(); //函数声明
- ul ADC(unsigned char m); //函数声明
- void Delay200us(); //函数声明
- unsigned char code Disp_Tab[] = {0xd7,0x11,0xcd,0x5d,0x1b,0x5e,0xde,0x15,0xdf,0x5f}; // 数组 0-9
- unsigned char code dispbit[8]={0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0}; // 位选控制 8位
- /************主函数**********************/
- void main()
- {
- ul V1,V2,Int_V1,Int_V2,Int_V1S,Int_V2S,Vcc, Vcc_S;
- unsigned char m,M;
- P3M1=0x00;
- P3M0=0xff; //设置P3口强推挽输出
- AD_Init(); //AD初始化
- M=1;
- while(1)
- {
- Int_V1S=0;
- Int_V2S=0;
- Vcc_S=0;
- m=0;
- if(M==0)
- {
- for(m;m<10;m++)
- {
- Delay200us(); //采样电压等待时间
- Int_V1S += ADC(6);
- Delay200us();
- Int_V2S += ADC(3);
- Delay200us();
- Vcc_S += ADC(7);
- Int_V1 = Int_V1S/10;
- Int_V2 = Int_V2S/10;
- Vcc = Vcc_S/10; //采样10次电压求平均值
- }
- V1=2500*Int_V1/Vcc;
- V2=25*488*Int_V2/Vcc;
- LCD_one(V1); //电压显示
- LCD_two(V2);
- if(2500*Int_V1/Vcc>4000)M=1;
- }
- if(M==1) //这里的if语句实现量程转换 M==0时ADC通道6-P1.6直接采样电压
- { // M==1时ADC通道4-P1.4采样电阻分压后的电压
- for(m;m<10;m++)
- {
- Delay200us(); //采样电压等待时间
- Int_V1S += ADC(4);
- Delay200us();
- Int_V2S += ADC(3);
- Delay200us();
- Vcc_S += ADC(7);
- Int_V1 = Int_V1S/10;
- Int_V2 = Int_V2S/10;
- Vcc = Vcc_S/10; //采样10次电压求平均值
- }
- V1=2500*5*Int_V1/Vcc;
- V2=25*488*Int_V2/Vcc;
- LCD_one(V1); //电压显示
- LCD_two(V2);
- if(25*496*Int_V1/Vcc<4000) M=0;
- }
- }
- }
- /*******数码管显示函数*************/
- void LCD_one(ul LedNumVal)
- {
- unsigned int LedOut[4]; //变量定义
- if(LedNumVal>9999)
- {
- LedOut[0]=Disp_Tab[LedNumVal%100000/10000]; // 千位
- LedOut[1]=Disp_Tab[LedNumVal%10000/1000]|0x20; // 百位
- LedOut[2]=Disp_Tab[LedNumVal%1000/100]; // 十位
- LedOut[3]=Disp_Tab[LedNumVal%100/10]; // 个位
- }
- if(LedNumVal<10000)
- {
- LedOut[0]=Disp_Tab[LedNumVal%10000/1000]|0x20; // 千位
- LedOut[1]=Disp_Tab[LedNumVal%1000/100]; // 百位
- LedOut[2]=Disp_Tab[LedNumVal%100/10]; // 十位
- LedOut[3]=Disp_Tab[LedNumVal%10]; // 个位
- } // if语句 实现 小数点自动切换
- P3=LedOut[3];
- P2=dispbit[0];
- P10=1;
- delay(500);
- P10=0;
- P3=LedOut[2];
- P2=dispbit[1];
- P10=1;
- delay(500);
- P10=0;
- P3=LedOut[1];
- P2=dispbit[2];
- P10=1;
- delay(500);
- P10=0;
- P3=LedOut[0];
- P2=dispbit[3];
- P10=1;
- delay(500);
- P10=0;
- }
- void LCD_two(ul LedNumVal)
- {
- unsigned int LedOut[4]; //变量定义
- if(LedNumVal>9999)
- {
- LedOut[0]=0x08; //显示负号
- LedOut[1]=Disp_Tab[LedNumVal%100000/10000];
- LedOut[2]=Disp_Tab[LedNumVal%10000/1000]|0x20;
- LedOut[3]=Disp_Tab[LedNumVal%1000/100];
- }
- if(LedNumVal<10000)
- {
- LedOut[0]=0x08;
- LedOut[1]=Disp_Tab[LedNumVal%10000/1000]|0x20;
- LedOut[2]=Disp_Tab[LedNumVal%1000/100];
- LedOut[3]=Disp_Tab[LedNumVal%100/10];
- } // if语句 实现 小数点自动切换
- P3=LedOut[3];
- P2=dispbit[4];
- P10=1;
- delay(500);
- P10=0;
- P3=LedOut[2];
- P2=dispbit[5];
- P10=1;
- delay(500);
- P10=0;
- P3=LedOut[1];
- P2=dispbit[6];
- P10=1;
- delay(500);
- P10=0;
- P3=LedOut[0];
- P2=dispbit[7];
- P10=1;
- delay(500);
- P10=0;
- }
- /***********AD初始化***************/
- void AD_Init()
- {
- P1M1=0xfe;
- P1M0=0x08; //设置高阻和开漏,ADC采样运放输出端电压时需要断开相应I/O口内部上拉,即开漏输入
- ADC_RES=0x00;
- ADC_RESL=0x00;
- P1ASF=0xfe;
- ADC_CONTR=ADC_POWER|ADC_speed_LL;
- Delay1ms();
- }
- /*********电压采样*********/
- ul ADC(unsigned char m)
- {
- if(m==3)
- {
- ADC_CONTR &=0xf8; //清空通道
- ADC_CONTR |=0x03; //更换通道
- Delay150us(); //更换通道延时
- }
- if(m==4)
- {
- ADC_CONTR &=0xf8;
- ADC_CONTR |=0x04;
- Delay150us();
- }
- if(m==6)
- {
- ADC_CONTR &=0xf8;
- ADC_CONTR |=0x06;
- Delay150us();
- }
- if(m==7)
- {
- ADC_CONTR &=0xf8;
- ADC_CONTR |=0x07;
- Delay150us();
- }
- ADC_CONTR |=ADC_START; //开启AD转换
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- while(!(ADC_CONTR & 0x10));
- ADC_CONTR &= ~ADC_FLAG;
- ADC_RES = (ADC_RES<<2)|ADC_RESL; //高八位按位左移2位与低两位结果按位或运算得到10位转换结果
- return ADC_RES; //返回10位AD转换结果
- }
- /*******************延时函数**********/
- void delay(unsigned int x)
- {
- char j;
- for(x; x> 0; x--)
- for(j = 400; j > 0; j--);
- }
- void Delay1ms() //@12.000MHz
- {
- unsigned char i, j;
- i = 2;
- j = 239;
- do
- {
- while (--j);
- } while (--i);
- }
- void Delay150us() //@12.000MHz
- {
- unsigned char i, j;
- i = 2;
- j = 189;
- do
- {
- while (--j);
- } while (--i);
- }
- void Delay200us() //@12.000MHz
- {
- unsigned char i;
- _nop_();
- i = 97;
- while (--i);
- }