STC15F2K60S2制作简易的电压表

冯:
参考,别人的别人的,参考链接:参考链接

效果图:
在这里插入图片描述

思:
这块简单易制作的0-30V,STC单片机数字电压表,被测电压经限流电阻接到AD检测端并由分流电阻分流,读出8位、2的8次方(256)的AD数据,由AD值计算出AD端电压,即分流点电压,由此电压计算出分流电流,再由此电流计算出输入电压。
如图:(参考链接中的)(链接中的图形,有个电容,可以起到很好的作用)
在这里插入图片描述
使用STC15F2K60s2AD单片机,P1段输出加限流电阻,AD为8位,计算方法:5/256=0.0195312V,分流电阻为实测阻值。AD值0.0195312v/对地分流电阻,算出分流电流,然后用分流电流分流电阻与限流电阻之和即为要显示的输入电压值,业余使用,精度已经够用了。

或者可以直接接分压电阻,但是如果是空载的话,就会有些问题。
如图:在这里插入图片描述
当直接接电阻时:(我使用的是STC15F2K系列,是10位AD,但是只用到8位而已,即用高八位,低二位不用)
电压=(5/256=0.019532)*AD值
电流=……

原理图:(15大多系列可以不用晶振,也可以用晶振)
在这里插入图片描述
其中:在这里插入图片描述
官方推荐电路:
在这里插入图片描述
主函数:

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 AD转换查询方式举例----------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/
//若无特别说明,工作频率一般为11.0592MHz
#include "reg51.h"
#include "intrins.h"

#define FOSC    11059200L//晶振大小
#define BAUD    115200//波特率

typedef unsigned char BYTE; //重命名 unsigned char 为 BYTE
typedef unsigned int WORD;	//重命名 unsigned int 为 WORD

#define     URMD    0           //0:使用定时器2作为波特率发生器

//WORD data dis[5]={0x00,0x00,0x00,0x00,0x00};
WORD ad_data;//记录AD值
float j=0.0;//计算电压值
int sum=0;//将浮点电压值装换成int型

//74HC595IO口定义
sbit SRCLK=P2^2;
sbit Rclk=P2^1;
sbit SER=P2^0;

//数码管IO口(使用的是共阴)
sbit SMG1=P2^3;
sbit SMG2=P2^4;
sbit SMG3=P2^5;
sbit SMG4=P2^6;

//数码管共阴码表
char code smgduan[17]=
{
    0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
    0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};//显示0~F的值

char Data[4]={0};//记录电压的4位数(Data【0】=高位依次)

sfr T2H   = 0xd6;               //定时器2高8位
sfr T2L   = 0xd7;               //定时器2低8位

sfr  AUXR       =   0x8e;       //辅助寄存器                              

sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
sfr ADC_RES     =   0xBD;           //ADC高8位结果
sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器

#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_FLAG    0x10            //ADC完成标志
#define ADC_START   0x08            //ADC起始控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_SPEEDL  0x20            //360个时钟
#define ADC_SPEEDH  0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟

void InitUart();//串口初始化
void InitADC();//AD初始化
void SendData(BYTE dat);//串发送数据
BYTE GetADCResult(BYTE ch);//获取AD值
void Delay(WORD n);//延时
void ShowResult(BYTE ch);//使用AD中的某一个输入口可以是0~7
void Hc595SendByte(char dat);//

void DigDisplay()//显示数据
{
    char i;
    for(i=0; i<4; i++)
    {
        switch(i)	 //位选,选择点亮的数码管,
        {
        case 0://Data【0】
            SMG1=0;
            SMG2=1;
            SMG3=1;
            SMG4=1;
            break;
        case 1://Data【1】
            SMG1=1;
            SMG2=0;
            SMG3=1;
            SMG4=1;
            break;
        case 2://Data【2】
            SMG1=1;
            SMG2=1;
            SMG3=0;
            SMG4=1;
            break;
        case 3://Data【3】
            SMG1=1;
            SMG2=1;
            SMG3=1;
            SMG4=0;
            break;
        }
				if(i==1)
				{
					Hc595SendByte(smgduan[Data[i]]|0x80);//第二个数码管加点(.)
				}
				else
				{
					Hc595SendByte(smgduan[Data[i]]);//发送段码					
				}

        Delay(100);
				Hc595SendByte(0x00);//消影
				Delay(100);//这里的延时不要太久
    }
}

void main()
{
	  SMG1=0;
    SMG2=0;
    SMG3=0;
    SMG4=0;//初始化数码管四位都开启
	
    InitUart();                     //初始化串口
    InitADC();                      //初始化ADC
    while (1)
    {
			char i=0;
			Delay(100);
			ShowResult(2);              //显示通道3
			DigDisplay();
    }
}
/*----------------------------
发送ADC结果到PC
----------------------------*/
void ShowResult(BYTE ch)//数据处理
{
    SendData(ch);                   //显示通道号
//		SendData(GetADCResult(ch));
//		Delay(10000);
//		Delay(10000);
		ad_data=GetADCResult(ch);
	
		j=ad_data*19.5312;//由AD数据*19.5312(放大1000倍)=分流后的电压
		j=j/9890; //j(电压)/接地电阻(实测)9890欧
		j=j*60190;//j(电流)*(输入限流电阻(实测)60190欧+接地电阻(实测)9890欧) 计算出实际输入电压 如果使用高精度电阻,则直接输入电阻值
	 
		//SendData(j);
		sum=j;
	
//		Data[0]=sum/10000%10;//(这里是直接接负载电阻的测量电压方法)
//		Data[1]=sum/1000%10;
//		Data[2]=sum/100%10;
//		Data[3]=sum/10%10;

		Data[0]=sum/10000%10;//十位
		Data[1]=sum/1000%10;//个位
		Data[2]=sum/100%10;//十分位
		Data[3]=sum/10%10;//百分位
}
/*----------------------------
读取ADC结果
----------------------------*/
BYTE GetADCResult(BYTE ch)
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
    _nop_();                        //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC

    return ADC_RES;                 //返回ADC结果
}

/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
    SCON = 0x5a;                //设置串口为8位可变波特率
#if URMD == 0
    T2L = (65536 - (FOSC/4/BAUD));
    T2H = (65536 - (FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;                //T2为1T模式, 并启动定时器2
    AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
#elif URMD == 1
    AUXR = 0x40;                //定时器1为1T模式
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
    TL1 = (65536 - (FOSC/4/BAUD));
    TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
    TR1 = 1;                    //定时器1开始启动
#else
    TMOD = 0x20;                //设置定时器1为8位自动重装载模式
    AUXR = 0x40;                //定时器1为1T模式
    TH1 = TL1 = (256 - (FOSC/32/BAUD));
    TR1 = 1;
#endif
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0xff;                   //设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);                       //ADC上电并延时
}

/*----------------------------
发送串口数据
----------------------------*/
void SendData(BYTE dat)
{
    while (!TI);                    //等待前一个数据发送完成
    TI = 0;                         //清除发送标志
    SBUF = dat;                     //发送当前数据
}

/*----------------------------
软件延时
----------------------------*/
void Delay(WORD n)
{
    WORD x;

    while (n--)
    {
        x = 10;
        while (x--);
    }
}

void Hc595SendByte(char dat)
{
    char a;

    SRCLK = 1;
    Rclk = 1;

    for(a=0; a<8; a++)		 //发送8位数
    {
        SER = dat >> 7;		 //从最高位开始发送
        dat <<= 1;

        SRCLK = 0;			 //发送时序
        _nop_();
        _nop_();
        SRCLK = 1;
    }
    Rclk = 0;
    _nop_();
    _nop_();
    Rclk = 1;
}


其实AD的检测的程序是参考了官方的。配置在如下图中参考:
在这里插入图片描述
大致就是这样:最后是Keil的一张图:
在这里插入图片描述
结语:由于本人技术有限,难免会有错误的地方,如有错误,还望大家多多指教v.
感谢:怡
作者:杏林洁白

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值