单片机c语言

#include <reg52.h>
#define uchar unsigned char // 定义用uchar表示
#define uint unsigned int
sbit BEEP = P3^7; // 位。定义BEEP表示P3。7口

uchar code DSY_CODE[]= //定义数组。
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00
};
uchar Pre_KeyNO = 16,KeyNO = 16;

void DelayMS(uint ms) //1MS 延时程序
{
uchar t;
while(ms--)
{
for(t=0;t<120;t++);
}
}

void Keys_Scan() //键盘扫描程序
{
uchar Tmp;
P1 = 0x0f; //p1口付初始值
DelayMS(1);
Tmp = P1 ^ 0x0f; //tmp= p1与0x0f的异或结果。
switch(Tmp) //判断tmp的值,根据tmp值不同处理
{
case 1: KeyNO = 0; break;
case 2: KeyNO = 1; break;
case 4: KeyNO = 2; break;
case 8: KeyNO = 3; break;
default: KeyNO = 16;
}
P1 = 0xf0;
DelayMS(1);
Tmp = P1 >> 4 ^ 0x0f; //tmp=P1当前值右移四位后和0x0f异或的结果。建议这样写 Tmp =(( P1 >> 4) ^ 0x0f);
switch(Tmp)
{
case 1: KeyNO += 0; break;
case 2: KeyNO += 4; break;
case 4: KeyNO += 8; break;
case 8: KeyNO += 12;
}
}

void Beep() //蜂鸣器发出声音 周期为2毫秒 高电平1秒低电平1秒
{
uchar i;
for(i=0;i<100;i++)
{
DelayMS(1);
BEEP = ~BEEP;
}
BEEP = 1;
}

void main() //主函数
{
P0 = 0x00; //p0口付初值
while(1)
{
P1 = 0xf0;
if(P1 != 0xf0) //当p1不等于0xf0的时候执行键盘扫描
Keys_Scan();
if(Pre_KeyNO != KeyNO)
{
P0 = ~DSY_CODE[KeyNO]; //p0口等于 DSY_CODE[KeyNO]值的取反
Beep();
Pre_KeyNO = KeyNO;
}
DelayMS(100);
}
}
各位朋友,键盘扫描程序,能将备注再详细一点吗,讲一下为什么,表面我也看的懂,并且希望朋友回答的时候认真点,谢谢,

你好:
对于标准的51来说,io口在作为输入时需先对其写1,这在4*4键盘中应用比较灵活。下面把原来的哪些肤浅的注释都去掉了,把认为对理解比较重要的部分重新写了一遍,请从main开始看起。

void Keys_Scan() //键盘扫描程序
{
uchar Tmp;
P1 = 0x0f; //低四位赋值1作为输入(51准双向Io口的特点),高四位用于输出全0。用于列扫描。判断被按下按键属于哪一列

DelayMS(1);
Tmp = P1 ^ 0x0f; //这里关键是异或的作用,任何位与0异或值不变,1异或取反。当有按键按下时,低四位中必有一列读都0,低四位原来为零的位与1异或后变为1,假设低四位读到1101,则与0x0f低四位1111异或后得到0010,表示第2列有按键按下。

switch(Tmp) //判断读到的列标,并将列标存入KeyNO
{
case 1: KeyNO = 0; break; //00000001 第1列有按键按下
case 2: KeyNO = 1; break; //00000010 第2列有按键按下
case 4: KeyNO = 2; break; //00000100 第3列有按键按下
case 8: KeyNO = 3; break; //00001000 第4列有按键按下
default: KeyNO = 16;
}
P1 = 0xf0; //同理,将高四位作为输入,第四位输出全0,用于行扫描,判断被按下的键属于哪一行

DelayMS(1);

Tmp = P1 >> 4 ^ 0x0f; //高四位读到的值移到第四位再异或,数值便于case处理。原理同上面列扫描

switch(Tmp)
{
case 1: KeyNO += 0; break; //若为第1行,则列标即为键值
case 2: KeyNO += 4; break; //若为第2行,则列标+4为键值
case 4: KeyNO += 8; break; //若为第3行,则列标+8为键值
case 8: KeyNO += 12; //若为第4行,则列标+12为键值
}
}

void Beep()
{
uchar i;
for(i=0;i<100;i++)
{
DelayMS(1);
BEEP = ~BEEP;
}
BEEP = 1;
}

void main()
{
P0 = 0x00;
while(1)
{
P1 = 0xf0; //p1高四位作为输入,低四位输出,实际硬件接线应该是高四位与第四位相连
if(P1 != 0xf0) //读到P1 != 0xf0,即有按键按下,高四位中读到0
Keys_Scan(); //若有键按下,则扫描
if(Pre_KeyNO != KeyNO) //这里的作用是判断是否有新的按键按下 Pre_KeyNO != KeyNO,来排除一直按下某个键的情况Pre_KeyNO = KeyNO

{
P0 = ~DSY_CODE[KeyNO]; //若有新键按下,显示键值,
Beep(); //若有新键按下,吱一声
Pre_KeyNO = KeyNO; //这一句比较重要,把新得到的键值赋给先前键值变量,用以下次循环时前面if语句判断是否有新键按下
}
DelayMS(100);
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-09-05
其实,你应该慢慢的研究这个程序,程序不太难,慢慢深入的了解你将受益匪浅。
第2个回答  2010-09-05
DelayMS(100);
是延迟程序
相似回答