当前位置:   article > 正文

【单片机】【学习日志】51单片机学习日志[Day2、2022.1.10]_数码管1引脚怎么接

数码管1引脚怎么接

第一部分:数码管

一、基础知识

1、数码管引脚定义(单个数码管)

上方的为 共阴极连接

下方的为 共阳极连接

把 “8”分为 8个段,分别为“A、B、C、D、E、F、G、DP(顺时针)",正好对应寄存器的 8个字节

引脚定义

1.1引脚类型

若其为共阴极连接

  • A、B、C、D、E、F、G、DP 段 的阴极均接 3、8号引脚

  • A段 阳极接 7号引脚

  • B段 阳极接 6号引脚

  • C段 阳极接 4号引脚

  • D段 阳极接 2号引脚

  • E段 阳极接 1号引脚

  • F段 阳极接 9号引脚

  • G段 阳极接 10号引脚

  • DP段 阳极接 5号引脚
    共阳极反过来即可

2、数码管引脚定义(多个数码管)(也称:静态数码管显示

拥有 12 个引脚

上方共阴极下方共阳极

  • 所有的 A段 连在一起、B段连在一起

二、操作分析

1、点亮数字 6 (单个数码管)

点亮 A、C、D、E、F、G段

因为是共阴极,设阴极接地,为低电平(数字 0)。要点亮 数字 6,则要改变另一端高电平。其段码:1011 1110;
若是 共阳极,则阳极接Vcc,为高电平(数字 1)。段码共阴极相反

2、点亮数字 1(多个数码管)(也称:静态数码管显示)

点亮第三块数码管的 B、C段

因为要使第三块数码管亮 数字1 ,又因为是共阴极,所以可把 12、9、6号引脚都接高电平8号引脚低电平。【 这样接的话,第一、二、四块数码管不会亮,二极管不导通嘛!】

再使得第三块数码管的 B、C段7,4号引脚都接高电平【二极管可以导通,就可点亮 第三块数码管的 A、B段,即点亮数字 1】

但是这种数码管只能 **几个数码管同时显示相同是数字。**要同时显示不同数字的,需要用到 动态数码管显示。

3、我的数据手册中的电路图

图中是一个共阴极的数码管。所以下方要配 阳码

图中 LED8、LED7、LED6、LED5、LED4、LED3、LED2、LED1 是接在 138译码器上的输出端的。

此时,我们需要让其中一个端口输入为 0 (低电平),其余的均为 1(高电平)。

  • 138译码器可以完成上面的功能。它也可以用 左边的 3个输入端控制 右边的 8个输出端。【8条线减少到了3条线,可以减少单片机的 IO口】
  • 左下角的三个引脚,称为“使能端”。(相当于一种电源开关,若是电平有效则其会工作,否则不工作。)
    • 6号引脚接Vcc(高电平),4、5号引脚接 0(低电平),其即可工作。

把 C、B、A 高低位排序后,转化为 10进制,转化完的数 就对应着输出

可以把各个位权写出来,如下:

C(4)B(2)A(1)转化完后的结果Y0Y1Y2Y3Y4Y5Y6Y7
电平0000×4+0×2+0×1=001111111
电平0010×4+0×2+1×1=110111111
电平1011×4+0×2+1×1=511111011

注意:Y0接的是 LED1、Y1接的是 LED2…以此类推。

三、实际操作

1、静态数码管显示

要让 LED6 显示 6

点亮A、C、D、E、F、G段,阳码(从下往上读)为 0111 1101 (十六进制为 7D

#include <REGX52.H>

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0X7D,
0X07,0X7F,0X6F,0X77,0X7C,0X39,0X5E,0X79,0X71,0X00}; 

void Nixie(unsigned char Location,Number)
{
	switch(Location)
	{/* 原理图中的位权和LED位置是相反的 */
		case 1:P2_4=1; P2_3=1;P2_2=1;break;//位权为 4×1+1×2+1×1 = 7;
		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=0x7D;段码:0111 1101 点亮 A、B、C、D、E、F、G段(即点亮数字 6)
	P0=NixieTable[Number];
	
}

void main()
{	
	Nixie(2,3);//在第 2个位置显示 数字3
	while(1)
	{	
		
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

2、动态数码管显示

虽然它有显示 1 2 3 但是有叠影

所以,需要加:

消影

因为它是 这样的一个过程:位选 段选 位选 段选 位选 段选 会串位

所以 我们要添加 清零

结果为:

四、数码管的驱动方式

1、单片机直接扫描

硬件设备简单,但会消耗大量单片机CPU时间

2、专用驱动芯片

内部自带显存、扫描电路,单片机只需告诉它显示什么即可

TM1640 两根线可以控制 16个IO口

第二部分:模块化编程

一、基础知识

1、传统方式编程

所有的函数均放在main.c里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路

2、模块化编程

各个模块的代码放在不同的.c 文件里,在.h文件里提供外部可调用函数的声明。对于其它.c文件,当我们想使用其中的代码时,只需要 #include"XXX.h:"即可。使用模块化编程可极大的提高代码的可阅读性、可维护性和可移植性等。

2.1注意事项

  • .c文件:函数、变量的定义;
  • .h文件:可被外部调用的函数、变量的声明;
  • 任何自定义的变量、函数在调用前必须有定义或声明(同一个.c);
  • 使用到的自定义函数的 .c文件必须添加到工程树中参与编译;
  • 使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义)。

3、C_预编译

C语言的预编译以#开头,作用是在真正的编译开始之前,对代码做一些处理(预编译)。

此外还有 #ifdef, #if, #else, #elif, #undef等

第三部分:LCD1602调试工具

一、基本介绍

  • 使用LCD1602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示;
  • 本课中的LCD1602代码属于模块化的代码,我们只需要知道所提供函数的作用使用方法就可以很容易的使用LCD1602。

1、函数尝试

#include <REGX52.H>
#include "LCD1602.h"

void main()
{
	LCD_Init();
	LCD_ShowChar(1,1,'A');
	LCD_ShowString(1,3,"Hello");
	LCD_ShowNum(1,9,123,3);
	LCD_ShowSignedNum(1,13,-66,2);
	LCD_ShowHexNum(2,1,0xA8,2);
	LCD_ShowBinNum(2,4,0xAA,8);
	while(1)
	{

	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

结果如下:

2、秒表

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"

int Result=0;
void main()
{
	LCD_Init();
	while(1)
	{
		Result++;
		Delay(1000);
		LCD_ShowNum(1,1,Result,3);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

结果如下:

二、矩阵键盘_介绍

  • 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式;
  • 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。

1、扫描的概念

  • 数码管扫描(输出扫描)
    原理:显示第1位→显示第2位→显示第3位→…,然后快速循环这个过程, 最终实现所有数码管同时显示的效果。
  • 矩阵键盘扫描(输入扫描)
    原理:读取第1行(列)→读取第2行(列) →读取第3行(列),→…,然后快速循环这个过程,最终实现所有按键同时检测的效果。
  • 以上两种扫描方式的共性:节省I/O口。

1.1 逐行扫描(会与其它的IO口 有冲突)

  • 以扫描第 2行为例,扫描前,上面的P17、15、14 都给1,P16 给0
  • 当按下的按键 S5的时候,给了 P13为 0;按下 S6的,给了 P12 为0…以此类推。
扫描的行P17P16P15P14按下X键,相应电平的变化P13P12P11P10
电平第2行1011S501(不变)1(不变)1(不变)
电平第3行1101S111(不变)1(不变)01(不变)

1.2 逐列扫描

  • 以扫描第 2列为例,扫描前,下面的P13、11、10 都给1,P12 给0
  • 当按下的按键 S5的时候,给了 P16为 0;按下 S9的,给了 P15 为0…以此类推。
扫描的列P13P12P11P10按下X键,相应电平的变化P17P16P15P14
电平第1列0111S51(不变)01(不变)1(不变)
电平第3列1101S111(不变)1(不变)01(不变)

实现代码如下:

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  矩阵键盘读取按键键码(按列)
  * @param 	无
  * @retval KeyNum 按下的按键键码值
  如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回键码,没有按键按下时,返回 0
  */
  
unsigned char MatrixKey()
{
	unsigned char KeyNumber=0;
	
	P1=0xFF;
	P1_3=0; //第1列置0
	if(P1_7 ==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
	if(P1_6 ==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
	if(P1_5 ==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
	if(P1_4 ==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
	
	P1=0xFF;
	P1_2=0; //第2列置0
	if(P1_7 ==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
	if(P1_6 ==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
	if(P1_5 ==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
	if(P1_4 ==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
	
	P1=0xFF;
	P1_1=0; //第3列置0
	if(P1_7 ==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
	if(P1_6 ==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
	if(P1_5 ==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
	if(P1_4 ==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
	
	P1=0xFF;
	P1_0=0; //第4列置0
	if(P1_7 ==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
	if(P1_6 ==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
	if(P1_5 ==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
	if(P1_4 ==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
	
	return KeyNumber;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"

unsigned char KeyNum;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Hello,World");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum)
		{
			LCD_ShowNum(2,1,KeyNum,2);
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

三、矩阵键盘电子密码锁

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"

unsigned char KeyNum;
unsigned int Password,count;
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Password!");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum)
		{
			if(KeyNum<=10) //如果S1~S10按键被按下,输入密码
			{
				if(count<4)//如果输入次数小于4
				{
					Password*=10;		 //密码左移一位
					Password+=KeyNum%10; //把S10 换为输入 0 //获取一位密码
					count++;	//计次加1
				}	
			}
			LCD_ShowNum(2,1,Password,4);	//更新显示输入的密码
		}
		if(KeyNum==11)	//如果S11按键被按下,确认输入的密码
		{
			if(Password==2345) //如果密码正确,显示OK
			{
				LCD_ShowString(1,14,"OK ");
				Password=0;		//密码清零
				count=0; 		//计次清零
				LCD_ShowNum(2,1,Password,4);	//更新显示
			}
			else	//如果密码不正确,显示ERR
			{
				LCD_ShowString(1,14,"ERR");
				Password=0;		//密码清零
				count=0; 		//计次清零
				LCD_ShowNum(2,1,Password,4);	//更新显示
			}
		}
		if(KeyNum==12)//按下S12,取消输入
		{
			Password=0;		//密码清零
			count=0; 		//计次清零
			LCD_ShowNum(2,1,Password,4);	//更新显示
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

编译器小技巧

添加快捷方式

加快写代码的效率

“|”在哪里,双击添加后的 光标就会出现在哪里

心得:

关键不是那些已封装好的函数,而是要理清楚代码的逻辑结构。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号