看代码之前呢 还是要看一下电路图,个人感觉,单片机的学习不能脱离电路图以及编程的练习,可能开始只是照猫画虎,仿照别人的代码,但我相信,经常仿照别人的代码并自己独立敲出来别人的代码,量边会引起质变,到时候会有厚积薄发的感觉的。好了,咱们一起看代码吧
#include <STC12C5A60S2.H>
#define SET 1000
sbit ENLED = P1^1;
unsigned int code wei[]={0x00,0x01,0x02,0x03,0x04,0x05};
unsigned int code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//数码管的显示
unsigned int k,tflag;
unsigned int key_scan(); //矩阵键盘扫描函数
void display(unsigned int a,unsigned int b); //数码管显示函数
void delay_us(unsigned int n);
void delay_ms(unsigned int n);
void main()//主函数
{
TMOD=0x01; //使用定时器0的模式1:即16位计数器,优点:可装载的值较多,计时可较长
TH0=(65535-SET)/256; //缺点:不是自动重装,所以在中断服务程序中还需装入初值
TL0=(65535-SET)%256;
ET0=1;//打开定时器0的中断
TR0=1;//打开定时器0
EA=1; //打开总中断
while(1)
{
display(5,k-1);
}
}
void timer_0() interrupt 1
{
TH0=(65535-SET)/256;
TL0=(65535-SET)%256;
tflag++;
if(tflag == 1) // 3ms*x 数码管扫描
{
ENLED = 1;
key_scan();
tflag = 0;
}
}
void display(unsigned int a,unsigned int b)
{
P2 = wei[a];
P0 = duan;
ENLED = 0;
}
unsigned int key_scan() //矩阵按键扫描程序
{
P2=0x7f;
if(P2 != 0x7f)
{
P0=0xff;
delay_ms(5);
if(P2 != 0x7f)
{
switch(P2)
{
case 0x77:k=4;break;
case 0x7b:k=3;break;
case 0x7d:k=2;break;
case 0x7e:k=1;break;
}
while(P2 != 0x7f);
}
}
P2=0xbf;
if(P2 != 0xbf)
{
P0=0xff;
delay_ms(5);
if(P2 != 0xbf)
{
switch(P2)
{
case 0xb7:k=8;break;
case 0xbb:k=7;break;
case 0xbd:k=6;break;
case 0xbe:k=5;break;
}
while(P2 != 0xbf);
}
}
P2=0xdf;
if(P2 != 0xdf)
{
P0=0xff;
delay_ms(5);
if(P2!=0xdf)
{
switch(P2)
{
case 0xd7:k=12;break;
case 0xdb:k=11;break;
case 0xdd:k=10;break;
case 0xde:k=9;break;
}
while(P2 != 0xdf);
}
}
P2=0xef;
if(P2 != 0xef)
{
P0=0xff;
delay_ms(5);
if(P2 != 0xef)
{
switch(P2)
{
case 0xe7:k=16;break;
case 0xeb:k=15;break;
case 0xed:k=14;break;
case 0xee:k=13;break;
}
while(P2 != 0xef);
}
}
}
void delay_us(unsigned int n)//延时函数
{
extern void _nop_(void);
register unsigned char i = n, j = (n>>8);
_nop_(); _nop_(); _nop_();
if ((--i) | j)
{
do
{
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
if (0xFF == (i--)) j--; else {_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();};
} while (i | j);
}
}
void delay_ms(unsigned int n) //延时函数
{
while (n--) delay_us(1000);
}
这段函数是援引自第41届学长的,并不是本人编写完成,我发表一下我对这段函数的理解,这提供了一个很好的思路(对于IO口冲突的问题),矩阵按键就是通过行线和列线来确定哪个按键被按下的。
在按键的扫描中断时,每次让矩阵按键的1个KOUT口输出低电平,其他三个输出高电平,判断当前所有的p20,p21,p22,p23的状态,下次中断时再让下一个KOUT输出低电平,其他三个输出高电平,再次判断所有的p20~p23的状态,通过快速的中断不停地循环进行判断,就可以最终确定那个按键被按下了,改用了1ms中断,按照板子的按键按下即可,数码管显示值=按键值-1;请大家认真分析一下这段例程,会对你的单片机学习有帮助的。还请各位高手斧正。
|