极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15325|回复: 7

小白请教大神关于四位数码管的显示问题。。。。。。

[复制链接]
发表于 2015-5-20 17:23:05 | 显示全部楼层 |阅读模式
大家好,好久不见,忙了几个月终于有时间了。
下面这个程序是电子温度计(温度传感器接模拟口A0)中,关于模拟数值在四位数码管上如何显示的部分,我用来修改下,来显示0-1023模拟数值(比如电位计),但是不成功,问题是有的数字,比如 3,5,8,9显示正常,但0,1,2,7,4,等其他数字显示就不正常,不是少笔画就是多笔画,我就把他程序里面关于四位数码管显示的部分单独拿出来,请教下大神,每句大概是个什么意思,然后来解决我的显示问题。

请教大神给逐句翻译下,谢谢了。


[pre lang="arduino" line="1" file="xianshi"]void display_num(int ledPinArray[],int number){
  //ledPinArray must be ABCDEFGH
  //default mask is LOW for positive share tube
  for(int i=0;i<=8;i++){
    pinMode(ledPinArray,OUTPUT);
  }
  //0 to 9 mask
  byte num_mask[] = {B11111100,B01100000,B11011010,B11110010,B01100110,B10110110,
                     B10111110,B11100000,B11111110,B11100110,B11000110,B10011100};
  
  byte intial_byte = B10000000;
  int masked,output;
  for(int i=0;i<=8;i++){
  byte  masked = intial_byte & num_mask[number];
    if (   masked  == B0 ){
      output = LOW;
    }
    else{
       output = HIGH;
    }
    digitalWrite(ledPinArray,output);
    intial_byte = intial_byte>>1;
  }
  delay(1);
}[/code]
回复

使用道具 举报

发表于 2015-5-20 20:19:31 | 显示全部楼层
原来还真有人跟我一样返璞归真,直接用Arduino驱动数码管啊。
我现在弄的一个,跟你的很像,只是我用A1检测电压,低于11报警。

个人建议:1.你的显示子程序中,有好多都应该放在setup()里,pinMode,数组之类的。
               2.显示数字有问题可能是:扫描速度与时间不太好,或者没有消影,比较倾向于后者。
晒一下我的程序(写时也借鉴了别人滴)
[pre lang="arduino" line="1" file="A1_7SEG"]/*
   程序功能:A1口检测电压,低于11V报警
   Techie 13531382
   15.05.20
*/
// 定义7段数码管的各段对应的Arduino管脚号
#define ASeg 6
#define BSeg 5
#define CSeg 11
#define DSeg 9
#define ESeg 13
#define FSeg 7
#define GSeg 8
#define HSeg 12

//用的共阳极数码管,十位,个位对应10、4号脚
#define CA10 10
#define CA1 4
// 定义数码管数组
byte segs[7] = { ASeg, BSeg, CSeg, DSeg, ESeg, FSeg, GSeg };

// 定义显示0-9的二维数组
//0代表亮,1代表灭(因为是共阳极,公共脚是1
byte seven_seg_digits[10][7] = { { 0,0,0,0,0,0,1 },  // = 0
                                 { 1,0,0,1,1,1,1 },  // = 1
                                 { 0,0,1,0,0,1,0 },  // = 2
                                 { 0,0,0,0,1,1,0 },  // = 3
                                 { 1,0,0,1,1,0,0 },  // = 4
                                 { 0,1,0,0,1,0,0 },  // = 5
                                 { 0,1,0,0,0,0,0 },  // = 6
                                 { 0,0,0,1,1,1,1 },  // = 7
                                 { 0,0,0,0,0,0,0 },  // = 8
                                 { 0,0,0,0,1,0,0 }   // = 9
                             };                             
                             
void setup() {
  pinMode(ASeg, OUTPUT);
  pinMode(BSeg, OUTPUT);
  pinMode(CSeg, OUTPUT);
  pinMode(DSeg, OUTPUT);
  pinMode(ESeg, OUTPUT);
  pinMode(FSeg, OUTPUT);
  pinMode(GSeg, OUTPUT);
  pinMode(HSeg, OUTPUT);
  pinMode(CA10, OUTPUT);
  pinMode(CA1, OUTPUT);
}
  
void loop() {
  clean();//清屏,然后进while(1)无限循环
  while(1){
           display();//显示子函数,如果电
           int alm = analogRead(A1);//再取一次A1值,作为报警的输入值
           if(alm <= 465){ //如果A1值低于这个值,即检测的电压低于11V,就一边显示,一边报警
                           //如果A1值高于这个值,就不会进入这个if,一直显示电压值
                         for(int i=200;i>0;i--){//扫描显示200次(时间也不长),报警一下,是为了使显示正常,不闪烁,不虚
                                               display();
                                               }
                          alarm();//报警
                         }
        }
}

// 个位数显示
void lightDigit1(byte number) {
  digitalWrite(CA1,HIGH);
  digitalWrite(CA10,LOW);  
  lightSegments(number);  
}

// 十位数显示
void lightDigit2(byte number) {
  digitalWrite(CA10,HIGH);
  digitalWrite(CA1,LOW);
  lightSegments(number);
}

// 显示算法
void lightSegments(byte number) {
  for (int i = 0; i < 7; i++) {
    digitalWrite(segs, seven_seg_digits[number]);
  }  
}

void clean(){//用于清屏,或消影(在显示下一位前,先让整个屏黑一下,就不会在显示当前值时,带着上一个数的虚影)
  for(int i = 0;i<7;i++){
    digitalWrite(segs,HIGH);
  }
  digitalWrite(12,HIGH);
}

void alarm(){//报警,闪烁数码管上小数点,连带蜂鸣器
  digitalWrite(CA10,HIGH);
  digitalWrite(CA1,HIGH);
  digitalWrite(HSeg,LOW);
  delay(500);
  digitalWrite(HSeg,HIGH);
  delay(500);
}
  
  void display(){//检测,显示子函数
  int value = analogRead(A1);//取A1值
  int voltage = map(value,465,615,110,144);//换算到需要的范围
  int voltage1 = voltage/10;//缩小10倍,用于数码管显示,反正显示数值只有2位,不用太精确
      //显示个位值
      lightDigit1(voltage1%10);
      delay(2);
      clean();
      // 显示十位值
      lightDigit2(voltage1/10);
      delay(2);
      clean();   
  }   [/code]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-22 10:51:31 | 显示全部楼层
本帖最后由 yqfans 于 2015-5-22 11:02 编辑

    我觉得数码管很有用,我想用在需要简单显示数值的地方,省电,应该也不容易出故障,液晶应该再怎么也比这个费电吧,而且摔的话,应该树数码管更抗摔打。

    我看了你程序里包含驱动数码管的地方,就是这个地方,是什么意思?后面是二进制的数值么?100111?这个我查了下并不是十位数的0 ,这里到底是什么意思?
byte seven_seg_digits[10][7] = { { 0,0,0,0,0,0,1 },  // = 0
                                 { 1,0,0,1,1,1,1 },  // = 1
                                 { 0,0,1,0,0,1,0 },  // = 2
                                 { 0,0,0,0,1,1,0 },  // = 3
                                 { 1,0,0,1,1,0,0 },  // = 4
                                 { 0,1,0,0,1,0,0 },  // = 5
                                 { 0,1,0,0,0,0,0 },  // = 6
                                 { 0,0,0,1,1,1,1 },  // = 7
                                 { 0,0,0,0,0,0,0 },  // = 8
                                 { 0,0,0,0,1,0,0 }   // = 9
                             };

对了,我用的四位数码管是共阴的,和共阳的比较驱动的程序有什么不同么?                          
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-24 10:48:30 | 显示全部楼层
wwwusr 发表于 2015-5-20 20:19
原来还真有人跟我一样返璞归真,直接用Arduino驱动数码管啊。
我现在弄的一个,跟你的很像,只是我用A1 ...
  1. //设置阳极接口
  2. int a = 1;
  3. int b = 2;
  4. int c = 3;
  5. int d = 4;
  6. int e = 5;
  7. int f = 6;
  8. int g = 7;
  9. int p = 8;
  10. //设置阴极接口
  11. int d4 = 9;
  12. int d3 = 10;
  13. int d2 = 11;
  14. int d1 = 12;

  15. byte segs[7] = { a, b, c, d, e, f, g };

  16. byte seven_seg_digits[10][7] = { { 1,1,1,1,1,1,0 },  // = 0
  17.                                  { 1,1,0,0,0,0,0 },  // = 1
  18.                                  { 1,0,1,1,0,1,1 },  // = 2
  19.                                  { 1,1,1,0,0,1,1 },  // = 3
  20.                                  { 1,1,0,0,1,0,1 },  // = 4
  21.                                  { 0,1,1,0,1,1,1 },  // = 5
  22.                                  { 0,1,1,1,1,1,1 },  // = 6
  23.                                  { 1,1,0,0,1,1,0 },  // = 7
  24.                                  { 1,1,1,1,1,1,1 },  // = 8
  25.                                  { 1,1,1,0,1,1,1 }   // = 9
  26.                              };

  27. void setup()
  28. {
  29.   pinMode(d1, OUTPUT);
  30.   pinMode(d2, OUTPUT);
  31.   pinMode(d3, OUTPUT);
  32.   pinMode(d4, OUTPUT);
  33.   pinMode(a, OUTPUT);
  34.   pinMode(b, OUTPUT);
  35.   pinMode(c, OUTPUT);
  36.   pinMode(d, OUTPUT);
  37.   pinMode(e, OUTPUT);
  38.   pinMode(f, OUTPUT);
  39.   pinMode(g, OUTPUT);
  40.   pinMode(p, OUTPUT);
  41.   Serial.begin(9600);
  42. }
  43. int moistureSensor=0;
  44. int moisture_val;

  45. void loop()
  46. {
  47.   
  48.   moisture_val=analogRead(moistureSensor);
  49.    Serial.print("moisture sensor reads=");
  50.    Serial.println(moisture_val);
  51.    delay(500);
  52.   
  53.   clearLEDs();
  54.   pickDigit(1);
  55.   lightSegments(moisture_val/1000);
  56.   //delayMicroseconds(del);
  57.   delay(500);

  58.   clearLEDs();
  59.   pickDigit(2);
  60.   lightSegments((moisture_val/100)%10);
  61. // delayMicroseconds(del);
  62.   delay(500) ;
  63.   
  64.   clearLEDs();
  65.   pickDigit(3);
  66.   //dispDec(3);
  67.   lightSegments((moisture_val/10)%10);
  68.   //delayMicroseconds(del);
  69.   delay(500);
  70.   
  71.   clearLEDs();
  72.   pickDigit(4);
  73.   lightSegments(moisture_val%10);
  74.   //delayMicroseconds(del);
  75.   delay(500);
  76. }

  77. void pickDigit(int x)  //定义pickDigit(x),其作用是开启dx端口
  78. {
  79.   digitalWrite(d1, HIGH);
  80.   digitalWrite(d2, HIGH);
  81.   digitalWrite(d3, HIGH);
  82.   digitalWrite(d4, HIGH);

  83.   switch(x)
  84.   {
  85.   case 1:
  86.     digitalWrite(d1, LOW);
  87.     break;
  88.   case 2:
  89.     digitalWrite(d2, LOW);
  90.     break;
  91.   case 3:
  92.     digitalWrite(d3, LOW);
  93.     break;
  94.   default:
  95.     digitalWrite(d4, LOW);
  96.     break;
  97.   }
  98. }

  99. void clearLEDs()  //清屏
  100. {
  101.   digitalWrite(a, LOW);
  102.   digitalWrite(b, LOW);
  103.   digitalWrite(c, LOW);
  104.   digitalWrite(d, LOW);
  105.   digitalWrite(e, LOW);
  106.   digitalWrite(f, LOW);
  107.   digitalWrite(g, LOW);
  108.   digitalWrite(p, LOW);
  109. }


  110. // 点亮对应数字的数码管
  111. void lightSegments(int x) {
  112.   for (int i = 0; i < 8; i++) {
  113.     digitalWrite(segs[i], seven_seg_digits[x][i]);
  114.   }
  115. }
复制代码



上面是我参考秒表程序写的程序,大致能显示A0口模拟信号的数值了,但现在有两个问题:

1,数字显示还是有错误,比如打开COM口看到数值是150,显示在数码管是190;看到数值是160,显示在数码管是180;其他还都能正常显示,就是说,该显示5的,显示成了9,该显示6的显示成了8,我不知道是怎么回事,定义数组那里的地方,我查过了,没有错,也试过秒表程序,都正常显示,不知道是怎么回事?

2,现在数码管的显示方式是,数码管上从左至右挨个显示,比如显示数值137,显示为数字为0,1,3,7,而且每次都只能一个数字数码管亮,就像跑马灯一样的,能不能改成四位一起亮,一直有数字,但在不停的变化的那种显示方式?

求大神指点。。。
回复 支持 反对

使用道具 举报

发表于 2015-5-24 20:44:13 | 显示全部楼层
yqfans 发表于 2015-5-24 10:48
//设置阳极接口
int a = 1;
int b = 2;

1.你确定数组没有问题?我怎么看得稀里糊涂的。。。
2.delay太长了,改小点儿,50,20,什么的,得试试确定
回复 支持 反对

使用道具 举报

发表于 2015-5-25 10:19:17 | 显示全部楼层
延时要改小,刷新一遍约 40 ms,也就是每个字亮10ms,这样显示的会连续些,

unsigned int EchoPin = 13;       //将Arduino 的 Pin2 连接至 HC-SR04 的Echo/RX
unsigned int TrigPin = 8;       //将Arduino 的 Pin3 连接至 HC-SR04 的Trig/TX
unsigned long Time_Echo_us = 0; //用于记录传感器返回的脉冲宽度
unsigned long Len_mm  = 0;      //用于存储距离值
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int f = 6;
int g = 7;

int d4 = 9;
int d3 = 10;
int d2 = 11;
int d1 = 12;

int x = 1;
void setup()
{
  pinMode(EchoPin, INPUT);  //设置EchoPin 为输入模式
  pinMode(TrigPin, OUTPUT); //设置TrigPin 为输出模式
  pinMode(d1, OUTPUT);
  pinMode(d2, OUTPUT);
  pinMode(d3, OUTPUT);
  pinMode(d4, OUTPUT);
  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);

}

void loop()
{
  //通过Trig/Pin 发送脉冲,触发 HC-SR04 测距
  digitalWrite(TrigPin, HIGH); //开始通过 Trig/Pin 发送脉冲
  delayMicroseconds(25);       //设置脉冲宽度为 50us (>10us)
  digitalWrite(TrigPin, LOW);  //结束脉冲

  Time_Echo_us = pulseIn(EchoPin, HIGH);           //获取 HC-SR04 返回的脉冲宽度
  if((Time_Echo_us < 60000) && (Time_Echo_us > 1)) //脉冲有效范围(1, 60000)
  {
     //Len_mm = (Time_Echo_us * 0.34mm/us) / 2 (mm)
     Len_mm = (Time_Echo_us * 34 / 100) / 2; //通过脉冲宽度计算距离
  clearLEDs();
  pickDigit(1);
  pickNumber((Len_mm/x/1000)%10);
  delayMicroseconds(1000);

  clearLEDs();
  pickDigit(2);
  pickNumber((Len_mm/x/100)%10);
  delayMicroseconds(1000);

  clearLEDs();
  pickDigit(3);
  //dispDec(3);
  pickNumber((Len_mm/x/10)%10);
  delayMicroseconds(1000);

  clearLEDs();
  pickDigit(4);
  pickNumber(Len_mm/x%10);
  delayMicroseconds(1000);
  }
//delay(1000); //每秒(1000ms)测量一次
}
void pickDigit(int y)
{
  digitalWrite(d1, LOW);
  digitalWrite(d2, LOW);
  digitalWrite(d3, LOW);
  digitalWrite(d4, LOW);

  switch(y)
  {
  case 1:
    digitalWrite(d1, HIGH);
    break;
  case 2:
    digitalWrite(d2, HIGH);
    break;
  case 3:
    digitalWrite(d3, HIGH);
    break;
  case 4:
    digitalWrite(d4, HIGH);
    break;
  }
}

void pickNumber(int x)
{
  switch(x)
  {
  default:
    zero();
    break;
  case 1:
    one();
    break;
  case 2:
    two();
    break;
  case 3:
    three();
    break;
  case 4:
    four();
    break;
  case 5:
    five();
    break;
  case 6:
    six();
    break;
  case 7:
    seven();
    break;
  case 8:
    eight();
    break;
  case 9:
    nine();
    break;
  }
}


void clearLEDs()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);

}

void zero()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, HIGH);
}

void one()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void two()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, HIGH);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, HIGH);
  digitalWrite(g, LOW);
}

void three()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, LOW);
}

void four()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void five()
{
  digitalWrite(a, LOW);
  digitalWrite(b, HIGH);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void six()
{
  digitalWrite(a, LOW);
  digitalWrite(b, HIGH);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void seven()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void eight()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void nine()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}


这是很早以前做的超声波测距的,有点啰嗦,可以参考。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-25 10:54:35 | 显示全部楼层
本帖最后由 yqfans 于 2015-5-25 11:04 编辑
wwwusr 发表于 2015-5-24 20:44
1.你确定数组没有问题?我怎么看得稀里糊涂的。。。
2.delay太长了,改小点儿,50,20,什么的,得试试确 ...


1,显示数字5,6不正常的问题解决了,原因可能是我用了1接口,1和TX是一个LED,因为定义a=1,所以,a 的那个位置就是每次都亮,所以5多了一笔,就成了9; 6也多了一笔成了8,其他数字虽然也收影响,但看不出来,呵呵,解决方法是我把1换成用13接口,最后问题解决了。数组那里你看的稀里糊涂,是因为我用的是共阴的4位数码管,而且这个数码管的 a 是从右上的那个管开始顺时针排列的,1代表亮,0代表灭。

2,第二个问题,还是没有解决,修改delay也达不到想要效果,改成1,最后一个字亮,前面三个数字有点暗,而且也能看到频闪。我想要的效果就是4个数字常亮,完了数值有变化,但不能看到频闪,这个我还在研究,有好办法和我说说。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-25 12:27:04 | 显示全部楼层
164335413 发表于 2015-5-25 10:19
延时要改小,刷新一遍约 40 ms,也就是每个字亮10ms,这样显示的会连续些,

unsigned int EchoPin = 13; ...


改成1也还是看到频闪,论坛上有个4位数码管的秒表的程序,那个数字就不会闪,也不知道我这个能不能改成这样的显示方式  http://www.geek-workshop.com/thread-82-1-1.html
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-9 04:00 , Processed in 0.036006 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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