长寿烙铁 发表于 2016-12-31 18:15:04

自制正负量程电压表,问题及解决。

本帖最后由 长寿烙铁 于 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:17:14

本帖最后由 长寿烙铁 于 2016-12-31 18:19 编辑

新手编写程序,遇到并且解决了一些问题。
名称定义错误sbit B=P1^7;void data(),B和data已经被系统使用,应该改用其它名称。
编译时void data()的附近竟然提示出好几个莫名其妙的错误,
改成void shuju()后,那几个错误都没有了。   

程序的系统周期使用了定时器,我没有弄清1T和12T,结果时间慢了很多。
stc单片机可以通过AUXR设置1T和12T,默认是12T。





长寿烙铁 发表于 2016-12-31 18:21:57

试验时调整输入测试电压,显示结果最大只有2.00多一点,
经过认真分析,发现1000*v超过了65535,导致计算结果错误。
我修改了变量类型u32 r,v,u;输出正常了。

由于接口紧张,我把下载口接到数码管上,
下载程序时有几次使电脑重启,不知道怎么回事。





长寿烙铁 发表于 2016-12-31 18:25:04

下面是程序,还需要改进,请大家多多指教
#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;
        }
   }
}


Mr-iuy 发表于 2016-12-31 18:52:29

顶顶顶

昶平 发表于 2016-12-31 20:15:33

赞个。。。

江南小丸子 发表于 2016-12-31 20:25:16

路过看看

炸香机 发表于 2016-12-31 20:55:39

感谢楼主分享                        

郭先生 发表于 2016-12-31 21:21:17

顶一个

大爱猩猩 发表于 2016-12-31 21:28:56

楼主好手艺

江南小丸子 发表于 2016-12-31 22:49:07

写程序的就是牛

枫飞秋语 发表于 2016-12-31 23:03:57

都是神人啊...看得我等小白一愣一愣的

wurenji 发表于 2016-12-31 23:10:39

感谢楼主分享

0ks4lz2skN 发表于 2016-12-31 23:15:19

厉害了

武杰杰 发表于 2017-1-1 07:59:25

反接碍事吧

独行者 发表于 2017-1-1 08:57:25

楼主厉害,谢谢分享,新年快乐!

3300178839 发表于 2017-1-1 09:58:29

利害,顶起来。。。。。。。。。。。。

金属风暴 发表于 2017-1-1 10:11:30

路过,帮顶→_→

huang2678 发表于 2017-1-1 12:11:23

很好   有空做一个 玩玩 谢谢楼主分享

长寿烙铁 发表于 2017-1-1 20:22:58

武杰杰 发表于 2017-1-1 07:59
反接碍事吧

这个电压表和数字万用表用法一样,可以测量正负电压,显示极性,而且有超压保护,单片机不会损坏。
页: [1] 2
查看完整版本: 自制正负量程电压表,问题及解决。