赞
踩
上方
的为共阴极连接
下方
的为共阳极连接
把 “8”分为 8个段,分别为
“A、B、C、D、E、F、G、DP(顺时针)"
,正好对应寄存器的 8个字节
。
引脚定义
若其为共阴极连接
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
号引脚
共阳极
则反过来即可
。
拥有 12 个引脚
上方
为共阴极
,下方
为共阳极
所有的
A段连在一起
、B段连在一起
…
点亮
A、C、D、E、F、G段
因为是
共阴极
,设阴极接地
,为低电平
(数字 0)。要点亮数字 6
,则要改变另一端
为高电平
。其段码
:1011 1110;
若是共阳极
,则阳极接Vcc
,为高电平
(数字 1)。段码
与共阴极相反
。
点亮
第三块数码管的 B、C段
因为要使
第三块数码管亮 数字1
,又因为是共阴极
,所以可把12、9、6号引脚
都接高电平
,8号引脚
接低电平
。【 这样接的话,第一、二、四块数码管不会亮,二极管不导通
嘛!】再使得
第三块数码管的 B、C段
的7,4号引脚
都接高电平
【二极管可以导通
,就可点亮 第三块数码管的 A、B段,即点亮数字 1】
但是这种数码管只能 **几个数码管同时显示相同是数字。**要同时显示不同数字的,需要用到 动态数码管显示。
图中是一个
共阴极
的数码管。所以下方要配阳码
图中
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) | 转化完后的结果 | Y0 | Y1 | Y2 | Y3 | Y4 | Y5 | Y6 | Y7 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
电平 | 0 | 0 | 0 | 0×4+0×2+0×1=0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
电平 | 0 | 0 | 1 | 0×4+0×2+1×1=1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
电平 | 1 | 0 | 1 | 1×4+0×2+1×1=5 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
注意:Y0接的是 LED1、Y1接的是 LED2…以此类推。
要让
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 但是有
叠影
所以,需要加:
因为它是 这样的一个过程:
位选 段选 位选 段选 位选 段选
会串位所以 我们要添加
清零
硬件设备简单,但会
消耗大量单片机CPU时间
。
内部自带显存、扫描电路,单片机
只需告诉它显示什么即可
。TM1640 两根线可以控制 16个IO口
所有的函数均放在main.c里
,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路
。
把
各个模块
的代码放在不同的.c 文件
里,在.h文件
里提供外部可调用函数的声明
。对于其它.c文件,当我们想使用其中的代码时,只需要#include"XXX.h:"
即可。使用模块化编程可极大的提高代码的可阅读性、可维护性和可移植性
等。
C语言的
预编译以#开头
,作用是在真正的编译开始之前,对代码做一些处理(预编译)。此外还有 #ifdef, #if, #else, #elif, #undef等
LCD1602液晶屏
作为调试窗口
,提供类似printf函数
的功能,可实时观察
单片机内部数据的变换情况,便于调试和演示;函数的作用
和使用方法
就可以很容易的使用LCD1602。#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) { } }
结果如下:
#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);
}
}
结果如下:
- 在键盘中按键数量较多时,为了
减少I/O口的占用
,通常将按键排列成矩阵形式;- 采用
逐行或逐列
的“扫描”,就可以读出任何位置
按键的状态。
数码管扫描
(输出扫描)
原理
:显示第1位→显示第2位→显示第3位→…,然后快速循环这个过程, 最终实现所有数码管同时显示的效果。矩阵键盘扫描
(输入扫描)
原理
:读取第1行(列)→读取第2行(列) →读取第3行(列),→…,然后快速循环这个过程,最终实现所有按键同时检测的效果。- 以上两种扫描方式的
共性
:节省I/O口。
- 以扫描第 2行为例,扫描前,上面的P17、15、14 都给1,P16 给0
- 当按下的按键 S5的时候,给了 P13为 0;按下 S6的,给了 P12 为0…以此类推。
扫描的行 | P17 | P16 | P15 | P14 | 按下X键,相应电平的变化 | P13 | P12 | P11 | P10 | |
---|---|---|---|---|---|---|---|---|---|---|
电平 | 第2行 | 1 | 0 | 1 | 1 | S5 | 0 | 1(不变) | 1(不变) | 1(不变) |
电平 | 第3行 | 1 | 1 | 0 | 1 | S11 | 1(不变) | 1(不变) | 0 | 1(不变) |
- 以扫描第 2列为例,扫描前,下面的P13、11、10 都给1,P12 给0
- 当按下的按键 S5的时候,给了 P16为 0;按下 S9的,给了 P15 为0…以此类推。
扫描的列 | P13 | P12 | P11 | P10 | 按下X键,相应电平的变化 | P17 | P16 | P15 | P14 | |
---|---|---|---|---|---|---|---|---|---|---|
电平 | 第1列 | 0 | 1 | 1 | 1 | S5 | 1(不变) | 0 | 1(不变) | 1(不变) |
电平 | 第3列 | 1 | 1 | 0 | 1 | S11 | 1(不变) | 1(不变) | 0 | 1(不变) |
实现代码如下:
#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; }
#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); } } }
#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); //更新显示 } } }
加快写代码的效率
“|”在哪里,双击添加后的 光标就会出现在哪里
关键不是那些已封装好的函数,而是要理清楚代码的逻辑结构。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。