找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5940|回复: 28
打印 上一主题 下一主题
收起左侧

【求助】关于STC12C2052AD单片机0-99v直流电压表

[复制链接]
跳转到指定楼层
楼主
是这样的,原贴的内容来源于本网站,但是我没有做出来,时间又比较急,原作者又没有回复我,所以我就发帖来求助了。原作者对不住了,我也是没办法的。。。。
始终做不出来原作的效果,我做出来的结果却是只显示最后一个零。本来是三极管放大,基极接1K电阻,然后发射极接正极,集电极接数码管,基极的电阻接单片机,这样的结果是只显示最后一个零。后来我在数码管的公共端6 8 9 12脚分别接了一根线,另一端直接接在单片机,于是乎数码管全部显示0,小数点也全部显示。跟死机了似的。。。当然了,不管怎么接都不能测量。


测量的分流电阻原文是75K,我觉得不妥,遂改成的30K。数码管是四位共阳没错。。。


我想问的是程序和电路图是不是有错误或者对不上号的地方???还是我搭的电路有问题???请各位大神指教一番。。。原作者再次对不住啦。。。
以下是原作者的实物图,原理图和程序。


程序源码:
  • /**********************************************************************

  • 基于STC12C4052AD单片机的0-99V数字电压表程序

  • P1.6口为0-5V模拟量输入端,P1.5口连接TL431l输出的2.5V基准电源,4位串行LED数码管显示

  • **********************************************************************/

  • #include <STC12C2052AD.H> //单片机头文件

  • #include <intrins.h> //51基本运算(包括_nop_空函数)

  • #define uchar unsigned char

  • #define uint unsigned int

  • #define LEDBus P3

  • //a3.0-b3.1-c3.2-d3.3-e3.4-f3.5-g3.7-dp1.0

  • sbit ge=P1^4;            //个位位选

  • sbit shi=P1^3;            //十位位选

  • sbit bai=P1^2;            //百位位选

  • sbit qian=P1^1;            //千位位选

  • sbit db=P1^0;

  • char d[5];

  • uint R,M,N;//若定义成uchar型就只能显示2.5V以下的数值

  • uchar code LEDTab[]={0xc0,0xf9,0x64,0x70,0x59,0x52,0x42,0xf8,0x40,0x50};//应为没有P3.6,所以这里管脚定义和普通的有点区别

  • unsigned char port[4]={0xfe,0xfd,0xfb,0xf7};

  • /*****************************************************************

  • 函数名:毫秒级CPU延时函数

  • 调  用:delay (?);

  • 参  数:1~65535(参数不可为0)

  • 返回值:无

  • 结  果:占用CPU方式延时与参数数值相同的毫秒时间

  • 备  注:应用于1T单片机时i<600,应用于12T单片机时i<125

  • /******************************************************************/

  • void delay(uint t)

  • {

  • uint i;               //定义变量

  • for(;t>0;t--)             //如果t大于0,t减1(外层循环)

  •   for(i=600;i>0;i--);         //i等于124,如果i大于0,i减1

  • }

  • /*******************************************************************

  • 函数名:ADC初始化及8位A/D转换函数

  • 返回值:8位的ADC数据

  • 结  果:读出指定ADC接口的A/D转换值,并返回数值

  • 备  注:适用于STC12C2052AD系列单片机(必须使用STC12C2052AD.h头文件)

  • *******************************************************************/

  • uchar Read (uchar CHA){

  • uchar AD_FIN=0; //存储A/D转换标志;若在函数外定义此变量则不能得到连续变化的模拟量的显示

  • /******以下为ADC初始化程序****************************/

  •     CHA &= 0x07;            //选择ADC的8个接口中的一个(0000 0111 清0高5位)

  •     ADC_CONTR = 0x60;  //ADC转换的速度(0XX0 0000 其中XX控制速度,请根据数据手册设置)

  •     _nop_();

  •     ADC_CONTR |= CHA;       //选择A/D当前通道

  •     _nop_();

  •     ADC_CONTR |= 0x80;      //启动A/D电源

  •     delay(1);            //使输入电压达到稳定(1ms即可?

  • /******以下为ADC执行程序****************************/

  •     ADC_CONTR |= 0x08;      //启动A/D转换(0000 1000 令ADCS = 1)

  •     _nop_();

  •     _nop_();

  •     _nop_();

  •     _nop_();

  •     while (AD_FIN ==0){     //等待A/D转换结束

  •     AD_FIN = (ADC_CONTR & 0x10); //0001 0000测试A/D转换结束否

  •     }

  •     ADC_CONTR &= 0xE7;      //1111 0111 清ADC_FLAG位, 关闭A/D转换,

  • return (ADC_DATA);          //返回A/D转换结果(8位)

  • }

  • /******************************************************************

  • 显示函数转换函数:

  • M=模拟量采样值,N=基准电压源采样值(本例为2.5V),R=模拟量输入值(待显示值)

  • N=256*2.5/Vcc;变形后得Vcc=256*2.5/N; 代入M=256*R/Vcc;得到M=R*N/2.5;变形后得R=M*2.5/N

  • 1为输入端分压比。

  • ******************************************************************/

  • void transfer(void){

  • M=Read(6);//P1.6口模拟量转换

  • N=Read(5);//P1.5口2.5V基准电压源采样(转换)

  • R=((M*2.5)/N)*9.31*1000;//输入模拟量换算并放大1000倍;

  • /***以下为3位显示转换***/

  • d[3]=R/1000;

  • R=R%1000;

  • d[2]=R/100;

  • R=R%100;

  • d[1]=R/10;

  • d[0]=R%10;

  • }

  • /******************************************************************

  • 函数功能:显示子程序

  • ********************************************************************/

  • void xian_shi (void)

  • {

  •    P1=0xfe;        //P1.3引脚输出低电平

  •    P3=LEDTab[d[0]];          //显示个位

  •    delay(1);

  •    P1=0xfd;       //P1.2引脚输出低电平

  •    P3=LEDTab[d[1]];         //显示十位

  •     delay(1);

  •     db=0;

  •    P1=0xfb;       //P1.1引脚输出低电平

  •    P3=LEDTab[d[2]];         //显示百位

  •    

  •     delay(1);

  •    if (LEDTab[3]!=0)

  •    P1=0xf7;       //P1.0引脚输出低电平

  •    P3=LEDTab[d[3]];         //显示千位

  •    db=0;

  •     delay(1);

  •     P1=0xff;     //关闭所有数码管

  •   

  • }

  • /******************************************************************

  • 函数名:主函数

  • 调  用:无

  • 参  数:无

  • 返回值:无

  • 结  果:程序开始处,无限循环

  • 备  注:

  • ******************************************************************/

  • void main (void)

  • {

  • P1M0 = 0x60; //P1.0/P1.1:0000 0011(高阻)//注意:更改ADC通道时须同时将对应的IO接口修改为高阻输入。

  • P1M1 = 0x00; //P1.0/P1.1:0000 0000

  • while(1){

  • uchar i;

  • delay(1);

  • i++;

  • if (i==30)

  • {

  • transfer();

  • i=0;

  • }

  • xian_shi();

  • //delay(10);

  • }

  • }


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2016-6-19 16:21 | 只看该作者
附图,未以许可,不能引用。
回复

使用道具 举报

板凳
ID:99130 发表于 2016-6-19 17:23 | 只看该作者
yzwzfyz 发表于 2016-6-19 16:21
附图,未以许可,不能引用。

又不是你的,而且本来就是开源的东西,我问了他他没回我我才发的,我会跟他说的,而且我说了抱歉了,如果你不是来提供技术支持的那请你不要管。谢谢
回复

使用道具 举报

地板
ID:99130 发表于 2016-6-19 17:42 | 只看该作者
这是原理图,原作者的图正常上电是显示后面三个0,数码管第二位的小数点显示。正文的图被举报了。没意思
回复

使用道具 举报

5#
ID:79544 发表于 2016-6-19 17:47 | 只看该作者
大家发出来的东西就是让大家相互学习进步的,要不发出来干什么,自己留着就是啦。何必。
回复

使用道具 举报

6#
ID:96682 发表于 2016-6-19 23:13 | 只看该作者
只是好奇 LZ 用啥软件设置烧录到单片机的?
回复

使用道具 举报

7#
ID:96682 发表于 2016-6-19 23:43 | 只看该作者
LZ,原作者用的是 11.0592Mz 的晶振,你却用 12MHz 的晶振。
这不是犯了低级错误嘛?
回复

使用道具 举报

8#
ID:99130 发表于 2016-6-20 11:34 | 只看该作者
wc86110 发表于 2016-6-19 23:13
只是好奇 LZ 用啥软件设置烧录到单片机的?

有一个软件叫STC ISP
回复

使用道具 举报

9#
ID:99130 发表于 2016-6-20 11:34 | 只看该作者
wc86110 发表于 2016-6-19 23:43
LZ,原作者用的是 11.0592Mz 的晶振,你却用 12MHz 的晶振。
这不是犯了低级错误嘛?

12M更准确 问题不是在这现在是连显示都不行
回复

使用道具 举报

10#
ID:123289 发表于 2016-6-20 12:14 | 只看该作者
7楼:
“LZ,原作者用的是 11.0592Mz 的晶振,你却用 12MHz 的晶振。
这不是犯了低级错误嘛?”
不认同这一点,用哪个都可以,只是在相关时间的细节处理上注意一下就可以了。估计对本例无所谓。
回复

使用道具 举报

11#
ID:123289 发表于 2016-6-20 12:18 | 只看该作者
第18脚,是电压输入吧?
你在17脚用TL431将参考电压置于2.5V,那么18脚的正常工作电压就是0-2.5V,电压输入依此据来分压即可。
但是你不能保证:超过VCC的电压,传到18脚来伤及IC(外接100V或更高的意外入侵),所以建议用一只稳压二极管(稳压值大于2.5V,在VCC附近)并在18脚,用于吸收意外超过VCC的电压,保护IC。这样就将输入至18脚的电压限制在:-0.7至VCC之间。当正常工作时,二极管不工作(<2.5V),不影响电阻分压。而出现异常时,比如输入100V接反了,变成-100V,18脚电压就会被限制在-0.7V,从而保护IC。
在没有保护的情况下,一旦18脚被异常电压攻击(或者是瞬间的),会出什么情况,就无法预料了。包括你现在的现象也会发生。
回复

使用道具 举报

12#
ID:123289 发表于 2016-6-20 12:28 | 只看该作者
本帖最后由 yzwzfyz 于 2016-6-20 12:59 编辑

数码管ABCDEFGH,应分别加一个电阻(共用八个),再接入IC。
电阻阻值=[电源电压VCC(5V)-Q1或4的导通压降(取0.4V)-LED段压降(取1.4V)-IO口低电平输出电压(取0.5V)]/(LED段电流,扫描显示取大一点,20mA吧,如果不是扫描显示就取10mA。)
不加电阻电阻不一定坏,但一定不好,对IC或电源7805,都不好,热!
回复

使用道具 举报

13#
ID:123289 发表于 2016-6-20 12:29 | 只看该作者
TL431上并个电容(17脚),以降低参考电压的噪声。
回复

使用道具 举报

14#
ID:123289 发表于 2016-6-20 12:41 | 只看该作者
本帖最后由 yzwzfyz 于 2016-6-20 12:58 编辑

电源用78L05是有风险的。你查一下手册就明白了,不给建议了。
这是一般想不到的问题。
不说别的,就一个LED,如果8个段同时亮显示”8.“。我建议加电阻后的电流是20*8=160mA ,你现在的电路无电阻限流估计会比这个大许多,再加上其它用电的部分,你计算一下78L05的供电能力。如果不是扫描显示,显8888呢?70*4。
更要命的是,电流不是恒定的,扫描显示,LED内容又不确定,电流脉动大,设计电源总要有富裕吧。
明白后就很好处理了。
回复

使用道具 举报

15#
ID:123289 发表于 2016-6-20 12:45 | 只看该作者
关于C2,C3的设计,麻烦,就不说了,
直接建议:
C2不小于220uF吧,
C3保持。
回复

使用道具 举报

16#
ID:99130 发表于 2016-6-20 12:54 | 只看该作者
yzwzfyz 发表于 2016-6-20 12:41
电源用78L05是有风险的。你查一下手册就明白了,不给建议了。
这是一般想不到的问题。
不就别的,就一个L ...

那为什么这个图原作者能成功?
回复

使用道具 举报

17#
ID:123289 发表于 2016-6-20 13:04 | 只看该作者
能成功,不保证设计有充足的余量,比如,冬天OK,夏天NG;或偶尔不OK,或时间长了NG。
回复

使用道具 举报

18#
ID:123289 发表于 2016-6-20 13:06 | 只看该作者
ABCDEFG,应尽可能放在同一个口上,比如全在P1,这样软件编写更方便。这是小事。
回复

使用道具 举报

19#
ID:123289 发表于 2016-6-20 13:16 | 只看该作者
我给你建议的东西,教师未必能讲到。
不采用,也一样“行”。
你考虑一下,其中的道理,都是从产品的可靠性来考虑的。这是实用与实验的区别。
学生没有经验。通常不会想到,教书先生如果做少,或看得少,也不一定能考虑到。
况且,这些都是潜在的失效,也只是在特定条件下,才有可能发生意外。
这些对你来说不一定重要,至少不是迫切的问题。

回复

使用道具 举报

20#
ID:123289 发表于 2016-6-20 13:47 | 只看该作者
现在说软件:
你的显示程序部分:
   P1=0xfe;        //P1.3引脚输出低电平
加注:是P1.0=0,可能是显示一位LED,起个名子叫LED0吧。
   delay(1);
加注:LED0只显示了一个delay(1)的时间,还来不及看清楚,就:
   P1=0xfd;       //P1.2引脚输出低电平
加注:这时P1.0=1,LED0被关闭……进入了LED1的显示
  ……
如此LED0,1,2,4,每个只显示了一个delay(1)的时间,就被

    P1=0xff;     //关闭所有数码管
全部关闭了。
-------------------------------------------------------------------------------------------
也就是:4位LED各闪显一下,就全部灭掉。再等下个处理周期(较长时间)
简化下来:4位LED各闪显一下→灭掉→等较长时间→下个轮回。
大部分时间LED都是关闭,要看么,闪一下,又无法看清。
回复

使用道具 举报

21#
ID:123289 发表于 2016-6-20 13:59 | 只看该作者
改正:
做个时间中断(建议5ms),每次中断如下处理:
k=k+1(让K=0-3,=4就复0),K由你增加。
关所有LED;(就是你的这一句:P1=0xff;     //关闭所有数码管)
根据K的值,决定显示哪一位LED(就是从你做的个十百千中选择一个显示;注意,先送数据,后开开关)
要点:先关所有,每次只显示一个位的LED,先送数据,后开开关显示。
回复

使用道具 举报

22#
ID:99130 发表于 2016-6-20 14:23 | 只看该作者
yzwzfyz 发表于 2016-6-20 13:59
改正:
做个时间中断(建议5ms),每次中断如下处理:
k=k+1(让K=0-3,=4就复0),K由你增加。

没看懂
回复

使用道具 举报

23#
ID:123289 发表于 2016-6-20 14:32 | 只看该作者
定义一个计数器(一个变量),起个名子叫K.
回复

使用道具 举报

24#
ID:99130 发表于 2016-6-20 14:33 | 只看该作者
yzwzfyz 发表于 2016-6-20 14:32
定义一个计数器(一个变量),起个名子叫K.

哦 明白了
回复

使用道具 举报

25#
ID:7485 发表于 2016-6-20 22:25 | 只看该作者
wc86110 发表于 2016-6-19 23:43
LZ,原作者用的是 11.0592Mz 的晶振,你却用 12MHz 的晶振。
这不是犯了低级错误嘛?

对于图中的外设,11.0592,12.0000都不会有楼主说的问题。
回复

使用道具 举报

26#
ID:96682 发表于 2016-6-21 13:58 | 只看该作者
LZ,这个电压表真能测量到 99 V ?
回复

使用道具 举报

27#
ID:99130 发表于 2016-6-21 16:16 | 只看该作者
wc86110 发表于 2016-6-21 13:58
LZ,这个电压表真能测量到 99 V ?

这个主要是看程序,硬件没多大影响
回复

使用道具 举报

28#
ID:157268 发表于 2017-1-14 00:16 | 只看该作者
本人亲测了一次,此程序确实有问题。数码管动作有问题
回复

使用道具 举报

29#
ID:95809 发表于 2017-1-16 17:58 来自手机 | 只看该作者
安羽 发表于 2017-1-14 00:16
本人亲测了一次,此程序确实有问题。数码管动作有问题

在开发板上搭了一下,确实有问题,但还没细查。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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