DFR0100 Arduino教程 17--数码管显示
该教程实验平台:(https://www.dfrobot.com.cn/goods-149.html)上一篇教程:(https://mc.dfrobot.com.cn/thread-2538-1-1.html)
数码管,常见的用来显示数字的,比如像计算器。这回我们就要来好好研究一下数码管,看看它是如何工作的。数码管,其实也算是LED中的一种。数码管的每一段,都是一个独立的LED,通过数字引脚来控制相应段的亮灭就能达到显示数字的效果。这个项目要实现的是循环显示数字0~9。
### 所需材料
- 1×八段数码管
- 8×220欧电阻
#### STEP 1: 硬件连接
按下图连线图连接,注意数码管各段所对应的引脚。右边引脚说明图上为什么画这么几个箭头呢?个人觉得,这样看起来更方便。可以给你作为参考。我们从上面一排看,红色箭头的方向,从右往左,b a f g的顺序正好对应,下面红色箭头逆时针顺序b --> a --> f --> g。蓝色箭头也是表达的同样的意思。
我还特意在连接图上,对数码管所连接的引脚做了标示。这样就能更清楚的知道哪个引脚控制哪一段了。这8个电阻同样是起限流的作用。
#### STEP 2: 输入代码
```
void setup(){
for(int pin = 2 ; pin <= 9 ; pin++){ // 设置数字引脚2~9为输出模式
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}
}
void loop() {
// 显示数字0
int n0={0,0,0,1,0,0,0,1};
//数字引脚2~9依次按数组n0中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n0);
}
delay(500);
// 显示数字1
int n1={0,1,1,1,1,1,0,1};
// 数字引脚2~9依次按数组n1中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n1);
}
delay(500);
// 显示数字2
int n2={0,0,1,0,0,0,1,1};
// 数字引脚2~9依次按数组n2中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n2);
}
delay(500);
// 显示数字3
int n3={0,0,1,0,1,0,0,1};
// 数字引脚2~9依次按数组n3中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n3);
}
delay(500);
// 显示数字4
int n4={0,1,0,0,1,1,0,1};
// 数字引脚2~9依次按数组n4中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n4);
}
delay(500);
// 显示数字5
int n5={1,0,0,0,1,0,0,1};
// 数字引脚2~9依次按数组n5中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n5);
}
delay(500);
// 显示数字6
int n6={1,0,0,0,0,0,0,1};
// 数字引脚2~9依次按数组n6中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n6);
}
delay(500);
// 显示数字7
int n7={0,0,1,1,1,1,0,1};
// 数字引脚2~9依次按数组n7中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n7);
}
delay(500);
// 显示数字8
int n8={0,0,0,0,0,0,0,1};
// 数字引脚2~9依次按数组n8中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n8);
}
delay(500);
// 显示数字9
int n9={0,0,0,0,1,1,0,1};
// 数字引脚2~9依次按数组n9中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n9);
}
delay(500);
}
```
完成下载后,数码管就会循环显示0~9的数字。由于要看懂代码的话,首先需要了解数码管的构造,所以我们这回先说硬件部分。
#### STEP 3: 硬件回顾
数码管
数码管其实就是一个前面介绍的led的组合体,这个组合体包含8个led,所以也称之为八段数码管。说白了就八个灯。哪八段?不用多说了吧!a到g以及小数点DP。其实用法和前面说的LED也是一样的,每段都是一个发光二极管,分别用8个数字口来控制它们的亮灭,通过不同段的显示,就能组成0~9的数字。比如,我们让b,a,f,e,d,c亮起的话,就能显示一个数字“0”了。
下图是个引脚说明图,不陌生了吧!在前面硬件连接的时候,已经看到过一次了。
这里,b --> a --> f --> g --> e --> d --> c --> DP分别连接到Arduino数字引脚2~9。
数码管一共有10个引脚。a~DP 这8个引脚接到数字口,那还有两个引脚呢?这是公共端,LED只有一端是不能被点亮的。我们在RGB灯那章讲到过共阴共阳的问题,数码管也存在共阴共阳问题。所谓共阳就是公共端接+5V,共阴则是公共端接GND。
数码管的共阴共阳在使用上有什么区别
共阳数码管,它们公共端接5V,那在代码中,控制另一端的数字引脚为LOW,这样才能让数码管点亮。如果是共阴数码管,公共端接GND,在代码中中,控制另一端数字引脚为HIGH,才让数码管点亮。
所以,共阴共阳只是在代码上要稍作修改。我们这里选用的是共阳数码管。硬件有了了解,我们来看看软件部分。
#### STEP 4: 代码回顾
硬件部分我们已经说过,数码管需要接到8个数字引脚,所以在一开始,需要定义8个数字引脚作为输出。这次我们用一个for循环来完成这8个数字引脚的设置。数码管b,a,f,g,e,d,c,DP分别和Arduino数字引脚2~9对应。
```
for(int pin = 2 ; pin <= 9 ; pin++){
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}
```
从引脚2开始,一直循环到引脚9,都设为OUTPUT模式,初始化为HIGH。前面说过,共阳的话,设置HIGH,不被点亮,所以开始先不点亮数码管。(当然,你一个一个引脚分开设置输出模式也是不会错的,只是会让代码显得很冗长。)
好了,到了主函数,要分别显示0~9的数字。是不是觉得代码大部分都是相似的。所以,我们只要看明白如何显示数字0,那整段代码就都迎刃而解了。
`int n0={0,0,0,1,0,0,0,1};`
这里我们要引入一个数组的概念。数组是一个变量的集合,可以通过索引号来找到数组中的元素。在我们的程序中,声明了一个int型的数组。并取名为n0。之后用8个数值来初始化这个数组。那如何获得数组中的元素呢?你只需要简单的指出这个元素的索引号。数组是从0开始索引的,这意味着数组中的第一个元素的索引号为0而不是1,因此数组中的8个元素的索引号是0~7。在这里元素4,对应索引号为3(n0),值为1。元素8(索引号7,n0)的值为1。
声明中n0的方括号中的8代表有8个元素。
定义完数组后,进入又一个for循环。
```
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n0);
}
```
这个for循环是给2~9引脚写入状态值,也就是HIGH还是LOW,digitalWrite函数中写入HIGH的另一种形式就是写入“1”,LOW则可以写为“0”。我们通过数组索引的方式给2~9引脚赋值。
比如当pin=2,代入n0中,对应为n0,n0意思是获得数组的第一个元素,为0。完成了引脚2置低(LOW)。我们前面说了,共阳的数码管,置低(LOW)的话,是被点亮,所以,b端被点亮了。循环到pin=3,a段被点亮,。循环到pin=4,f段被点亮,依次类推……。
整个循环过程如下:
pin=2 --> n0 =0 --> digitalWrite(2,0) --> b段点亮
pin=3 --> n0 =0 --> digitalWrite(3,0) --> a段点亮
pin=4 --> n0 =0 --> digitalWrite(4,0) --> f 段点亮
pin=5 --> n0 =1 --> digitalWrite(5,1) --> g段不点亮
pin=6 --> n0 =0 --> digitalWrite(6,0) --> e段点亮
pin=7 --> n0 =0 --> digitalWrite(7,0) --> d段点亮
pin=8 --> n0 =0 --> digitalWrite(8,0) --> c段点亮
pin=9 --> n0 =1 --> digitalWrite(9,1) --> DP段不点亮
这样就完成了显示数字“0”了。同样用数组的方法显示数字1~9。自己动手画一下,哪几段亮,哪几段不亮就一目了然了。 kaka 发表于 2015-11-30 15:41
多位数码管的时候,你的IO口就不够用了,建议使用专用数码管驱动芯片
你好要控制LED矩阵用什么ic芯片比较好,我现在使用的是74hc595只需要3个端口就可以控制8位,还有更好的解决方案吗? flugkatze 发表于 2015-1-7 22:19
做了一段可以用遥控器控制8段数码管的程序:
谢谢,自己感觉很实用 厉害了,新手来顶一顶帖子,加油学习~ 做了一段可以用遥控器控制8段数码管的程序:
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
boolean stopplay = LOW;
int playNum=0;
boolean onoff = LOW;
void setup(){
for(int pin = 2 ; pin <= 9 ; pin++){ // 设置数字引脚2~9为输出模式
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
Serial.begin(9600);
irrecv.enableIRIn();
}
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
if (onoff == HIGH)
{
switch (results.value) {
case 0xFD30CF:{
// 显示数字0
displayNum(0);
playNum=0;}
break;
case 0xFD08F7:{
// 显示数字1
displayNum(1);
playNum=1;}
break;
case 0xFD8877:{
// 显示数字2
displayNum(2);
playNum=2;}
break;
case 0xFD48B7:{
// 显示数字3
displayNum(3);
playNum=3;}
break;
case 0xFD28D7:{
// 显示数字4
displayNum(4);
playNum=4;}
break;
case 0xFDA857:{
// 显示数字5
displayNum(5);
playNum=5;}
break;
case 0xFD6897:{
// 显示数字6
displayNum(6);
playNum=6;}
break;
case 0xFD18E7:{
// 显示数字7
displayNum(7);
playNum=7;}
break;
case 0xFD9867:{
// 显示数字8
displayNum(8);
playNum=8;}
break;
case 0xFD58A7:{
// 显示数字9
displayNum(9);
playNum=9;}
break;
case 0xFD00FF:{
// off
for(int pin = 2 ; pin <= 9 ; pin++){ // 设置数字引脚2~9为输出模式
digitalWrite(pin, HIGH);
}
onoff = LOW;}
break;
case 0xFDA05F:
{
irrecv.resume();
stopplay = LOW;
for (int i = playNum ; i <= 9; i++){
displayNum(i);
delay(500);
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
if(results.value == 0xFDA05F){
stopplay = HIGH;
playNum = i;
break; //stop play
}
irrecv.resume();
}
}
while(!stopplay){
// 显示数字
for (int i = 0 ; i <= 9; i++){
displayNum(i);
delay(500);
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
if(results.value == 0xFDA05F){
stopplay = HIGH;
playNum = i;
break; //stop play
}
irrecv.resume();
}
}
}
}
break;
case 0xFD50AF:
{
if (++playNum > 9)
playNum=0;
displayNum(playNum);
}
break;
case 0xFD10EF:
{
if (--playNum < 0)
playNum=9;
displayNum(playNum);
}
break;
case 0xFD609F:
{
playNum += 2;
if (playNum > 9)
playNum -= 10;
displayNum(playNum);
}
break;
case 0xFD20DF:
{
playNum -= 2;
if (playNum < 0)
playNum += 10;
displayNum(playNum);
}
break;
default:
break;
}
irrecv.resume();
}
else {
if (results.value == 0xFD00FF){
// on
displayNum(playNum);
onoff = HIGH;}
irrecv.resume();
}
}
}
void displayNum(int num){
int n0={0,0,0,1,0,0,0,1};
int n1={0,1,1,1,1,1,0,1};
int n2={0,0,1,0,0,0,1,1};
int n3={0,0,1,0,1,0,0,1};
int n4={0,1,0,0,1,1,0,1};
int n5={1,0,0,0,1,0,0,1};
int n6={1,0,0,0,0,0,0,1};
int n7={0,0,1,1,1,1,0,1};
int n8={0,0,0,0,0,0,0,1};
int n9={0,0,0,0,1,1,0,1};
int *n /*= (int *) malloc(sizeof(int)*8)*/;
switch (num) {
case 0:
n=n0;
break;
case 1:
n=n1;
break;
case 2:
n=n2;
break;
case 3:
n=n3;
break;
case 4:
n=n4;
break;
case 5:
n=n5;
break;
case 6:
n=n6;
break;
case 7:
n=n7;
break;
case 8:
n=n8;
break;
case 9:
n=n9;
break;
default:
// statements
break;
}
//数字引脚2~9依次按数组n0中的数据显示
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n);
}
//free(n);
}
红色开关可以控制数码管显示/关闭;
显示状态下按数字键控制数码管显示相应数字;
按下播放键使数码管循环显示0~9,再按一下停止循环;
还有上下键和快进/后退键也有相应的用途;
有一个比较奇怪的地方是:
我如果把displayNum函数中,下面这两段注释的代码打开,就会导致显示失灵。
int *n /*= (int *) malloc(sizeof(int)*8)*/;
//free(n);
有哪位大侠能帮忙解释解释? flugkatze 发表于 2015-1-7 22:19
做了一段可以用遥控器控制8段数码管的程序:
没太看明白你的代码,我之前写过一段也是红外遥控的,给你参考下吧。
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
int currentNumber = 0;
long codes= // this array is used to store infrared codes
{
0xFD30CF,0xFD08F7, // 0 ,1
0xFD8877,0xFD48B7, // 2 ,3
0xFD28D7,0xFDA857, // 4 ,5
0xFD6897,0xFD18E7, // 6 ,7
0xFD9867,0xFD58A7, // 8 ,9
0xFD20DF,0xFD609F, // advance, move back
};
int number = //the array is used to store the number 0~9
{
{0,0,0,1,0,0,0,1},//0
{0,1,1,1,1,1,0,1},//1
{0,0,1,0,0,0,1,1},//2
{0,0,1,0,1,0,0,1},//3
{0,1,0,0,1,1,0,1},//4
{1,0,0,0,1,0,0,1},//5
{1,0,0,0,0,0,0,1},//6
{0,0,1,1,1,1,0,1},//7
{0,0,0,0,0,0,0,1},//8
{0,0,0,0,1,1,0,1} //9
};
void numberShow(int i) { //this function is used to display numbers
for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin, number);
}
}
void setup(){
Serial.begin(9600);
irrecv.enableIRIn();
for(int pin = 2 ; pin <= 9 ; pin++){
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}
}
void loop() {
if (irrecv.decode(&results)) {
for(int i = 0; i <= 11; i++){
if(results.value == codes&& i <= 9){
numberShow(i);// display number 0~9 on the digital control
currentNumber = i;
Serial.println(i);
break;
}
else if(results.value == codes&& currentNumber != 0){
currentNumber--;
numberShow(currentNumber);
Serial.println(currentNumber);
break;
}
//
else if(results.value == codes&& currentNumber != 9){
currentNumber++;
numberShow(currentNumber);
Serial.println(currentNumber);
break;
}
}
Serial.println(results.value, HEX);
irrecv.resume();
}
}
Jane 发表于 2015-1-8 10:26
没太看明白你的代码,我之前写过一段也是红外遥控的,给你参考下吧。
OK,多谢! 为什么复制上面的代码会弹出“应用程序错误的窗口” 多位数码管的时候,你的IO口就不够用了,建议使用专用数码管驱动芯片 本帖最后由 powera 于 2015-12-12 15:07 编辑
请问Jane,除了那八个接数字口之外,另外两个针脚,从图上来看,都是接到5V上
为什么,不是一个接5V,一个接地吗?
哦,明白了,数码管那另外两个针脚是 公共端
共阳,则两个公共端都接5V
共阴,则两个公共端都接GND。:)
数码管这样接是不是好点吧?23456789分别对应abcdefgDP 好好好!!!! 你好,我对数组不是太理解
int number = //the array is used to store the number 0~9
{
{0,0,0,1,0,0,0,1},//0
{0,1,1,1,1,1,0,1},//1
{0,0,1,0,0,0,1,1},//2
{0,0,1,0,1,0,0,1},//3
{0,1,0,0,1,1,0,1},//4
{1,0,0,0,1,0,0,1},//5
{1,0,0,0,0,0,0,1},//6
{0,0,1,1,1,1,0,1},//7
{0,0,0,0,0,0,0,1},//8
{0,0,0,0,1,1,0,1} //9
};
怎么知道0~9对应的数组就是这几个呢? 此段loop里的函数是什么意思,为什么没有for(int pin = 2; pin <= 9 ; pin++){
digitalWrite(pin,n); //数字引脚2~9依次按数组n0中的数据显示
这一段?
void loop() {
if (irrecv.decode(&results)) {
for(int i = 0; i <= 11; i++){
if(results.value == codes&& i <= 9){
numberShow(i);// display number 0~9 on the digital control
currentNumber = i;
Serial.println(i);
break;
}
else if(results.value == codes&& currentNumber != 0){
currentNumber--;
numberShow(currentNumber);
Serial.println(currentNumber);
break;
}
//
else if(results.value == codes&& currentNumber != 9){
currentNumber++;
numberShow(currentNumber);
Serial.println(currentNumber);
break;
}
}
李明哲 发表于 2017-3-28 09:28
你好,我对数组不是太理解
int number = //the array is used to store the number 0~9 ...
数字0的组成 = (b,a,f,g,e,d,c,DP)赋值为(0,0,0,1,0,0,0,1) 你看这样是不是能理解
李明哲 发表于 2017-3-28 09:31
此段loop里的函数是什么意思,为什么没有for(int pin = 2; pin
你可以试下效果如何~ Jane 发表于 2017-3-30 00:29
数字0的组成 = (b,a,f,g,e,d,c,DP)赋值为(0,0,0,1,0,0,0,1) 你看这样是不是能理解
...
懂了,是0代表LOW,所以显示0的代表亮了。谢谢楼主啦~:handshake Arduino:1.8.3 (Windows 7), 开发板:"Arduino/Genuino Uno"
C:\Users\andyyt\Desktop\ygf\arduino-1.8.3\libraries\RobotIRremote\src\IRremoteTools.cpp:5:16: error: 'TKD2' was not declared in this scope
int RECV_PIN = TKD2; // the pin the IR receiver is connected to
^
exit status 1
为开发板 Arduino/Genuino Uno 编译时出错。
在文件 -> 首选项开启
“编译过程中显示详细输出”选项
这份报告会包含更多信息。
请问为什么头脚两个+需要连接到5V?发现一端连接到5V就能正常工作了 Jane 发表于 2015-1-8 10:26
没太看明白你的代码,我之前写过一段也是红外遥控的,给你参考下吧。
有没有电路图啊 就红外控制8的
受教了 完习了!完习了!完习了! ee
页:
[1]
2