小白请教大神关于四位数码管的显示问题。。。。。。
大家好,好久不见,忙了几个月终于有时间了。下面这个程序是电子温度计(温度传感器接模拟口A0)中,关于模拟数值在四位数码管上如何显示的部分,我用来修改下,来显示0-1023模拟数值(比如电位计),但是不成功,问题是有的数字,比如 3,5,8,9显示正常,但0,1,2,7,4,等其他数字显示就不正常,不是少笔画就是多笔画,我就把他程序里面关于四位数码管显示的部分单独拿出来,请教下大神,每句大概是个什么意思,然后来解决我的显示问题。
请教大神给逐句翻译下,谢谢了。
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++){
bytemasked = intial_byte & num_mask;
if ( masked== B0 ){
output = LOW;
}
else{
output = HIGH;
}
digitalWrite(ledPinArray,output);
intial_byte = intial_byte>>1;
}
delay(1);
} ;P 原来还真有人跟我一样返璞归真,直接用Arduino驱动数码管啊。
我现在弄的一个,跟你的很像,只是我用A1检测电压,低于11报警。
个人建议:1.你的显示子程序中,有好多都应该放在setup()里,pinMode,数组之类的。
2.显示数字有问题可能是:扫描速度与时间不太好,或者没有消影,比较倾向于后者。
晒一下我的程序(写时也借鉴了别人滴)
/*
程序功能: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 = { ASeg, BSeg, CSeg, DSeg, ESeg, FSeg, GSeg };
// 定义显示0-9的二维数组
//0代表亮,1代表灭(因为是共阳极,公共脚是1
byte seven_seg_digits = { { 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);
}
}
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();
} 本帖最后由 yqfans 于 2015-5-22 11:02 编辑
我觉得数码管很有用,我想用在需要简单显示数值的地方,省电,应该也不容易出故障,液晶应该再怎么也比这个费电吧,而且摔的话,应该树数码管更抗摔打。
我看了你程序里包含驱动数码管的地方,就是这个地方,是什么意思?后面是二进制的数值么?100111?这个我查了下并不是十位数的0 ,这里到底是什么意思?
byte seven_seg_digits = { { 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
};
对了,我用的四位数码管是共阴的,和共阳的比较驱动的程序有什么不同么? wwwusr 发表于 2015-5-20 20:19 static/image/common/back.gif
原来还真有人跟我一样返璞归真,直接用Arduino驱动数码管啊。
我现在弄的一个,跟你的很像,只是我用A1 ...
//设置阳极接口
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int f = 6;
int g = 7;
int p = 8;
//设置阴极接口
int d4 = 9;
int d3 = 10;
int d2 = 11;
int d1 = 12;
byte segs = { a, b, c, d, e, f, g };
byte seven_seg_digits = { { 1,1,1,1,1,1,0 },// = 0
{ 1,1,0,0,0,0,0 },// = 1
{ 1,0,1,1,0,1,1 },// = 2
{ 1,1,1,0,0,1,1 },// = 3
{ 1,1,0,0,1,0,1 },// = 4
{ 0,1,1,0,1,1,1 },// = 5
{ 0,1,1,1,1,1,1 },// = 6
{ 1,1,0,0,1,1,0 },// = 7
{ 1,1,1,1,1,1,1 },// = 8
{ 1,1,1,0,1,1,1 } // = 9
};
void setup()
{
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);
pinMode(p, OUTPUT);
Serial.begin(9600);
}
int moistureSensor=0;
int moisture_val;
void loop()
{
moisture_val=analogRead(moistureSensor);
Serial.print("moisture sensor reads=");
Serial.println(moisture_val);
delay(500);
clearLEDs();
pickDigit(1);
lightSegments(moisture_val/1000);
//delayMicroseconds(del);
delay(500);
clearLEDs();
pickDigit(2);
lightSegments((moisture_val/100)%10);
// delayMicroseconds(del);
delay(500) ;
clearLEDs();
pickDigit(3);
//dispDec(3);
lightSegments((moisture_val/10)%10);
//delayMicroseconds(del);
delay(500);
clearLEDs();
pickDigit(4);
lightSegments(moisture_val%10);
//delayMicroseconds(del);
delay(500);
}
void pickDigit(int x)//定义pickDigit(x),其作用是开启dx端口
{
digitalWrite(d1, HIGH);
digitalWrite(d2, HIGH);
digitalWrite(d3, HIGH);
digitalWrite(d4, HIGH);
switch(x)
{
case 1:
digitalWrite(d1, LOW);
break;
case 2:
digitalWrite(d2, LOW);
break;
case 3:
digitalWrite(d3, LOW);
break;
default:
digitalWrite(d4, LOW);
break;
}
}
void clearLEDs()//清屏
{
digitalWrite(a, LOW);
digitalWrite(b, LOW);
digitalWrite(c, LOW);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
digitalWrite(p, LOW);
}
// 点亮对应数字的数码管
void lightSegments(int x) {
for (int i = 0; i < 8; i++) {
digitalWrite(segs, seven_seg_digits);
}
}
上面是我参考秒表程序写的程序,大致能显示A0口模拟信号的数值了,但现在有两个问题:
1,数字显示还是有错误,比如打开COM口看到数值是150,显示在数码管是190;看到数值是160,显示在数码管是180;其他还都能正常显示,就是说,该显示5的,显示成了9,该显示6的显示成了8,我不知道是怎么回事,定义数组那里的地方,我查过了,没有错,也试过秒表程序,都正常显示,不知道是怎么回事?
2,现在数码管的显示方式是,数码管上从左至右挨个显示,比如显示数值137,显示为数字为0,1,3,7,而且每次都只能一个数字数码管亮,就像跑马灯一样的,能不能改成四位一起亮,一直有数字,但在不停的变化的那种显示方式?
求大神指点。。。 yqfans 发表于 2015-5-24 10:48 static/image/common/back.gif
//设置阳极接口
int a = 1;
int b = 2;
1.你确定数组没有问题?我怎么看得稀里糊涂的。。。
2.delay太长了,改小点儿,50,20,什么的,得试试确定 延时要改小,刷新一遍约 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);
}
这是很早以前做的超声波测距的,有点啰嗦,可以参考。 本帖最后由 yqfans 于 2015-5-25 11:04 编辑
wwwusr 发表于 2015-5-24 20:44 static/image/common/back.gif
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个数字常亮,完了数值有变化,但不能看到频闪,这个我还在研究,有好办法和我说说。 164335413 发表于 2015-5-25 10:19 static/image/common/back.gif
延时要改小,刷新一遍约 40 ms,也就是每个字亮10ms,这样显示的会连续些,
unsigned int EchoPin = 13; ...
改成1也还是看到频闪,论坛上有个4位数码管的秒表的程序,那个数字就不会闪,也不知道我这个能不能改成这样的显示方式http://www.geek-workshop.com/thread-82-1-1.html
页:
[1]