简单易制作的0-30VSTC单片机数字电压表

  这块简单易制作的0-30VSTC单片机数字电压表,被测电压经限流电阻接到AD检测端并由分流电阻分流,读出8位(256)的AD数据,由AD值计算出AD端电压,即分流点电压,由此电压计算出分流电流,再由此电流计算出输入电压。使用STC12C5204AD单片机,P0.0-P0.3 共阴数码管位、P2 为共阴数码管段a-g dp,P0、P2 设置为推挽输出,段输出加限流电阻,AD为8位,计算方法:5/256=0.0195312V,分流电阻为实测阻值。AD值*0.0195312v/对地分流电阻,算出分流电流,然后用分流电流*分流电阻与限流电阻之和即为要显示的输入电压值,业余使用,精度已经够用了。STC12C5204AD头文件 网上多的是,大家搜一下就会找到的,其中涉及到端口设置的地方大家对照芯片手册更正。

简单易制作的0-30VSTC单片机数字电压表源程序:


#include <STC12C52.H>  //STC12C5204AD头文件

#include <intrins.h>   //_nop_();

#define uchar unsigned char

#define uint  unsigned int


//sfr ADC_CONTR=0XBC;//adc使能位.ADC电源控制位

sfr ADC_RES=0XBD;// adc数据高八位,即ADC值

sfr P1ASF=0X9D;//P1各端口ADC使能端

uchar led_bcd[]={0x3F,/*0*/  //共阴数码管

          0x06,/*1*/

          0x5B,/*2*/

          0x4F,/*3*/

          0x66,/*4*/

          0x6D,/*5*/

          0x7D,/*6*/

          0x07,/*7*/

          0x7F,/*8*/

          0x6F,/*9*/

    0x00,/* */

    0x7c /*b*/

    }

    ,ad_data

    ;

uint data dis[5]={0x00,0x00,0x00,0x00,0x00},ZZ; //定义四个显示数据单元和一个数据存储单元

//dis[4,3,2,1,5]  显示:12.34   5为存储单元


/*******************************************************************/

/*  延时子程序                                                                                                                                 */

/*                                                                                                                  */

/*                                                                                                                                  */

/*******************************************************************/

void delay(uint z)    //延时子函数

{  

   uchar de1,de2;

  for(de1=z;de1>0;de1--)

  for(de2=100;de2>0;de2--);  

}

/*******************************************************/

//显示子函数 display(h1,h2,h3,h4)

//h1,h2,h3,h4 为四位LED数码管显示变量

//

//

//

/*******************************************************/

void display(uchar h1,uchar h2,uchar s1,uchar s2)   ////LED显示函数(参数:LED1,LED2,LED3,LED4) 

{


// 第一个数码管显示数据

if(h1==0x3f) h1=0x00;   //0消隐语句

P2=h1;

  //delay(2);

P00=0;

  delay(2);   //参数2-10   数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.

P2=0X00;

P00=1;

/*******************************************************/ 

// 第二个数码管显示数据

P2=h2|0x80;

  //delay(2);

P01=0;

  delay(2);  //参数2-10   数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.

P2=0X00;

P01=1;

//delay(5);

/*******************************************************/

// 第三个数码管显示数据


P2=s1;

  //delay(2);

P02=0;

  delay(2); //参数2-10   数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.

  P2=0X00;

    P02=1;

// delay(5);

/*******************************************************/

// 第四个数码管显示数据

P2=s2;

  //delay(2);

P03=0;

  delay(2); //参数2-10   数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.

  P2=0X00;

P03=1;


//delay(5); 


}

void init()//系统初始化函数

{

P2M1=0Xff; //强推挽   推动a-g dp

P2M0=0X00; //强推挽   推动a-g dp

P0M1=0X0f; //强推挽   推动位

P0M0=0X00; //强推挽   推动位

P0=0XFF;   //初始化

P2=0;    //初始化

/***定时器0初始化设置*****/  

TMOD = 0x01;

    TH0 = 0xFC;  //初值1ms

    TL0 = 0x18;  //初值1ms

    EA = 1;   //开总中断

    ET0 = 1;  //定时器0中断打开

    TR0 = 1;  //打开定时器 开始计时

/*************************/

ZZ=0;

}

void initADC()  //AD初始化

{

P1ASF=0x01;//只使用P1.0端口做为ADC输入端.

ADC_RES=0;//ADC数据寄存器清零

ADC_CONTR=ADC_POWER|ADC_SPEEDLL;  //打开ADC开关并设置 转换速率详见STC12C52.H

delay(2);  //打开ADC并延时.

}

uchar readADC()   //读AD

{

ADC_CONTR=ADC_POWER|ADC_SPEEDLL|0|ADC_START;

_nop_();

_nop_();

_nop_();

_nop_();

while(!(ADC_CONTR&ADC_FLAG));//等待转换完成标志

ADC_CONTR&=~ADC_FLAG;//close ADC

return ADC_RES;//返回ADC值.

}

void main()

{

init();

initADC();//初始化ADC

ad_data=readADC();//开机转换

while(1)

{

  float j;

  uchar ad_data;

  while(ZZ>=500) //500毫秒读一次ADC

  {

   ad_data=readADC();//读入ADC数据

   ZZ=0;

  }

  j=ad_data*19.5312;//由AD数据*19.5312(放大1000倍)=分流后的电压

  j=j/9890; //j(电压)/接地电阻(实测)9890欧

  j=j*60190;//j(电流)*(输入限流电阻(实测)60190欧+接地电阻(实测)9890欧) 计算出实际输入电压 如果使用高精度电阻,则直接输入电阻值

  dis[4]=j/1000;

  dis[3]=dis[4]/10;

  dis[2]=dis[4]%10;

  //h=(h-(dis[3]*10+dis[2]))*100;

  dis[4]=j/10-dis[4]*100;

  //dis[4]=j%100;//小数位第一位

  dis[1]=dis[4]/10;

  dis[0]=dis[4]%10;//小数位第二位

  //delay(10000);

}

}

void Timer0Interrupt(void) interrupt 1

{

    ZZ++;   //AD读取间隔时间控制

TH0 = 0xFC;

    TL0 = 0x18;

display(led_bcd[dis[3]],led_bcd[dis[2]],led_bcd[dis[1]],led_bcd[dis[0]]);

   }




猜你喜欢

转载自blog.csdn.net/u010402372/article/details/51670494
今日推荐