自制正负量程电压表,问题及解决。
本帖最后由 长寿烙铁 于 2016-12-31 18:18 编辑自制正负量程电压表。
我的单片机是20脚的12c5608ad,用三位共阳数码管显示数字。
使用微型锂电池供电,电压3.5到4.2v。
基本功能为:直流电压-10到10v,可以加一个电阻测量-100到100v。
电压接口并联红色发光管作为限压保护,压降1.6v。
基本电压测量范围-1.5到1.5v,用431产生1.5v作为基准,以便能够测量电压极性。
本帖最后由 长寿烙铁 于 2016-12-31 18:19 编辑
新手编写程序,遇到并且解决了一些问题。
名称定义错误sbit B=P1^7;void data(),B和data已经被系统使用,应该改用其它名称。
编译时void data()的附近竟然提示出好几个莫名其妙的错误,
改成void shuju()后,那几个错误都没有了。
程序的系统周期使用了定时器,我没有弄清1T和12T,结果时间慢了很多。
stc单片机可以通过AUXR设置1T和12T,默认是12T。
试验时调整输入测试电压,显示结果最大只有2.00多一点,
经过认真分析,发现1000*v超过了65535,导致计算结果错误。
我修改了变量类型u32 r,v,u;输出正常了。
由于接口紧张,我把下载口接到数码管上,
下载程序时有几次使电脑重启,不知道怎么回事。
下面是程序,还需要改进,请大家多多指教
#include<reg51.h>
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
/****************************************************/
sbit A=P3^1;
sbit b=P1^7;
sbit C=P3^2;
sbit D=P3^4;
sbit E=P3^5;
sbit F=P3^0;
sbit G=P1^4;
sbit H=P3^3; //小数点
sbit D1=P1^5;//第一位
sbit D2=P1^0;//第二位
sbit D3=P1^2;//第三位
sfr P1M0=0x91; //IO口控制寄存器
sfr P1M1=0x92; //IO口控制寄存器
sfr P3M0=0xb1;
sfr P3M1=0xb2;
sfr ADC_CONTR=0xc5;//ADC控制寄存器
sfr ADC_DATA=0xc6;
sfr ADC_LOW2=0xbe;
sfr AUXR=0x8e;
/****************************************************/
u8 w,t,tt;
u8 vf; //负电压
u16 a; //电流
u32 r,v,u; //参考 测量 显示电压
u8 d; //3位数字
u16 ad; //3个AD值
/****************************************************/
//软件延时函数
void delay2ms() //@6.0MHz 2ms
{
u8 i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay_ms(u8 i)
{
while(i--)
delay2ms();
}
void shuju() //数据处理
{
r=ad; //基准电压
v=ad; //测量电压
a=ad; //电流检测
if(v<r)v=r-v,vf=1; //测量电压为负
else v=v-r,vf=0; //测量电压为正
u=1000*v/r; //测量电压换算
//基准电压1.5V,量程10V,分压电阻22K+3.9K
if(u>999)
{
d=10;
d=10;
d=10;
}
else
{
d=u/100;
d=u%100/10;
d=u%10;
}
}
/******************************************************/
void zifu(u8 n) //字符显示
{
switch(n)//笔画控制(共阳数码管)
{
case 0:A=0;b=0;C=0;D=0;E=0;F=0;G=1;break;
case 1:A=1;b=0;C=0;D=1;E=1;F=1;G=1;break;
case 2:A=0;b=0;C=1;D=0;E=0;F=1;G=0;break;
case 3:A=0;b=0;C=0;D=0;E=1;F=1;G=0;break;
case 4:A=1;b=0;C=0;D=1;E=1;F=0;G=0;break;
case 5:A=0;b=1;C=0;D=0;E=1;F=0;G=0;break;
case 6:A=0;b=1;C=0;D=0;E=0;F=0;G=0;break;
case 7:A=0;b=0;C=0;D=1;E=1;F=1;G=1;break;
case 8:A=0;b=0;C=0;D=0;E=0;F=0;G=0;break;
case 9:A=0;b=0;C=0;D=0;E=1;F=0;G=0;break;
case 10:A=0;b=1;C=1;D=0;E=0;F=0;G=0;break; //E
}
}
/**********显示函数*****************************************/
void xianshi()
{
if(t==1)
{zifu(d);
D1=1; //显示第一位 4ms
H=0; //小数点
}
if(t==5)
{D1=0; //1ms间歇
H=1;
}
if(t==6)
{zifu(d);
D2=1; //显示第二位
}
if(t==10)D2=0;
if(t==11)
{zifu(d);
D3=1; //显示第三位
if(vf==1) //测量电压为负
H=0; //末尾小数点显示(使电路简化)
}
if(t==15)
{D3=0; H=1;}
if(t>15)t=0;
}
/****************************************************/
void initial()
{
ADC_CONTR=0x80; //ADC上电
P1M0=0x4a; //配置IO口为ADC输入
P1M1=0x25; //配置IO口为推挽模式
AUXR=0x10; //允许ADC中断
TMOD=0x01; //定时器T0为16位
delay_ms(5); //等待ADC稳定
IE=0xa2; //启用ADC转换和定时器TR0
}
/****************************************************/
main()
{
delay_ms(200); //开机延时
initial();
ADC_CONTR=0x88; //准备AD转换
TR0=1;
while(1)
{
xianshi();
if(tt>250)
{tt=0;shuju();}
}
}
/****************************************************/
void et0()interrupt 1
{
TH0=0xfe,TL0=0x0c; //定时1ms @6.0MHz
t++;tt++; //次数累加
}
/****************************************************/
void adc_spi()interrupt 5 //轮流测量AD值
{
if(tt==100)
{
w++;
ad=ADC_DATA,ad<<=2,ad+=ADC_LOW2; //每通道AD值(10位)
switch(w)
{
case 1:ADC_CONTR=0x8b;break;//p1^3通道AD转换
case 2:ADC_CONTR=0x8e;break;//p1^6通道AD转换
case 3:ADC_CONTR=0x89; //p1^1通道AD转换
w=0;break;
}
}
}
顶顶顶
赞个。。。
路过看看
感谢楼主分享 顶一个
楼主好手艺
写程序的就是牛
都是神人啊...看得我等小白一愣一愣的 感谢楼主分享 厉害了
反接碍事吧
楼主厉害,谢谢分享,新年快乐! 利害,顶起来。。。。。。。。。。。。 路过,帮顶→_→
很好 有空做一个 玩玩 谢谢楼主分享 武杰杰 发表于 2017-1-1 07:59
反接碍事吧
这个电压表和数字万用表用法一样,可以测量正负电压,显示极性,而且有超压保护,单片机不会损坏。
页:
[1]
2