当前位置: 首页 > news >正文

【51单片机】3. 数码管大师

1. 单个数码管基本定义

数码管连接方式:

分为共阳极和共阴极连接,如下图所示,上面为共阴极连接,下面为共阳极连接。

在这里插入图片描述

数码管引脚定义:

右侧从1开始逆时针到10,依次为1,2,3,…,8,9,10。上面数码管连接方式图中的标号就对应到具体的引脚。数码管定义的ABCDEFG&DP如左图所示,结合这些LED灯的编号和引脚编号可以得出连线图。

在这里插入图片描述

连线方式如下图所示:

在这里插入图片描述

2. 多个数码管定义

连接方式如下图所示,一共有12个引脚(上下的连接方式只是共阴极连接和共阳极连接的区别)。

则12,9,8,6控制具体亮哪一个LED灯,而其他控制显示的具体数字

在这里插入图片描述

每一个独立数码管显示(下方)都连接到了相同的接口。如果我们上方将12,9,8,6全部点亮(即所有数码管都显示数字),则每个数码管显示的都是具体ABCDEFG&DP连接的单片机的8个端口对应的结果。

这样的好处是,原本需要4*8=32个引脚控制的多个数码管,只用12个引脚就简单替代了

3. 动态数码管模块电路图分析

动态数码管模块电路图如下:

在这里插入图片描述

图中的COM通常接地或电源负极,这里可以看作这些LED管是共阴极连接,所以具体abcdefg&dp点亮哪一个,就要给哪一个置1。

0-9对应16进制如下(P07→P00):

int LEDNum[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

下边的74HC245是一个双向数据缓冲器。使用这个是因为:

  • 高电平点亮灯与低电平点亮灯比起来,低电平会更亮一些(需要具体自己动手实验看)

  • 这里的双向数据缓冲器,就是拿单片机的微弱电流作为输入信号,做信号控制,控制右侧B0~B7这部分的结果

  • B0~B7右侧由VCC直流供电,电源更够一些,保证数码管的亮度

  • 综上,双向数据缓冲器就是用来增强驱动能力的

上图中LED连接到74H138译码器如下图所示:

在这里插入图片描述

译码器连接了VCC,所以在输出的LED中,需要通过置0,和VCC行成电压差点亮具体的LED(即给低电压点灯)。138是低电平译码!

通过CBA(P24,P23,P22)三个口来控制输出,具体如下:

  • C B A Output

  • 0 0 0 0(右4)

  • 0 0 1 1(右3)

  • 0 1 0 2(右2)

  • 0 1 1 3(右1)

  • 1 0 0 4(左4)

  • 1 0 1 5(左3)

  • 1 1 0 6(左2)

  • 1 1 1 7(左1)

好处就是仅需单片机3个接口控制8个灯具体亮哪个

还需要注意的是,无论是控制哪个单片机亮、还是控制显示什么数字,例如给P0端口输入,输入的顺序是从P07-P00,而译码器也是从P24-P22输入来控制对应的结果

4. 静态输入位置和数字

代码如下:

#include <REGX52.H>
#include <INTRINS.H>void Delay500ms()        //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}int LEDNum[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};void LEDShow(unsigned int LEDLocation,Number)
{switch(LEDLocation){case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;}P0 = LEDNum[Number];
}int main(void)
{while (1){// 检测所有位置显示是否正确LEDShow(1,8);Delay500ms();LEDShow(2,8);Delay500ms();LEDShow(3,8);Delay500ms();LEDShow(4,8);Delay500ms();LEDShow(5,8);Delay500ms();LEDShow(6,8);Delay500ms();LEDShow(7,8);Delay500ms();LEDShow(8,8);Delay500ms();// 检测所有数字显示是否正确LEDShow(3,0);Delay500ms();LEDShow(3,1);Delay500ms();LEDShow(3,2);Delay500ms();LEDShow(3,3);Delay500ms();LEDShow(3,4);Delay500ms();LEDShow(3,5);Delay500ms();LEDShow(3,6);Delay500ms();LEDShow(3,7);Delay500ms();LEDShow(3,8);Delay500ms();LEDShow(3,9);Delay500ms();}
}

给LEDShow函数传入具体显示的LED位置(板子上从左至右是第1-8个位置)以及要显示的具体数字,就能够得到对应的结果。

以上的代码有点长,简单展示在第5位显示8的结果如下:

在这里插入图片描述

5. 动态数码管显示

小节的要求是在多个位置上显示不同的数字。

动态数码管显示实际上是轮流点亮数码管(一个时刻内只有一个数码管是亮的),利用人眼的视觉暂留现象(余晖效应),看起来是所有数码管在同时显示。

基于第四小节的结果,我们可以设计本小节的代码如下(第一版):

#include <REGX52.H>
#include <INTRINS.H>void Delay(unsigned int ms)        //@11.0592MHz
{unsigned char i, j;while (ms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);ms--;}
}int LEDNum[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};void LEDShow(unsigned int LEDLocation,Number)
{switch(LEDLocation){case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;}P0 = LEDNum[Number];
}int main(void)
{while (1){LEDShow(1,2);LEDShow(2,0);LEDShow(3,0);LEDShow(4,1);LEDShow(5,0);LEDShow(6,6);LEDShow(7,0);LEDShow(8,6);}
}

结果如下:

在这里插入图片描述

看起来很花,我认为是闪烁过快没有延时导致的,于是我在LEDShow函数后面加了一个延时1ms,对应函数修改如下:

void LEDShow(unsigned int LEDLocation,Number)
{switch(LEDLocation){case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;}P0 = LEDNum[Number];Delay(1);
}

效果如下:

在这里插入图片描述

上面的现象减轻了一些,但依然存在,这是因为数码管需要消影。数码管的显示过程实际上是:

位选→段选→位选→段选→位选→段选→位选→段选......

但在段选和位选中间就会出现问题,导致把上一个段选的结果带入到下一个位选中,从而导致重影现象,所以在每一个位选→段选过后将数码管置0。Delay仍然需要保留,因为去掉Delay的话会什么都不显示,因为单片机的执行速度很快,我们要让数字留下来,就要保留Delay

修改对应函数如下:

void LEDShow(unsigned int LEDLocation,Number)
{switch(LEDLocation){case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;}P0 = LEDNum[Number];Delay(1);P0 = 0x00;
}

最终效果如下:

在这里插入图片描述

完整代码:

#include <REGX52.H>
#include <INTRINS.H>void Delay(unsigned int ms)        //@11.0592MHz
{unsigned char i, j;while (ms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);ms--;}
}int LEDNum[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};void LEDShow(unsigned int LEDLocation,Number)
{switch(LEDLocation){case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;}P0 = LEDNum[Number];Delay(1);P0 = 0x00;
}int main(void)
{while (1){LEDShow(1,2);LEDShow(2,0);LEDShow(3,0);LEDShow(4,1);LEDShow(5,0);LEDShow(6,6);LEDShow(7,0);LEDShow(8,6);}
}

相关文章:

  • 【CUDA 】核函数性能分析工具
  • PLC入门【2】PLC的接线
  • 系统模块与功能设计框架
  • 【Java学习笔记】System类
  • Linux下的进程调度机制
  • 深入理解 Java 的反射、注解与动态代理
  • 2025新高考二卷选择题第一题题解
  • LangChain4j 1.x 核心源码剖析-基础篇
  • 【项目实训项目博客】用户使用手册
  • Secs/Gem第十二讲(基于secs4net项目的ChatGpt介绍)
  • 【第四十八周】HippoRAG 2 复现与分析(二):索引阶段代码分析
  • 嵌入式学习笔记 - freeRTOS为什么中断中不能使用互斥量
  • 使用自定义模板的方式批量切割图片。
  • 从零开始编写Mcp Server,发布上线,超简单极速入门
  • Amazon RDS on AWS Outposts:解锁本地化云数据库的混合云新体验
  • 循环神经网络(RNN):从理论到翻译
  • 标准代码项目开发流程学习指南
  • leetcode Top100 238. 除自身以外数组的乘积|数组系列
  • 【Ragflow】27.RagflowPlus(v0.4.1):小版本迭代,问题修复与功能优化
  • 高保真组件库:单选复选
  • 西宁网站建设多少钱/云和数据培训机构怎么样
  • 网站建设的功能需求分析策划书/30条新闻摘抄
  • 官渡网站设计制作/昆明seo网站管理
  • bootstrap微网站模板下载/百度搜索量查询
  • 吉安市网站建设/免费个人网站源码
  • 太原住房与城乡建设厅网站/外链seo推广