1、基础知识
电阻:102 = 10*10^2=1k ,252=25*10^2 =2500
LED接的电阻是限流电阻,VCC电压是5V,电流可能过大而烧毁LED灯,所以需要接一个限流电阻。
单片机是使用TTL电平,高5低0,所以控制单片机的P2口输出低电平就能点亮LED灯。
点亮一个灯:P2 = 0xFE;//1111 1110 二进制转16进制。
#include<reg51.h> //只能操作整个P2 P2 = 0xFE;
#include<regx51.h> //可以直接操作位寄存器 P2_0 = 0;
void main() //点亮一个
{
P2 = 0xFE; // 1111 1110
P2 = 0x55; // 0101 0101
}
//--------------------------------------------------
void main() // 闪烁
{
while(1)
{
P2 = 0xFE;
delay(500);
P2 = 0xFF;
}
}
//--------------------------------------------------
void main() //流水灯
{
while(1)
{
P2 = 0xFE;
delay(500);
P2 = 0xFD;
delay(500);
P2 = 0xFB;
// ...
}
}
//---------------------------------------------------
void main(){ //独立按键
//按键是P3端口,依次3_1、3_0、3_2、3_3
while(1)
{
if(P3_1 == 0)
{
P2_0=0;
}
else
{
P2_0=1;
}
}
}
//---------------------------------------------------
//按键抖动
void main(){
while(1)
{
if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
P2_0=~P2_0; //按位取反
}
}
}
//---------------------------------------------------
//按键控制LED二进制
void main(){
unsigned char LEDNum=0;
while(1)
{
if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
//1111 1111
//P2++; // 0000 0000
//P2_0=~P2_0; //按位取反 1111 1111
LEDNum++;
P2=~LEDNum;
}
}
}
//---------------------------------------------------
//独立按键控制LED移位
0000 0001 0x01<<0
0000 0010 0x01<<1
unsigned char LEDNum;
void main()
{
P2=~0x01; //初始化
while(1)
{
if(P3_1==0){ // 左移
Delay(20);
while(P3_1==0);
Delay(20);
LEDNum++;
if(LEDNum>8){
LEDNum=0;
P2=~(0x01<<LEDNum);
}
if(P3_0==0){ //右移
Delay(20);
while(P3_0==0);
Delay(20);
if(LEDNum==0)
LEDNum=7;
else
LEDNUm--;
P2=~(0x01<<LEDNum);
}
}
}
2、数码管与芯片连接
2.1 为什么使用锁存器
二极管正常工作时需要5mA以上的电流,若数码管引脚和芯片引脚直接相连,芯片的I/O口无法输出这么大的电流,对于共阴极的数码管,可以在阳极处接上拉电阻,对于共阳极的数码管,可以在阴极处接下拉电阻,但是也使得“位选”需做另外的处理。
引入锁存器,利用其输出电流大的特点,有效的解决了LED工作电流问题,而且还可以利用锁存器进行“位选”、“段选”。
2.2、锁存器的电路连接
单片机的芯片引脚P00—>P07分别接U1锁存器的D0——>D7,单片机的芯片引脚P00—>P07分别接U2锁存器的D0——>D7,也就是说U1、U2俩锁存器都与P0相连,所以在数码管工作状态下,俩个锁存器不能同时处于打开状态,即俩个锁存器的LE不能同时为高电平。锁存器U1的输出接数码管的LED阳极,锁存器U2的输出接数码管的WE,控制“数码管选择”。
73HC138接74HC245再接数码管
2.3、静态数码管代码
#include<REGX52.H>
void main()
{
P2_4=1;
P2_3=0;
P2_2=0;
P0=0x7D; //1011 1110
while(1)
{
}
}
//创建子函数(位选,段选):switch-case 视频代码
#include <REGX52.H>
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Nixie(unsigned char Location,Number)
{
switch(Location)//74Hc138译码器三个输入端,低电平有效
{
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;
}
P2 = NixieTable[Number];
}
void main(){
Niexie(5,3);
while(1){
}
}
2.4、动态数码管代码
在静态数码管代码的基础上,显示多个数码管并且加延时。
消影现象(位选-段选,位选-段选,位选-段选),需要在子函数中清零(P0=0x00)
数码管驱动方式:直接扫描、专用驱动扫描
#include <REGX52.H>
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Nixie(unsigned char Location,Number)
{
switch(Location)//74Hc138译码器三个输入端,低电平有效
{
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;
}
P2 = NixieTable[Number];
Delay(1); //消影
P2=0x00;//消影
}
void main(){
while(1){
Niexie(1,1);
Delay(20);
Niexie(2,2);
Delay(20);
Niexie(3,3);
Delay(20);
}
}