找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
楼主: 刘海龙
打印 上一主题 下一主题
收起左侧

开源基于STC单片机内部基准mini电压表—极简设计创新制作

  [复制链接]
161#
ID:620993 发表于 2019-10-15 16:52 | 只看该作者
谢谢楼主,正需要
回复

使用道具 举报

162#
ID:239055 发表于 2019-10-27 08:01 来自手机 | 只看该作者
谢谢了,龙哥
回复

使用道具 举报

163#
ID:239055 发表于 2019-10-27 08:02 来自手机 | 只看该作者
等我做好了,再来请教
回复

使用道具 举报

164#
ID:239055 发表于 2019-10-27 22:14 来自手机 | 只看该作者
p1.0只能用来测内部基准吗?
回复

使用道具 举报

165#
ID:632444 发表于 2019-11-3 10:25 来自手机 | 只看该作者
手上刚好有这个单片机,改天就试试,谢谢
回复

使用道具 举报

166#
ID:64269 发表于 2019-11-7 12:23 | 只看该作者
学一习,学习一下.非常感谢
回复

使用道具 举报

167#
ID:197178 发表于 2019-11-14 18:52 | 只看该作者
好小巧
回复

使用道具 举报

168#
ID:644368 发表于 2019-11-19 18:58 | 只看该作者
下载来学习学习
回复

使用道具 举报

169#
ID:24685 发表于 2019-12-22 21:22 | 只看该作者
龙哥每次都是精品
回复

使用道具 举报

170#
ID:428400 发表于 2019-12-26 18:56 | 只看该作者
liu牛人,不知道STC的精度怎么样
回复

使用道具 举报

171#
ID:123732 发表于 2019-12-30 19:35 | 只看该作者
c20160526 发表于 2019-10-27 22:14
p1.0只能用来测内部基准吗?

p1.0-p1.7都可以测外部电压
回复

使用道具 举报

172#
ID:127666 发表于 2020-1-10 13:15 | 只看该作者
不知道用431精度会不会更好
回复

使用道具 举报

173#
ID:684413 发表于 2020-1-10 20:57 | 只看该作者
学习一下,电路简单。
回复

使用道具 举报

174#
ID:562099 发表于 2020-1-12 20:59 | 只看该作者
对于初学者,这也是最新款的单片机了,就是要这样去学习啊,真是好论坛
回复

使用道具 举报

175#
ID:623647 发表于 2020-1-14 16:32 | 只看该作者
下载学习一下
回复

使用道具 举报

176#
ID:75864 发表于 2020-1-15 08:45 | 只看该作者
很好,感谢楼主分享!
回复

使用道具 举报

177#
ID:136485 发表于 2020-1-15 15:10 | 只看该作者
测试能用,多谢分享,但是小数后一直跳动,加个104电容电压就误差大了
回复

使用道具 举报

178#
ID:577329 发表于 2020-1-24 20:59 | 只看该作者
1123212143255 发表于 2016-11-3 04:02
做出来了,引脚可以任意改,非常好用。



怎么改?我都是16口的,麻烦讲解一下。
回复

使用道具 举报

179#
ID:283207 发表于 2020-2-1 23:06 | 只看该作者
STC15W408AS,学习一下
回复

使用道具 举报

180#
ID:36359 发表于 2020-2-11 22:38 | 只看该作者
找了一圈 终于找到了,感谢楼主,发现楼主真的很有耐心,解答了网友各种问题。表示感谢!
回复

使用道具 举报

181#
ID:51443 发表于 2020-4-8 07:57 | 只看该作者
把显示部分这样改了一下觉得更符合视觉习惯:
void disp()           //0.00V-30.0V
{
   unsigned int i;
   if(v>=10000)
      for(i=0;i<50;i++)
                {
         diplay_data (1,disdata[v/10000]);
         diplay_data (2,disdata[v%10000/1000]+0x80);
         diplay_data (3,disdata[v%1000/100]);
        }
        else if((10000>v)&&(v>80))                        
         for(i=0;i<50;i++)
          {
                diplay_data (1,disdata[v/1000]+0x80);
                diplay_data (2,disdata[v%1000/100]);
                diplay_data (3,disdata[v%100/10]);
          }
   else
            for(i=0;i<50;i++)
          {
                diplay_data (1,disdata[0]+0x80);
                diplay_data (2,disdata[0]);
                diplay_data (3,disdata[0]);
          }
}
回复

使用道具 举报

182#
ID:311661 发表于 2020-4-13 17:36 | 只看该作者
很不错的分享,支持一下
回复

使用道具 举报

183#
ID:686739 发表于 2020-4-21 07:00 来自手机 | 只看该作者
谢谢分享
回复

使用道具 举报

184#
ID:428400 发表于 2020-4-25 18:43 | 只看该作者
有仿制成功的朋友吗?
回复

使用道具 举报

185#
ID:537743 发表于 2020-4-25 22:05 | 只看该作者
好东西,谢谢分享!
回复

使用道具 举报

186#
ID:738263 发表于 2020-4-26 18:30 | 只看该作者
乱跳,根本看不出是多少V??
回复

使用道具 举报

187#
ID:738263 发表于 2020-4-26 18:33 | 只看该作者
电路一模一样的搭建了,程序下载了。显示乱眺??请问为何?
回复

使用道具 举报

188#
ID:738263 发表于 2020-4-26 18:34 | 只看该作者
用的是STC15W408AS 35I   28DIP
回复

使用道具 举报

189#
ID:600952 发表于 2020-4-27 15:24 | 只看该作者
好帖,基于STC单片机内部基准(Bandgap voltage reference)mini电压表—极简设计,非常详细,精华!
成品小巧便携,很实用,建议再加上量程档位变化就更好了,不过这个30V量程已经够用了
学习到了,谢谢分享!!!
回复

使用道具 举报

190#
ID:779135 发表于 2020-6-14 17:18 | 只看该作者
好评,好用
回复

使用道具 举报

191#
ID:766985 发表于 2020-6-16 09:14 | 只看该作者
收藏学习一下
回复

使用道具 举报

192#
ID:491577 发表于 2020-6-18 10:28 | 只看该作者
这种电路只能用来学习,了解ADC是怎么回事,要想做电压表误差太大。首先10K分压电阻太小,对要检测的电压影响很大,万用表的分压电阻是10M,举个例子:两个串联的10K电阻,两端接5V电压,两个电阻间的电压应该是2.5V,如果用你的这个电路测量会是多少伏呢?认真想想,肯定不会是2.5V,如果是更大的电阻100K呢,误差就更大了。
回复

使用道具 举报

193#
ID:491577 发表于 2020-6-18 10:45 | 只看该作者
真正能用的电压表必须要大于10M的分压电阻,分压电阻的大小是会影响到被测电路电压的,并且要运算放大器做电压跟随,直接用ADC芯片测量电压,测电池电压没问题,要测实际电路电压只能呵呵。
回复

使用道具 举报

194#
ID:554177 发表于 2020-8-13 17:39 | 只看该作者
不错,正好做这个,收藏了
回复

使用道具 举报

195#
ID:143767 发表于 2020-8-29 18:18 | 只看该作者
楼主你好,我想把3位数码管的电压显示变成电量百分比显示,比如锂电池在4.2V的时候显示100,在2.8V的时候显示1,请问程序需要怎样改?谢谢!
回复

使用道具 举报

196#
ID:143767 发表于 2020-9-2 10:34 | 只看该作者
这帖子还是不错的,可惜没人顶快沉了,我想用这个做个电量指示装置,不知程序如何修改,不知楼主还能否看到此贴。
回复

使用道具 举报

197#
ID:66416 发表于 2021-7-11 22:20 | 只看该作者
楼主能不能改个共阳的程序?
或者在4LED_YIN.h中指明一下,怎样修改?
回复

使用道具 举报

198#
ID:951574 发表于 2021-7-12 11:24 | 只看该作者
电路简洁,先收藏一下
回复

使用道具 举报

199#
ID:66416 发表于 2021-7-13 01:21 | 只看该作者
@楼主,过来帮忙看一下,为什么我用的共阳极的,改了程序还是没有显示:
一、原理图:
二、STC15ADC.c
/********************************************/
//2016.10.20日 1:01编写完成
//作者:刘海龙 (读单片机内部BandGap基准电压值参考的STC官网程序)
//硬件:STC15W408AS+3位共阴数码管+2个10K的电阻(1/4w)
//晶振无说明的情况选12M
//测量口P1.3
#include <STC15W.h>
#include <intrins.h>
#include<4LED_YIN.H>//数码管驱动显示程序
#include <BandGap.H>//包含读单片机内部BandGap基准电压值       
/********************************/
void main (void)
{        Delay20ms();//待系统稳定
    InitADC();//初始化ADC
    P1M1=0X08;//P1.3高阻输入
          init();//IO口设置初始化
    while (1)
    {
        ShowResult(3);//显示通道P1.3的测量值、单位为毫伏
                    disp();        //数码管显示电压值
    }
}


三、4LED_YIN.H
/***********四位共阴数码管驱动程序************/
//stc15w单片机
//1在主程序前加上初始化init();程序
//2硬件连接变动时需修改下面的参数
sbit H1        = P1^0;//设置第1位数码管阳极连接的I/O口
sbit H2        = P1^1;//设置第2位数码管阳极连接的I/O口
sbit H3        = P1^2;//设置第3位数码管阳极连接的I/O口
//sbit H4        = P1^7;//设置第4位数码管阳极连接的I/O口
sbit a        = P3^7;
sbit b        = P3^6;
sbit c        = P3^5;
sbit d        = P3^4;
sbit e        = P3^3;
sbit f        = P3^2;
sbit g        = P3^1;
sbit dp        = P3^0;
unsigned char PWM;//显示亮度
unsigned int v;//定义测量电压变量
#define P1M0SET                0x00 //设置I/O口工作方式//00000000(左到右,高到低位)
#define P1M1SET                0x00 //设置I/O口工作方式//00000000
#define P3M0SET                0xFF //设置I/O口工作方式//11111111
#define P3M1SET                0x00 //设置I/O口工作方式//00000000
/*****以上定义需要根据实际硬件情况更改******/
#define light                        9         //设置LED显示的亮度(值域:1~9)
#define DELAY_L                12         //设置每一个点显示的时间长度(1~20)
/********* 延时函数    ***************/
void delay (unsigned int a){ // 用于点扫描的延时
        unsigned int i;
        while( a-- != 0){
                for(i = 0; i < DELAY_L; i++);
        }                                     
}
/*********************************************************************************************/
unsigned char code disdata[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09}; //显示0~9的段码

//数码管:负向位置;共阳极;负向连接

void dis_off (void){
        P3 = P3M0SET; //关所有显示
        P1 = ~P1M0SET;
        delay(10-PWM);
}
/*********************************************************************************************/
void displayHH1 (unsigned char q){ //第1位数码管显示程序
        unsigned char i;
        i = q & 0x7F;
        if(i == 0x7F){
                H1 = 0;a = 0;}delay(PWM);dis_off();
        i = q & 0xBF;
        if(i == 0xBF){
                H1 = 0;b = 0;}delay(PWM);dis_off();
        i = q & 0xDF;
        if(i == 0xDF){
                H1 = 0;c = 0;}delay(PWM);dis_off();
        i = q & 0xEF;
        if(i == 0xEF){
                H1 = 0;d = 0;}delay(PWM);dis_off();
        i = q & 0xF7;
        if(i == 0xF7){
                H1 = 0;e = 0;}delay(PWM);dis_off();
        i = q & 0xFB;
        if(i == 0xFB){
                H1 = 0;f = 0;}delay(PWM);dis_off();
        i = q & 0xFD;
        if(i == 0xFD){
                H1 = 0;g = 0;}delay(PWM);dis_off();
        i = q & 0xFE;
        if(i == 0xFE){
                H1 = 0;dp = 0;}delay(PWM);dis_off();
}
/*********************************************************************************************/
void displayHH2 (unsigned char q){ //第2位数码管显示程序
        unsigned char i;
        i = q & 0x7F;
        if(i == 0x7F){
                H2 = 0;a = 0;}delay(PWM);dis_off();
        i = q & 0xBF;
        if(i == 0xBF){
                H2 = 0;b = 0;}delay(PWM);dis_off();
        i = q & 0xDF;
        if(i == 0xDF){
                H2 = 0;c = 0;}delay(PWM);dis_off();
        i = q & 0xEF;
        if(i == 0xEF){
                H2 = 0;d = 0;}delay(PWM);dis_off();
        i = q & 0xF7;
        if(i == 0xF7){
                H2 = 0;e = 0;}delay(PWM);dis_off();
        i = q & 0xFB;
        if(i == 0xFB){
                H2 = 0;f = 0;}delay(PWM);dis_off();
        i = q & 0xFD;
        if(i == 0xFD){
                H2 = 0;g = 0;}delay(PWM);dis_off();
        i = q & 0xFE;
        if(i == 0xFE){
                H2 = 0;dp = 0;}delay(PWM);dis_off();
}
/*********************************************************************************************/
void displayHH3 (unsigned char q){ //第3位数码管显示程序
        unsigned char i;
        i = q & 0x7F;
        if(i == 0x7F){
                H3 = 0;a = 0;}delay(PWM);dis_off();
        i = q & 0xBF;
        if(i == 0xBF){
                H3 = 0;b = 0;}delay(PWM);dis_off();
        i = q & 0xDF;
        if(i == 0xDF){
                H3 = 0;c = 0;}delay(PWM);dis_off();
        i = q & 0xEF;
        if(i == 0xEF){
                H3 = 0;d = 0;}delay(PWM);dis_off();
        i = q & 0xF7;
        if(i == 0xF7){
                H3 = 0;e = 0;}delay(PWM);dis_off();
        i = q & 0xFB;
        if(i == 0xFB){
                H3 = 0;f = 0;}delay(PWM);dis_off();
        i = q & 0xFD;
        if(i == 0xFD){
                H3 = 0;g = 0;}delay(PWM);dis_off();
        i = q & 0xFE;
        if(i == 0xFE){
                H3 = 0;dp = 0;}delay(PWM);dis_off();
}
void diplay_data (unsigned char l,unsigned char q){
                switch (l){//显示的数码管位置               
                                case 1://                       
                                        displayHH1(q); //将显示数据送入               
                                        break;//               
                                case 2://                       
                                        displayHH2(q); //将显示数据送入               
                                        break;//               
                                case 3://                       
                                        displayHH3(q); //将显示数据送入               
                                        break;//
//                                case 4://                       
//                                        displayHH4(q); //将显示数据送入               
//                                        break;//                       
                               
                }
}

/*****************IO口初始化**************************/
void init (void){       
                P3M1=P3M1SET;
                P3M0=P3M0SET;
                P1M0=P1M0SET;
                P1M1=P1M1SET;
                dis_off();
                PWM = light;}
/*******************************************/
/******************显示程序*************************/
void disp(){
unsigned int i;
        for(i=0;i<50;i++){
                diplay_data (1,disdata[v/1000]+0x80);
                diplay_data (2,disdata[v%1000/100]);
                diplay_data (3,disdata[v%100/10]);
        }
}


四、BandGap.H
//内部BandGap为基准测电压
//-----------------------------------------
#define  uchar unsigned char  
#define uint  unsigned int
unsigned int v;       
//ADC相关设定参数
#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个时钟
//-----------------------------------------
//BandGap相关参数
//注意:需要在下载代码时选择"在ID号前添加重要测试参数"选项,才可在程序中获取此参数
//#define ID_ADDR_ROM 0x03f7      //1K程序空间的MCU
//#define ID_ADDR_ROM 0x07f7      //2K程序空间的MCU
//#define ID_ADDR_ROM 0x0bf7      //3K程序空间的MCU
//#define ID_ADDR_ROM 0x0ff7      //4K程序空间的MCU
//#define ID_ADDR_ROM 0x13f7      //5K程序空间的MCU
#define ID_ADDR_ROM 0x1ff7      //8K程序空间的MCU
//#define ID_ADDR_ROM 0x27f7      //10K程序空间的MCU
//#define ID_ADDR_ROM 0x2ff7      //12K程序空间的MCU
//#define ID_ADDR_ROM 0x3ff7      //16K程序空间的MCU
//#define ID_ADDR_ROM 0x4ff7      //20K程序空间的MCU
//#define ID_ADDR_ROM 0x5ff7      //24K程序空间的MCU
//#define ID_ADDR_ROM 0x6ff7      //28K程序空间的MCU
//#define ID_ADDR_ROM 0x7ff7      //32K程序空间的MCU
//#define ID_ADDR_ROM 0x9ff7      //40K程序空间的MCU
//#define ID_ADDR_ROM 0xbff7      //48K程序空间的MCU
//#define ID_ADDR_ROM 0xcff7      //52K程序空间的MCU
//#define ID_ADDR_ROM 0xdff7      //56K程序空间的MCU
//#define ID_ADDR_ROM 0xeff7      //60K程序空间的MCU


//-----------------------------------------
//声明

void Delay20ms()                //@12.000MHz
{
        unsigned char i, j, k;

        _nop_();
        _nop_();
        i = 1;
        j = 234;
        k = 113;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}


/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
           P1ASF = 0x00;                   //不设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
        Delay20ms();
}
/*----------------------------
读取ADC结果
----------------------------*/
uint GetADCResult(uchar ch)
{
    uint ADC_10BIT_RES;
    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;         //关闭 ADC
    ADC_10BIT_RES=ADC_RES;      //得到高8位
    ADC_10BIT_RES<<=2;
    ADC_10BIT_RES+=ADC_RESL;     //得到低2位
    return ADC_10BIT_RES;                 //返回ADC结果

}

/*----------------------------
发送ADC结果
----------------------------*/
void ShowResult(uchar ch)
{
    uint adc_res10,//测量设定通道adc值
    bandgap,       //bandgap预储存校准值,单位毫伏
    adc_9gallery_res; //测量第九通道(bandgap)值
    float power_voltage,        //系统供电电压,单位毫伏
    ADC_voltage;     //设定通道电压值,单位毫伏

    uchar  code *cptr; //定义ROM(代码)区指针
    //uchar  idata *iptr;//定义RAM(内存)区指针

    cptr = ID_ADDR_ROM;         //从程序区读取BandGap电压值(单位:毫伏mV)
    bandgap=*cptr++;
    bandgap<<=8;
    bandgap+=*cptr;
    /*iptr = ID_ADDR_RAM;         //从内存区读取BandGap电压值(单位:毫伏mV)
    bandgap=*iptr++;              //两种方法结果一样,上面的方法需要在下载式勾选"在ID号前添加重要测试参数"选项,才可在程序中获取此参数
    bandgap<<=8;                  //下面的方法不需要
    bandgap+=*iptr;    */
    //测量设定通道adc值
    ADC_RES = 0;                    //清除结果寄存器
    P1ASF = 0x08;                   //设置P1.3口为AD口
    GetADCResult(ch);
    GetADCResult(ch);                 //读三次获得稳定
    adc_res10= GetADCResult(ch);
    //测量第九通道(bandgap)值
    ADC_RES = 0;                    //清除结果寄存器
    P1ASF = 0x00;                   //设置读第九通道
    GetADCResult(0);                 //测bandgap时,调用此函数时通道数只能填0
    GetADCResult(0);                 //读三次获得稳定
    adc_9gallery_res=GetADCResult(0);
    //计算系统供电电压
    power_voltage=(float)bandgap*1024/adc_9gallery_res;
    //计算ADC通道测得电压值
    ADC_voltage=(float)bandgap*adc_res10/adc_9gallery_res;
        v=ADC_voltage;
        v=v*2;
}


原理图.jpg (185.98 KB, 下载次数: 426)

原理图

原理图
回复

使用道具 举报

200#
ID:53978 发表于 2021-7-13 08:33 | 只看该作者
留个记号 有时间了来学习一下,谢谢大神们。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表