STC89C52单片机 启动!!!(一)

跑马灯实现

直接上代码

#include<regx52.h>
sbit D1=P2^0;
sbit D2=P2^1;
sbit D3=P2^2;
sbit D4=P2^3;
sbit D5=P2^4;
sbit D6=P2^5;
sbit D7=P2^6;
sbit D8=P2^7;
void delay(int num){while(num--){}
}
void led_running(){//从第1盏灯到第8盏灯依次点亮D1=0;delay(40000);D2=0;delay(40000);D3=0;delay(40000);D4=0;delay(40000);D5=0;delay(40000);D6=0;delay(40000);D7=0;delay(40000);D8=0;delay(40000);//从第1盏灯到第8盏灯依次熄灭D1=1;delay(40000);D2=1;delay(40000);D3=1;delay(40000);D4=1;delay(40000);D5=1;delay(40000);D6=1;delay(40000);D7=1;delay(40000);D8=1;delay(40000);//从第1盏灯到第8盏灯依次点亮D1=0;delay(40000);D2=0;delay(40000);D3=0;delay(40000);D4=0;delay(40000);D5=0;delay(40000);D6=0;delay(40000);D7=0;delay(40000);D8=0;delay(40000);//从第8盏灯到第一盏灯依次熄灭D8=1;delay(40000);D7=1;delay(40000);D6=1;delay(40000);D5=1;delay(40000);D4=1;delay(40000);D3=1;delay(40000);D2=1;delay(40000);D1=1;delay(40000);
}
void main(){while(1){int i=3;while(i--){P2=0x00;delay(40000);P2=0xFF;delay(40000);}led_running();}
}

STC89C52单片机LED结构以及原理

由图中,我们可以看出每个led灯的正极都接高电平,所有的负极都接在端口上,1-8LED分别对应P20-P27引脚,当我们给这些引脚一个低电平的时候二极管就会导通,发光。

两种方式控制LED点亮

P2=0x00;一次性控制8个引脚从而一次性控制8个LED,转化为二进制为0000000,此时8个led均点亮。P2=0xFF;此时8个led均熄灭。格外注意:这里的P是大写。

用sbit来控制每个LED的亮灭。

sbit关键字

在单片机编程中,sbit 是特定于 Keil C 编译器的关键字,用于定义特定位的名称。通过 sbit 关键字,可以将某个特定的位与一个变量相关联,方便编程时对位进行操作。

例如,在 8051 单片机的 Keil C 编程中,可以使用 sbit 来定义位,示例代码如下:

sbit LED = P1^0; // 将 P1 端口的第 0 位与 LED 变量关联

代码

#include <reg51.h>sbit LED1 = P2^0; // 将 P2 端口的第 0 位与 LED 变量关联void main() {LED1 = 1; // 设置 LED 为高电平,相当于 P2.0 = 1;
//此时第一个LED灯就点亮了}

数码管实现

数码管结构图(上面是共阴数码管,下面是共阳数码管)

  1. 共阳数码管: 共阳数码管的基本结构是由多个发光二极管(LED)组成,每个 LED 的阳极连接在一起,而各个 LED 的阴极分别独立控制。在共阳数码管中,当给定阳极一个高电平时,对应的 LED 会被激活,发光显示。因此,通过控制各个阴极的低电平来实现对数码管上不同位置的 LED 的显示和关闭。

  2. 共阴数码管: 共阴数码管的基本结构与共阳数码管类似,也由多个发光二极管(LED)组成,但是每个 LED 的阴极连接在一起,而各个 LED 的阳极分别独立控制。在共阴数码管中,当给定阴极一个低电平时,对应的 LED 会被激活,发光显示。因此,通过控制各个阳极的高电平来实现对数码管上不同位置的 LED 的显示和关闭。

总结:

  •   共阳数码管:阳极共连接,通过控制阴极的低电平来点亮对应的 LED。
  •   共阴数码管:阴极共连接,通过控制阳极的高电平来点亮对应的 LED。

数码管的段码值表

我们可以看到上面的图片中,A-G再加上一个小数点dp正好是8个,对应8个二极管。

这个表定义的是无小数点dot的段码值表

共阴带小数点的段码为:{0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7};

共阳带小数点的断码为:{0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

这篇文章里面有详细断码表:

共阳和共阴数码管详细段码(带图)_共阳极数码管显示0~f对应的段码-CSDN博客

共阴带小数点的可以由共阴不带小数点的段码加0x80

共阳带小数点的可以由共阳不带小数点的段码减0x80

以6为例

注意:a对应的是最低位

a b c d e f g dp(共阴数码管)手动定义二极管阳极,让一个二极管点亮给这个端口赋值1

1 0 1 1 1 1 1 0=0x7D,这里要注意a对应的是最低位所以01111101=0x7D

a b c d e f g dp(共阳数码管)手动定义二极管阴极,让一个二极管点亮给这个端口赋值0

0 1 0 0 0 0 0 1=0x82,这里要注意a对应的是最低位所以10000010=0x82

实现让数码管显示数字4

#include<reg52.h>
unsigned char SMGnodot[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void main(){while(1){P0=SMGnodot[5];}
}

这里我首先有两个疑惑

1.这里明显是要存储数字类型的数据,但是为什么这里使用的是unsigned char字符类型呢?

 在单片机中,char数组中的数据也是以字节(byte)的方式存储的。char类型表示一个字节的数据,即8位(8 bits)。在C语言中,char类型是用来表示字符的,但是它也可以用来存储其他8位的数据。在单片机中内存紧张,为了尽量减少内存消耗,我们选择使用char,并且在这里存储的数字正好是8位,char正好可以满足需求。换句话来说在c语言当中我们char是用来存放字符的,输出char类型变量出来的是字符,但是char在这里完全可以当成一个内存更小的数字存储单元

2.由下面的一张图片,我们可以看到8个引脚要控制8个晶体管,但是现在一个1晶体管就将8个引脚用光掉了,51单片机的共有40个引脚,每一个引脚通常有1位存储空间,用于表示引脚的状态(高电平或低电平)。这让我不得不猜想可能会在短时间内将仅用8个引脚来对8个晶体管状态进行遍历,利用我们的视觉暂留效果来看起来8个晶体管同时亮起来。当然,这只是我目前的猜想,让我们继续学习下去。

单个数码管静态显示(数码管实现遍历0-9)

#include<reg52.h>
unsigned char SMGnodot[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(int num){while(num--){}
}
void main(){unsigned char i;while(1){for(i=0;i<10;i++){P0=SMGnodot[i];delay(40000);}}
}

代码注意:这里不能写成for(unsigned char i=0;i<10;i++),在早期版本的C语言标准中,循环变量的定义只能放在函数的开头,而不能在循环内部进行定义。然而,随着C语言标准的演进,C99标准引入了块作用域规则,允许在循环内部定义循环变量。对于8051单片机编程,因为它使用的是较早的C语言标准,所以循环变量的定义通常放在循环外部,这样可以保证与旧版本C语言兼容。因此,你可以将循环变量i的定义放在main函数的开头,以符合8051单片机编程的惯例。

数码管中的段选和位选

数码管的段选是用来控制每一位数码管的8段的,一位需要8个端口,数码管的位选是控制数码管的这位是否可以显示。

数码管的位选控制的就是每个数码管的共阳端或者共阴端。就是公共端COM对于共阳数码管,当位选信号为高电平时,对应的数码管会被选中并显示;而对于共阴数码管,当位选信号为低电平时,对应的数码管会被选中并显示。对于一组四个共阴数码管,给其中一个的共阴端为低电平,其他三个数码管的共阴端为高电平,此时只有一个数码管被选中来能接受传输过来的数据。这就是动态显示选择其中一个数码管作为当前要显示的数码管的原理。

这里的位的意思可以看图片理解

数码管的两种显示方式(静态显示和动态显示)

静态显示

静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。这种方法的优点是占用CPU时间少,显示便于检测可控制。缺点是硬件电路比较复杂,成本较高。 如果对于一个四位数码管我们采用静态显示方式,仅仅段选加起来就需要32个接口一共需要33个端口,显然不太现实,使用动态显示的话只用12个端口就够了(8+4),所以对于多位数码管,我们常常使用动态显示的方式。

动态显示

看来和我想的一样(狗头)

数码管的动态显示原理是通过快速地切换多个数码管的显示,使人眼产生视觉上的同时显示效果。这种技术通常被称为多路复用显示。

实现数码管动态显示的基本步骤如下:

  1. 设置位选信号:首先选择其中一个数码管作为当前要显示的数码管,通过位选信号(即控制数码管的某一位)来选中该数码管。

  2. 发送段选数据:在选择了要显示的数码管之后,发送对应该数码管要显示的段选数据,包括要显示的数字、字母或其他符号的编码信息。

  3. 等待一小段时间:在当前数码管显示数据的瞬间,需要给予足够的时间让数码管完成显示,这样可以确保人眼能够清晰地看到显示的内容。

  4. 重复上述步骤:然后,迅速切换到下一个数码管,重复上述步骤1~3,直到所有的数码管都完成显示。

通过不断地重复以上步骤,每个数码管都会以很高的频率被选中并显示对应的内容,由于人眼的视觉暂留效应,就会给人一种所有数码管同时显示的错觉。这样就实现了数码管的动态显示效果。

对于上面的解释:【(即控制数码管的某一位)来选中该数码管。】为什么是只能控制某一位呢?按理来说使用12个端口控制的话,虽然不能让这四个数码管同时显示不同内容,但肯定能让这几个数码管同时更新相同的内容,同时接收,同时控制。其实是因为在我们这个单片机上并没有使用12个接口来控制,而是使用了一种其他芯片(74HC138),下面对其介绍。

74HC138

配合我们的动态数码管的结构来看

我们可以看到74HC138模块与图中动态数码管的8个公共端相连,功能

它具有多个输入线(A, B, C)和多个输出线(Y0-Y7),可以根据输入线的状态选择其中一个输出线。

具体来说,74HC138 可以将 3 个输入线的组合转换成 1 个输出线,实现将 8 个输入信号(2^3=8)映射到 1 个输出线上的功能。通过控制输入线的状态,可以选择激活其中一个输出线,从而实现解码器或者多路复用器的功能。

其实就是对应的三位二进制的真值表(原理图中C对应高位

结构图中的左下角功能是上电开关,电路图中已经接好了,表示这个芯片可以直接使用。

74HC245

它和动态数码管是直接相连的,在动态数码管图中的左侧部分,这是一个双向数据缓冲器。直观地理解它的功能就是:原封不动地将左边的数据传输到右边或者将右边的数据传输到左边。就像下面这个图中所示。值得注意的是左上角的接口DIR,对应英语中的direction(方向),作用是决定将右边的数据传输到左边还是将左边的数据传输到右边,DIR如果是高电平,就将左边的数据传输到右边,如果低电平,就将右边的数据传输到左边。

DIR与LE相连(图中黄色的装置,可用跳线棒连接)

采用74HC245这样接的话好处:缓冲器可以提高驱动能力,直接单片机接上数码管的话就相当于这个单片机的电位直接驱动数码管,但是单片机中高电位不会很高,这样驱动能力弱,导致数码管发光暗一点,但是现在有了这个芯片,就相当于是单片机中高电位起到一个控制信号,控制信号可以很微弱,然后接收到信号,这个芯片可以从它本身相连的vcc中汲取能量,这样的话就会使得数码管更亮。

由于单片机的输出端无法提供足够的电流来驱动数码管,可能会导致数码管亮度较低或者亮度不均匀。而使用 74HC245 缓冲器后,单片机的输出信号可以作为控制信号输入到缓冲器中,缓冲器会根据这个控制信号来控制数码管的数据输入输出,同时从自身的 VCC 中获取能量来驱动数码管,从而提高了驱动能力,并且可以改善数码管的发光效果。

多个数码管的动态显示

直接上代码

#include<regx52.h>
sbit A1=P2^2;
sbit B1=P2^3;
sbit C1=P2^4;
unsigned char SMGNOdt[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80};
void delay(int num){while(num--){}
}
void show(unsigned char pos,unsigned char num){switch(pos){case 1:C1=0;B1=0;A1=0;break;case 2:C1=0;B1=0;A1=1;break;case 3:C1=0;B1=1;A1=0;break;case 4:C1=0;B1=1;A1=1;break;case 5:C1=1;B1=0;A1=0;break;case 6:C1=1;B1=0;A1=1;break;case 7:C1=1;B1=1;A1=0;break;case 8:C1=1;B1=1;A1=1;break;}P0=SMGNOdt[num];
}
void main(){while(1){show(8,5);delay(50);show(7,2);delay(50);show(6,0);delay(50);show(5,10);delay(50);show(4,1);delay(50);show(3,3);delay(50);show(2,1);delay(50);show(1,4);delay(50);}
}

这个代码中我主要强调几点: 

1.引脚的顺序赋值问题,让我们再看前面的这张图,这里可以看到74HC138芯片中A对应于P22,C对应于P24,在这款单片机中的P0,P1.P2.P3这四组引脚都是P0^0,P1^0,P2^0,P3^0对应8位二进制数字的最低位,所以看我们代码中这里是依次赋值给C1,B1,A1然后对应让哪个数码管可以接收数据,比如110对应Y6就是让第7个数码管接收数据。

2.注意结合我们的板子电路原理图来看对应顺序,其实也是在强调对应顺序。

可以看到从左到右分是数码管的8-1,并不是我们想的1-8,所以,在我们想显示5201314的时候第一位想显示5,其实是要让LED8显示5,让LED8接收数据。如下所示,所以我们一定要通过板子的原理图看清楚对应关系。

对江协科技老师的代码做一个解释

这里的代码相当于是和我的反过来了他主要是想函数内部反一下,外部我们自己写代码比较顺畅,这样的话我们外面想让第一个数码管显示数字5,就调用函数show(1,5);第1个灯显示了5,实际上还是让LED8显示的5,这样的话虽然方便,但是我觉得没有遵循原理图中的对应关系,看大家爱好喜欢,来选择书写方式。

欢迎大家指正!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/537831.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github主页设置贪吃蛇详细教程

先看最终实现结果&#xff1a; 有条贪吃蛇放在主页还是蛮酷的哈哈哈。接下来我来讲一讲怎么在Github主页添加一条贪吃蛇。 首先要修改自己的Github的主页&#xff0c;我们得有一个特殊的仓库——这个仓库必须与你的Github用户名保持一致&#xff0c;并且需要公开&#xff0c…

Database Connection Pool 数据库连接池-01-概览

拓展阅读 第一节 从零开始手写 mybatis&#xff08;一&#xff09;MVP 版本。 第二节 从零开始手写 mybatis&#xff08;二&#xff09;mybatis interceptor 插件机制详解 第三节 从零开始手写 mybatis&#xff08;三&#xff09;jdbc pool 从零实现数据库连接池 第四节 从…

QT c++ 双精度数拆分和组合 Tool

本文描述QT c的双精度数拆分和合并&#xff0c;即双精度浮点数拆为四个16位无符号整数以及将四个16位无符号整数组合为双精度浮点数。 开发平台&#xff1a;win10QT6.2.4 MSVC2019 64 bit 在本文的最好列出了代码和可执行文件打包下载链接&#xff08;可直接使用&#xff09;…

国创证券|炒股有哪八不碰?

炒股存在以下八不碰&#xff1a; 1、散户多的个股不碰 散户较多&#xff0c;则阐明市场上的散户在不断地买入该股&#xff0c;主力在不断地卖出该股&#xff0c;筹码逐步从主力的手中流入散户的手中&#xff0c;这会引起市场上的投资者惊惧&#xff0c;大量地抛出手中的股票&…

maven打包把所有依赖的jar copy到一个文件夹

在maven项目中&#xff0c;是使用依赖坐标来引入jar包&#xff0c;在引入jar包的时候&#xff0c;maven也会默默的帮助我们导入这个jar包所依赖的jar包。 但是当我们打包项目使用jar包运行的时候&#xff0c;往往会出现缺少jar的情况&#xff1a; 如果我们一个一个添加缺少的…

Android系统 关于ntp的修改(网络时间同步)

一&#xff0c;现象&#xff1a; 1. NTP介绍 NTP&#xff1a;网络时间协议&#xff0c;英文名称&#xff1a;Network Time Protocol&#xff08;NTP&#xff09;是用来使计算机时间同步化的一种协议&#xff0c;它可以使计算机对其服务器或时钟源&#xff08;如石英钟&#x…

input输入框支持明文暗文切换

input输入框支持明文暗文切换 场景与思路实现 场景与思路 我们通常实现密码框的时候会直接使用 input ,设置它的 type 为 password&#xff0c;如果要实现明文和暗文的切换&#xff0c;实际上就是 type“text” 和 type"password"的切换。 实现 样式上我们可以先找…

Igraph入门指南 5

2、graph_from系列&#xff0c;将其他R数据结构转换成图 2-1 邻接矩阵转图&#xff1a;graph_from_adjacency_matrix 可以接受Matrix包创建的稀疏矩阵作为参数 邻接矩阵中行的顺序被保留&#xff0c;并作为图中顶点的顺序。 本函数几个重要的参数&#xff1a; weighted&am…

EPSON X1E000341003100 FA-238A石英晶体谐振器

EPSON X1E000341003100 FA-238A是一款无源晶振&#xff0c;具有特定的频率和尺寸规格。这款晶振的频率为20MHz&#xff0c;尺寸为3.20 x 2.50mm &#xff0c;这使得它非常适合用于小型化设计中。它的温度范围从-40℃到125℃&#xff0c;并且具有20ppm的频率稳定性&#xff0c;这…

软考高级:软件工程单元测试(驱动模块、被测模块、桩模块)概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

FX110网:1月美国零售货币资金环比上升2.61%,嘉盛环比上升1.86%

美国商品期货交易委员会&#xff08;CFTC&#xff09;发布的最新月度报告显示&#xff0c;2024年1月零售货币存款与上月相比上升2.61%。 这份报告涵盖在美国运营的注册零售货币对交易商&#xff08;RFED&#xff09;和经纪自营商。包括嘉信理财&#xff08;CHARLES SCHWAB Futu…

重学SpringBoot3-集成FreeMarker

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成FreeMarker 1. 添加 FreeMarker 依赖2. 配置 FreeMarker 属性&#xff08;可选&#xff09;3. 创建 FreeMarker 模板4. 编写控制器5. 运行应用程序F…