数码管动态显示
所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
详细结合例子说明:
//数码管从0到255循环
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uint time = 9216; //定时的长度 ,触发一次中断大约10ms
uchar num = 0,tmp = 0;
sbit dula=P2^6;
sbit wela=P2^7;
uchar code table[]={ //数码管0到f
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar code tablewe[]={ //第几个数码管
0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
void display(uchar,uchar); //相依的数码管显示数字
void delay(uint z);
void init();
void main(){
init();//初始化子程序
while(1){
if(tmp == 17){
num ++;
tmp = 0 ;
}
display(num / 100 , 0); //第一位显示数字的百位,
display(num % 100 / 10 , 1);//第二位显示十位
display(num % 10 , 2);
/*dula=1;
P0=0x00;
dula=0;
P0=0xff;
wela=1;
P0=tablewe[2];
wela=0;
delay(2);*/ //有时候会出现第三个数码管最亮,就可以加上左边的语句
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void display(uchar num,uchar wei){ //控制第几个数码(wei)显示数字(num)
dula=1;
P0=table[num];
dula=0;
P0=0xff;//没有这条会发现其余三个未点亮的数码管也有显示,主要是在下条语句的一瞬间P0还是等于原来的P0
wela=1;
P0=tablewe[wei];
wela=0;
delay(2);//没有这条延时函数会看不清数码管数字变化
}
void init(){
TMOD=0x01;
TH0=(65536-time)/256;
TL0=(65536-time)%256;
EA=1;
ET0=1;
TR0=1;
}
void timer0() interrupt 1
{
TH0=(65536-time)/256;
TL0=(65536-time)%256;
tmp ++;
}
键盘
独立键盘
P3.4到P3.7
对于P3.4口的s2,一端接地为低电平,另一端接高电平,被按下的时候,
通过线与,在P3.4口表现出低电平。所以只要判断相应的引脚电压是不是低电平就可以判断按键有没有被按下。
不过事实没那么简单,主要是因为下图,按下去的瞬间会发生抖动现象
可以使用硬件或软件的方法处理这种现象,这里主要说明下软件的方法,就是在检测到比如P3.4口为低电压的时候,隔一小段时间再检测一下。
代码如下
//当按下s2的时候发现LED灯亮,松开时候数码管+1
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit d1=P1^0;
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar num;
void delay(uint z){
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main()
{
wela=1; //选择第一个数码管
P0=0xfe;
wela=0;
P3=0xff;
while(1){
if(key1==0) //当检测到为低电压的时候
{
delay(5); //延迟一段时间
if(key1==0){ //再检测
d1=0; //做出相应的处理,这里是点亮第一个LED
num++;
if(num==10)
num=0;
}
while(!key1); //后面三行同理处理释放时候的抖动电压
delay(5);
while(!key1);
}
else
d1=1;
dula=1; //没检测到的话就熄灭LED等并且显示数码管
P0=table[num];
dula=0;
}
}
矩阵键盘
详细参考郭天祥十天学会单片机
这里还是采用郭天祥老师的例子说明:
//按下矩阵键盘1到16个键分别在数码管中显示不同数字
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0};
uchar num,temp,num1;
void delay(uint z){
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
uchar keyscan();
void init(){
num=17;
dula=1;
P0=0;
dula=0;
wela=1;
P0=0xc0;
wela=0;
}
void display(uchar aa);
void main(){
init();
while(1){
display(keyscan());
}
}
void display(uchar aa){ //显示第几个数
dula=1;
P0=table[aa-1];
dula=0;
}
uchar keyscan(){
P3=0xfe; //选择矩阵键盘中的第一行
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0) //第一行有按下就不相等,因为线与使得temp改变
{
delay(5); //软件处理抖动电压
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0) //再次检查
{
temp=P3;
switch(temp) //根据不同的值可以判断出是哪一个
{
case 0xee:num=1;
break;
case 0xde:num=2;
break;
case 0xbe:num=3;
break;
case 0x7e:num=4;
break;
}
while(temp!=0xf0) //松开的时候就等于0xf0了退出循环
{
temp=P3;
temp=temp&0xf0;
}
}
}
//第二三四行同理
P3=0xfd;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:num=5;
break;
case 0xdd:num=6;
break;
case 0xbd:num=7;
break;
case 0x7d:num=8;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
P3=0xfb;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:num=9;
break;
case 0xdb:num=10;
break;
case 0xbb:num=11;
break;
case 0x7b:num=12;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
P3=0xf7;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:num=13;
break;
case 0xd7:num=14;
break;
case 0xb7:num=15;
break;
case 0x77:num=16;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
return num;
}