数码之家

 找回密码
 立即注册
搜索
查看: 3661|回复: 21

[C51] 电子钟仿真没问题,做电路出不来是什么原因啊

[复制链接]
发表于 2020-6-23 08:05:21 | 显示全部楼层 |阅读模式
刚接触单片机,想做一个电子钟,照着网上的例子用isis仿真,没有问题,
file:///C:/Users/杨宏波/AppData/Roaming/Tencent/Users/123770116/QQ/WinTemp/RichOle/FU)CNUW66D%60(37T7LH~MXIP.png


然后自己做了实物,但是只有一段亮,其他段微亮,而且显示也不是数字,两个秒点显示正常,按钮功能正常
file:///C:/Users/杨宏波/AppData/Roaming/Tencent/Users/123770116/QQ/WinTemp/RichOle/C@ZK2BG@)M5VQ)CQ9]T03%7B1.png


确定段码a的亮度偏大,去掉a段后,显示还是不正常

数码管是共阴的,段码接了3k的上拉电阻,




这个是HEX文件,源码不会烤,找不到是哪个了,请高手指点下



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 2020-6-23 09:27:16 | 显示全部楼层
只有一段点亮,大部分问题出在刷新上了,可能刷完后延迟太高,导致程序停留在某个位置时间太长,这样某一段就会比其它段亮不少。
回复 支持 反对

使用道具 举报

发表于 2020-6-23 09:46:25 | 显示全部楼层
显示的延时,不对

导致太快,看不着
回复 支持 反对

使用道具 举报

发表于 2020-6-23 11:21:07 | 显示全部楼层
本帖最后由 qrut 于 2020-6-23 11:58 编辑

p0口每一位都得加100欧电阻限流(不然被vf低的某段钳位,其它亮不了),1位数码管最多8个led 位选直接用p1口拖不动,得加四个三极管驱动。另外p0口加10k上拉就行,3k太小了。扫描程序for循环每位扫描完加个延时,将p1.0-1.3拉高消隐~

打赏

参与人数 1家元 +20 收起 理由
亲爱的混蛋 + 20

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2020-6-23 13:35:36 | 显示全部楼层
我猜你的显示刷新代码是放在主循环中,并且靠延时来实现定时扫描,那么显示成这样就很正常。这种现象是初学者做数码管动态扫描实验时的常见问题,主要是对数据管动态扫描的显示原理理解不够深入。具体原因就是,受主循环中其他代码的影响,每个字段实际点亮的时间严重不同。

解决方法是:使用一个定时器工作在中断模式,显示定时刷新代码放入定时器中断中,可以每20mS刷新一次。
回复 支持 反对

使用道具 举报

发表于 2020-6-23 13:52:01 | 显示全部楼层
本帖最后由 bg4uvr 于 2020-6-23 14:26 编辑

稍微再说详细点:

1、定时器可以设置为每5mS溢出,溢出中断中,每次换一个位来显示。比如现在显示第1位,下一次中断就去显示第2位,后来是第3位、第4位,再循环显示第1位。这样4个位,每个显示5mS的时间,整体刷新一次的时间为20mS,实际效果是基本不会感觉到闪烁。

2、另外4楼说的驱动问题也是存在的。
回复 支持 反对

使用道具 举报

发表于 2020-6-23 14:07:01 来自手机浏览器 | 显示全部楼层
本帖最后由 bg4uvr 于 2020-6-23 14:27 编辑

原说明有误,请删除本帖
回复 支持 反对

使用道具 举报

发表于 2020-6-23 19:45:26 | 显示全部楼层
如果是第一次玩LED数码管,建议先将一位数码的位控制(某一个共阴极com)端置0,而后发0-9的段码,如果这一位数码显示都正常了再固定的发送某一个数字的段码来调试4个位的扫描显示,等到4位数码可以正常的显示同一个数字以后接下来就简单了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-23 19:46:37 来自手机浏览器 | 显示全部楼层
感谢各位热心解答,准备重新焊一个板,换10k上拉试试,装了上拉还需要每段一个限流电阻吗?程序现在还看不懂,先从实物找原因吧
回复 支持 反对

使用道具 举报

发表于 2020-6-23 21:51:06 | 显示全部楼层
如果按钮有用,说明程序在跑,记忆中51的P0口是OC门,SEG接P0的话,应该用共阳的数码管,你用共阴的数码管应该是不行的
回复 支持 反对

使用道具 举报

发表于 2020-6-23 23:26:04 | 显示全部楼层
数码管是共阴的,3K的上拉,数码管应该是比较暗的。
a段比较亮,说明a段的平均电流比较大。
检查a段所接的上拉电阻阻值是否正常,是不是误装了300欧的;
数码管在更新显示数据时,有没有先关闭显示。
回复 支持 反对

使用道具 举报

发表于 2020-6-23 23:29:45 | 显示全部楼层
pooooyhb 发表于 2020-6-23 19:46
感谢各位热心解答,准备重新焊一个板,换10k上拉试试,装了上拉还需要每段一个限流电阻吗?程序现在还看不 ...

你这个电路主要问题是单片机直驱,没有三态门之类的驱动,p0负责段码,led驱动电流完全p0上拉提供,51的io口总灌电流应该是24ma(太久了记不清了)如果p0全低电平3k限流 每个io口电流就得1.7ma, 8个就得13.6ma,还有其他端口需要灌电流,这样有可能到极限,换大上拉扫描起来led的电流又有可能不够,总之你要直驱必须选驱动电流小的数码管,位选一定要加三极管的,p1口位选程序里做个 非 处理,输出串10k电阻,大点也行,到三极管基极,发射极接地,集电极接数码管阴极位选,npn管。上拉你先3k试试,亮度不够就得换小,但是不能太小,亮度足够可以换大点儿,100欧电阻如果加了三极管可以不加。最好把扫描放到定时器中断里,放到while主循环里你按键可能会闪~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-24 01:23:46 来自手机浏览器 | 显示全部楼层
感谢大家的帮助,现在换了一个带排阻的最小系统,然后把3k电阻当限流用了(手头没有材料了,先将就下,实际影响不大,LED亮度降了一点),现在每个LED显示正常,但字码是错的,程序能看的出来运转正常,字码乱应该是程序问题,正在一点点扣,学历不够,看不懂啊,

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-24 01:27:13 来自手机浏览器 | 显示全部楼层
qrut 发表于 2020-6-23 23:29
你这个电路主要问题是单片机直驱,没有三态门之类的驱动,p0负责段码,led驱动电流完全p0上拉提供,51的i ...

我的数码管不大,直接驱动感觉也可以正常运行,还有程序方面,真的看不懂(#-.-)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-24 01:37:41 | 显示全部楼层
下面是源程序,网上抄的,如有侵权请原谅,刚找出来大家看看,现在问题是显示字码不对,但单片机还是正常跑着,我看程序里关于共阴数码管的字符定义也没有问题,剩下的看不懂了,也不知道哪的问题,用小数码管,51直驱感觉问题不大,可以运转

#include<reg52.h>
sbit P13=P1^3; //分个位控制端,数码管第四位
sbit P12=P1^2; //分十位控制端
sbit P11=P1^1; //时个位控制端
sbit P10=P1^0; //时十位控制端 数码管第1位
sbit led=P2^7; //秒闪烁 led单独接两个二极管发光
sbit key0=P3^7; //模式设置 按键1
sbit key1=P3^6; //加
sbit key2=P3^5; //减
unsigned char hour,min,sec,T50ms;//定义5个变量
unsigned char modstate; //模式状态
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};//段码 (0--9、黑屏)
//unsigned char code tablemin[]={0xc0,0xcf,0xa4,0x86,0x8b,0x92,0x90,0xc7,0x80,0x82};//秒十位倒置编码
void init();                                        //初始化子程序声明 /
void delay500us(unsigned char X); //延时子程序声明
void display();                                 //显示子程序声明
void display001();                           //显示“时”子程序声明
void display002();                           //显示“分”子程序声明
void keyscan();                               //按键识别子程序声明
void main()
{  
init();
while(1)
{
  keyscan();
}
}
void init() //初始化子程序
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
ET0=1;
EA=1;
TR0=1;
}
void delay500us(unsigned char X)
{
unsigned char i,j;
for(i=X;i>0;i--)
for(j=248;j>0;j--);
}
void timer0() interrupt 1 //timer0中断服务子程序,定时时间为50ms,本程序加了10us的时间修正量
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
T50ms++;
if(T50ms>=20)
{
  T50ms=0;
  sec++;
  if(sec>=60)
  {
   sec=0;
   min++;
   if(min>=60)
   {
    min=0;
    hour++;
    if(hour>=24)hour=0;
   }
  }
}
}
        
void display()
{
P1=0xff;
P0=table[hour/10];
P10=0;
delay500us(5);
P1=0xff;
    P0=table[hour%10];
P11=0;
delay500us(5);
P1=0xff;
P0=table[min/10];
P12=0;
delay500us(5);
P1=0xff;
P0=table[min%10];
P13=0;
delay500us(5);
if(T50ms<=10)led=0;
if(T50ms>10)led=1;
}
void display001()
{
     P1=0xff;
P0=table[hour/10];
P10=0;
delay500us(10);

  P1=0xff;
P0=table[hour%10];
P11=0;
delay500us(10);
}
void display002()
{
  P1=0xff;
P0=table[min/10];
P12=0;
delay500us(10);
  P1=0xff;
P0=table[min%10];
P13=0;
delay500us(10);
}
void keyscan()  //按键识别钟程序
{
while(modstate==0)
{
  display();
  if(key0==0)
  {
   display();
   if(key0==0)modstate++;  //这两句加在一起为延时10ms软件防抖设计。
   while(key0==0)display001(); //等待按键释放。
  }
}
//****************************************************************************//
while(modstate==1)
{
  display001();
  if(key0==0)
  {
   display001();
   if(key0==0)modstate++;  //这两句加在一起为延时10ms软件防抖设计。
   while(key0==0)display002(); //等待按键释放。
  }
  if(key1==0)
  {
   display001();
   if(key1==0)
   {
    hour++;
    if(hour>=24)hour=0;
    while(key1==0)display001();
   }
  }
  if(key2==0)
  {
   display001();
   if(key2==0)
   {
    hour--;
    if(hour>=24)hour=0;
    while(key2==0)display001();
   }
  }
}
//****************************************************************************//
while(modstate==2)
{
  display002();
  if(key0==0)
  {
   display002();
   if(key0==0)modstate=0;  //这两句加在一起为延时10ms软件防抖设计。
   while(key0==0)display(); //等待按键释放。
  }
  if(key1==0)
  {
   display002();
   if(key1==0)
   {
    min++;
    if(min>=60)min=0;
    while(key1==0)display002();
   }
  }
  if(key2==0)
  {
   display002();
   if(key2==0)
   {
    min--;
    if(min>=60)min=0;
    while(key2==0)display002();
   }
  }
}
}
回复 支持 反对

使用道具 举报

发表于 2020-6-24 09:29:31 | 显示全部楼层
最好是开辟一个影子内存,把要显示的内容在影子内存中设置好,然后定时从IO口发出来显示。譬如2ms一次,完全不用也不要在中断中送显。
回复 支持 反对

使用道具 举报

发表于 2020-6-24 13:23:24 来自手机浏览器 | 显示全部楼层
sz1988 发表于 2020-6-24 09:29
最好是开辟一个影子内存,把要显示的内容在影子内存中设置好,然后定时从IO口发出来显示。譬如2ms一次,完 ...

51有这玩意么
回复 支持 反对

使用道具 举报

发表于 2020-6-24 18:08:41 | 显示全部楼层
本帖最后由 慕名而来 于 2020-6-24 18:15 编辑

不太懂楼上“影子内存”的意思,我的LED数码管的驱动代码都要设一个显示数据暂存的数组,例如:5位数码就有一个uchar SEG[5];如果是楼主这样单片机直驱的方式我还要加一个uchar WEI[5];这样一来所有送显示的数据计算、变换好了以后填入SEG[5]中,显示的时候
  1. for(i=0;i<5;i++)
  2. {
  3. P0= table[SEG[i]];
  4. P1=WEI[i];
  5. delay_ms(3);
  6. }
复制代码


回复 支持 反对

使用道具 举报

发表于 2020-6-26 20:56:23 | 显示全部楼层
你的LED数显管是共阴极还是共阳极?
共阴极的,P1端口设置推挽,P0设置开漏;共阳极的反之。试试。
回复 支持 反对

使用道具 举报

发表于 2020-6-30 06:42:35 来自手机浏览器 | 显示全部楼层
感觉少了四个三极管8050的
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-13 08:51 , Processed in 0.436801 second(s), 15 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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