用8266学习单片机-6-八段数码管显示数字?时间?金钱?闹钟?从一位八段数码管到四位-网络同步时钟
八段数码管原理
单个数码管本质就是LED的排列组合,你也可以自己用八个LED组合试一试,分为共阴和共阳两种,共阳的3、8引脚就是接正极,共阴接地(电阻别忘了)
比如让g、dp两个led不亮,其余的都亮,看起来是啥??就是0嘛,其它的类推嘛
上图下方第三个管脚为dp
多位数码管原理是一样的,都是那八个管脚,只是多了几个选通管脚:1、2、3、4,指定哪个亮啥就亮啥,以人眼无法识别的高频率变换的时候,你以为每一个都以不同的状态同时亮,其实不是的。
数码管其实可以直接使用Arduino上别人写好的库函数,想直接看这个直接跳到最后即可
万用表测试数码管好坏
一位数码管
万用表调节到二极管挡位,如果是共阴管,就把黑表笔COM端接数码管3(或8)管脚,用红表笔一个个去测试a~dp,都亮就是好的,有一个不亮就是那个小LED烧坏了。。
四位数码管
万用表调节到二极管挡位,如果是共阳管,就把红表笔接1~4其中一个,假设先测试第1个一位数码管,然后用黑表笔测试a ~dp,都亮了说明第1个一位数码管是好的,然后测试第2个一位数码管,就把 红表笔接在2上,然后黑表笔测试a ~ dp管脚,依次类推
经过测试:我发现我的第1、4个一位数码管存在“坏道”!!!
管脚分配
管脚图说明
由于8266只有12个GPIO,但是有的GPIO无法使用,
GPIO0引脚在开发板运行中需要一直保持高电平状态。
GPIO2引脚 在NodeMCU开发板启动时是不能连接低电平的
GPIO6~GPIO 11被用于连接开发板的闪存,
GPIO15引脚在开发板运行中一直保持低电平状态。因此请不要使用GPIO15引脚来读取开关状态或进行I²C通讯。
于是我打算这样分配
int a= D10;
int b= D9;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
int dp= D0;
但是发现D9不知名原因维持在0.3V。。。于是取消dp,改成这样
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
代码
点亮全部管脚
/*
* 四位共阳数码管测试,
* 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
* 0等效为LOW,1等效为HIGH,经测试有效
*/
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
}
void loop() {
digitalWrite(a,0);
digitalWrite(b,0);
digitalWrite(c,0);
digitalWrite(d,0);
digitalWrite(e,0);
digitalWrite(f,0);
digitalWrite(g,0);
}
加个鸡蛋,点亮0
/*
* 四位共阳数码管测试,
* 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
* 0等效为LOW,1等效为HIGH,经测试有效
*/
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
}
void loop() {
digitalWrite(a,0);
digitalWrite(b,0);
digitalWrite(c,0);
digitalWrite(d,0);
digitalWrite(e,0);
digitalWrite(f,0);
digitalWrite(g,1);
}
加鸡蛋不过瘾??全家福来一套吧
/*
提前将0~9对应的管脚序列存到数组中,然后一个循环输出
最后结果就是0~9之间循环变换
*/
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
int light[10][8] = {
//a b c d e f g dp
{0, 0, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 1, 0, 0, 1},
{0, 1, 0, 0, 1, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 1, 0, 0, 1},
};
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
}
void loop() {
for(int i = 0; i<10;i++){
digitalWrite(a,light[i][0]);
digitalWrite(b,light[i][1]);
digitalWrite(c,light[i][2]);
digitalWrite(d,light[i][3]);
digitalWrite(e,light[i][4]);
digitalWrite(f,light[i][5]);
digitalWrite(g,light[i][6]);
delay(300);
}
}
封装一下函数
/*
* 四位共阳数码管测试,
* 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
*/
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
int delayTime = 500; //延迟时间ms
int light[10][8] = {
//a b c d e f g dp
{0, 0, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 1, 0, 0, 1},
{0, 1, 0, 0, 1, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 1, 0, 0, 1},
};
void lightControl(int i){
digitalWrite(a,light[i][0]);
digitalWrite(b,light[i][1]);
digitalWrite(c,light[i][2]);
digitalWrite(d,light[i][3]);
digitalWrite(e,light[i][4]);
digitalWrite(f,light[i][5]);
digitalWrite(g,light[i][6]);
delay(delayTime); //不延时也是可以的,但是变化比较快
}
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
}
void loop() {
for(int i = 0; i<10;i++){
lightControl(i);
}
}
/*其中,loop还可以这样写
void loop() {
static int i = 0; //没有static就一直是0
lightControl(i);
i++;
i = i %9;
}
*/
二位数码管不同步
上面的演示都是只能所有管子显示同一个数字,那我想显示52、13、14怎么办????
其实思路很简单,先让一个管子显示5,然后让另一个管子同时显示2,单独为每个管子引9根线,两个管子就18根,那4个不就是36???我8266没有那么多孔啊。。。。。
在这种思路上稍微改进一丢丢,只增加一根控制线来实现,一次只亮一个管子,假设两只管子A、B,让A先显示5,然后关掉A,打开B,显示2,你说这不是同时显示啊!!!但是如果提高频率呢???人眼都是傻瓜,我亮灭的频率到达阈值之后,人眼就无法分辨其实A、B是一个亮的同时另一个是灭的(有没有感觉自己的眼睛好蠢)
先控制一位数码管的亮灭
这里只在上面的程序修改了一丢丢,加了一个控制引脚,效果就是A管只有在偶数才亮!!
/*
* 四位共阳数码管测试,
* 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
* 用D4控制一位数码管是否显示
*/
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
int delayTime = 500; //延迟时间ms
int led1 = D4; //GPIO2
int light[10][8] = {
//a b c d e f g dp
{0, 0, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 1, 0, 0, 1},
{0, 1, 0, 0, 1, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 1, 0, 0, 1},
};
void lightControl(int i){
//i只能取0~9
digitalWrite(a,light[i][0]);
digitalWrite(b,light[i][1]);
digitalWrite(c,light[i][2]);
digitalWrite(d,light[i][3]);
digitalWrite(e,light[i][4]);
digitalWrite(f,light[i][5]);
digitalWrite(g,light[i][6]);
delay(delayTime); //不延时也是可以的,但是变化比较快
}
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
pinMode(led1,OUTPUT);
}
void loop() {
static int i = 0; //没有static就一直是0
if(i%2==0)
{
digitalWrite(led1,1);
}
else
{
digitalWrite(led1,0);
}
lightControl(i);
i++;
i = i %9;
}
两位数码管~爱你
这里又增加了一根控制线,用来控制B管的亮灭
这里A、B就可以显示不同的数字了
/*
* 四位共阳数码管测试,
* 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
*/
int a= D10;
int b= D0;
int c= D7;
int d= D6;
int e= D5;
int f= D2;
int g= D1;
int delayTime = 500; //延迟时间ms
int led1 = D4; //GPIO2
int led2 = D9; //GPIO3,最低点位还是0.3V,不过测试后发现能控制LED
int light[10][8] = {
//a b c d e f g dp
{0, 0, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 1, 0, 0, 1},
{0, 1, 0, 0, 1, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 1, 0, 0, 1},
};
void lightControl(int i){
//i只能取0~9
digitalWrite(a,light[i][0]);
digitalWrite(b,light[i][1]);
digitalWrite(c,light[i][2]);
digitalWrite(d,light[i][3]);
digitalWrite(e,light[i][4]);
digitalWrite(f,light[i][5]);
digitalWrite(g,light[i][6]);
delay(delayTime); //不延时也是可以的,但是变化比较快
}
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
}
//loop中切勿delay。。否则你会发现你傻了,这灯一闪一闪的
void loop() {
static int i = 0; //没有static就一直是0
if(i%2==0)
{ //A管显示5,B管灭
digitalWrite(led1,1);
digitalWrite(led2,0);
lightControl(5);
}
else
{//B管显示2,A管灭
digitalWrite(led1,0);
digitalWrite(led2,1);
lightControl(2);
}
i++;
i = i %2;
}
你说这看起来很傻逼卡顿啊,我这不是为了演示才调大delayTime嘛,你把它调小一点试试!!!200?100?50??究竟多小最好??根据不正常理论显示,最佳的时间应该是刚好不让你察觉到闪烁,我则是设为10,慢慢调试呗
改进
你说我不想自己写0~9对应的引脚01分配,那怎么办??也不想每次都设置那么多东西,这个世界上大部分问题都有人遇到过了,百度之后你会发现肯定有大佬写好了库函数,调用一下就行,见参考2怎么下SevSeg
库
这个库可以应用到1~4个数码管上,其实你也可以把上面的两位数码管的简单封装一下
参考
- 单管 https://blog.csdn.net/TonyIOT/article/details/82490703
- 库 https://blog.csdn.net/TonyIOT/article/details/82490703
- https://blog.csdn.net/weixin_43031092/article/details/106771413
- 网络对时 https://blog.csdn.net/Cloud_1234_5678/article/details/84346087