STC89C52RC是STC公司生產(chǎn)的一種低功耗、高性能CMOS8位微控制器,具有8K字節(jié)系統(tǒng)可編程Flash存儲器。STC89C52使用經(jīng)典的MCS-51內(nèi)核,但是做了很多的改進(jìn)使得芯片具有傳統(tǒng)51單片機(jī)不具備的功能。在單芯片上,擁有靈巧的8 位CPU 和在系統(tǒng)可編程Flash,使得STC89C52為眾多嵌入式控制應(yīng)用系統(tǒng)提供高靈活、超有效的解決方案。
stc52單片機(jī)鍵盤原理圖
說明:
1. 獨立鍵盤部分
S2~S5為4個獨立鍵盤, 與單片機(jī)的P3.4~P3.7分別相連
2. 矩陣鍵盤部分
S6~S21為16個矩陣鍵盤,8條線分別與單片機(jī)的P3口相連, 其中矩陣鍵盤的4行分別與單片機(jī)的P3.0~P3.3相連,矩陣鍵盤的4列分別與單片機(jī)的P3.4~P3.7相連。
程序設(shè)計詳解
程序功能:
用數(shù)碼管的前兩位顯示一個十進(jìn)制數(shù),變化范圍為00-59,開始時顯示00,每按下S2鍵一次,數(shù)值加1;每按下S3鍵一次,數(shù)值減1;每按下S4鍵一次,數(shù)值歸零;按下S5鍵一次,利用定時器功能使數(shù)值開始每秒加1,再次按下S5鍵,數(shù)值停止自動加1,保持原數(shù)。
程序源碼:
#include
#define uchar unsigned char
#define uint unsigned int
sbit key1 = P3 ^ 4;
sbit key2 = P3 ^ 5;
sbit key3 = P3 ^ 6;
sbit key4 = P3 ^ 7;
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void init();
void keyscan();
void display(uchar);
void delayms(uint);
uchar t0, num;
void main()
{
init();
while (1)
{
keyscan();
display(num);
}
}
void init()
{
TMOD = 0x01;
TH0 = (65536 - 45872) / 256;
TL0 = (65536 - 45872) % 256;
EA = 1;
ET0 = 1;
}
void keyscan()
{
if (key1 == 0)
{
delayms(10);
if (key1 == 0)
{
if (num == 60)
num = 0;
num++;
while (!key1)
display(num);
}
}
if (key2 == 0)
{
delayms(10);
if (key2 == 0)
{
if (num == 0)
num = 60;
num--;
while (!key2)
display(num);
}
}
if (key3 == 0)
{
delayms(10);
if (key3 == 0)
{
num = 0;
while (!key3)
display(num);
}
}
if (key4 == 0)
{
delayms(10);
if (key4 == 0)
{
TR0 = ~TR0;
while (!key4)
display(num);
}
}
}
void display(uchar numDis)
{
dula = 1;
P0 = table[numDis / 10];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfe;
wela = 0;
delayms(5);
dula = 1;
P0 = table[numDis % 10];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfd;
wela = 0;
delayms(5);
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
void T0_timer() interrupt 1
{
TH0 = (65536 - 45872) / 256;
TL0 = (65536 - 45872) % 256;
t0++;
if (t0 == 20)
{
t0 = 0;
num++;
if (num == 60)
num = 0;
}
}
程序小結(jié):
a. 鍵盤按鍵檢測需要做兩次 (每個鍵盤按鍵用了兩個if)
b. 鍵盤按鍵退出也需要檢測 (每次按鍵退出用了一個while(!key))
c. 這段程序包含按鍵加1,按鍵減1,按鍵歸零,按鍵開始計數(shù),再按停止計數(shù)
2. 按矩陣鍵盤,在數(shù)碼管上顯示0~F,6個數(shù)碼管同時靜態(tài)顯示即可。
程序功能
上電不顯示, 按矩陣鍵盤,在數(shù)碼管上顯示0~F,6個數(shù)碼管同時靜態(tài)顯示即可。
程序源碼
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint);
void display(uchar);
void matrixkeyscan();
void main()
{
dula = 1;
P0 = 0;
dula = 0;
wela = 1;
P0 = 0xc0;
wela = 0;
while (1)
{
matrixkeyscan();
}
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
void display(uchar num)
{
dula = 1;
P0 = table[num];
dula = 0;
}
void matrixkeyscan()
{
uchar temp, key;
P3 = 0xfe;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xee:
key = 0;
break;
case 0xde:
key = 1;
break;
case 0xbe:
key = 2;
break;
case 0x7e:
key = 3;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
display(key);
}
}
P3 = 0xfd;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xed:
key = 4;
break;
case 0xdd:
key = 5;
break;
case 0xbd:
key = 6;
break;
case 0x7d:
key = 7;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
display(key);
}
}
P3 = 0xfb;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xeb:
key = 8;
break;
case 0xdb:
key = 9;
break;
case 0xbb:
key = 10;
break;
case 0x7b:
key = 11;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
display(key);
}
}
P3 = 0xf7;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xe7:
key = 12;
break;
case 0xd7:
key = 13;
break;
case 0xb7:
key = 14;
break;
case 0x77:
key = 15;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
display(key);
}
}
}
程序小結(jié)
a. 先送行線低電平,檢測列線信號
b. 通過延時來消抖
c. 需要檢查釋放
3. 數(shù)碼管前三位顯示一個跑表,從000到999之間以1%秒速度運(yùn)行
程序功能
當(dāng)按下一個獨立鍵盤時跑表停止,松開手后跑表繼續(xù)運(yùn)行。用定時器設(shè)計表。
程序源碼
#include
#define uint unsigned int
#define uchar unsigned char
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
sbit s2 = P3 ^ 4;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0
};
uchar flag, t0, bai, shi, ge;
uint shu;
void init();
void display(uchar aa, uchar bb, uchar cc);
void delayms(uint);
void main()
{
init();
while (1)
{
display(bai, shi, ge);
if (s2 == 0)
{
delayms(10);
if (s2 == 0)
{
TR0 = 0;
while (!s2)
display(bai, shi, ge);
TR0 = 1;
}
}
}
}
void init()
{
TMOD = 0x01;
TH0 = (65536 - 10000) / 256;
TL0 = (65536 - 10000) % 256;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void T0_timer() interrupt 1
{
TH0 = (65536 - 10000) / 256;
TL0 = (65536 - 10000) % 256;
t0++;
if (t0 == 1)
{
t0 = 0;
shu++;
if (shu == 1000)
shu = 0;
bai = shu / 100;
shi = shu % 100 / 10;
ge = shu % 10;
}
}
void display(uchar aa, uchar bb, uchar cc)
{
dula = 1;
P0 = table[aa];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfe;
wela = 0;
delayms(1);
dula = 1;
P0 = table[bb];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfd;
wela = 0;
delayms(1);
dula = 1;
P0 = table[cc];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfb;
wela = 0;
delayms(1);
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
程序小結(jié)
a. 松開檢測 while (!s2)
b. 1%秒速度運(yùn)行: 選擇定時基數(shù)為1000(即10ms), 定時倍數(shù)為1,相乘為10ms
說明: 由于間隔時間太短,所以這里出現(xiàn)的問題是低位數(shù)據(jù)顯示看不清楚,可以選用定時倍數(shù)為10 (但定時數(shù)變成了100ms, 可能與題意不符)
4. 數(shù)碼管前三位顯示一個跑表,從000到999之間以1%秒速度運(yùn)行
程序功能
當(dāng)按下第一個獨立鍵盤時跑表停止,松開手后跑表繼續(xù)運(yùn)行。
當(dāng)按下第二個獨立鍵盤時計時停止,
當(dāng)按下第三個獨立鍵盤時計時開始,
當(dāng)按下第三個獨立鍵盤時計數(shù)值清零從頭開始
程序源碼
#include
#define uint unsigned int
#define uchar unsigned char
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
sbit s2 = P3 ^ 4;
sbit s3 = P3 ^ 5;
sbit s4 = P3 ^ 6;
sbit s5 = P3 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0
};
uchar flag, t0;
uint shu;
void init();
void display(uint num);
void delayms(uint);
void keyscan();
void main()
{
init();
while (1)
{
display(shu);
keyscan();
}
}
void init()
{
TMOD = 0x01;
TH0 = (65536 - 10000) / 256;
TL0 = (65536 - 10000) % 256;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void keyscan()
{
if (s2 == 0)
{
delayms(10);
if (s2 == 0)
{
TR0 = 0;
while (!s2)
display(shu);
TR0 = 1;
}
}
if (s3 == 0)
{
delayms(10);
if (s3 == 0)
{
TR0 = 0;
while (!s3)
display(shu);
}
}
if (s4 == 0)
{
delayms(10);
if (s4 == 0)
{
TR0 = 1;
while (!s4)
display(shu);
}
}
if (s5 == 0)
{
delayms(10);
if (s5 == 0)
{
shu = 0;
while (!s5)
display(shu);
}
}
}
void T0_timer() interrupt 1
{
TH0 = (65536 - 10000) / 256;
TL0 = (65536 - 10000) % 256;
t0++;
if (t0 == 1)
{
t0 = 0;
shu++;
if (shu == 1000)
shu = 0;
}
}
void display(uint num)
{
dula = 1;
P0 = table[num / 100];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfe;
wela = 0;
delayms(1);
dula = 1;
P0 = table[num % 100 / 10];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfd;
wela = 0;
delayms(1);
dula = 1;
P0 = table[num % 100 % 10];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfb;
wela = 0;
delayms(1);
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
程序小結(jié)
1. 按鍵退出檢測時需要加上display(shu), 否則數(shù)碼管顯示前兩位為空白
2. 按鍵退出檢測與執(zhí)行動作的順序問題
1) 如果要求一按鍵馬上執(zhí)行動作, 應(yīng)該時先執(zhí)行動作,再做按鍵退出檢測
即如:
shu = 0;
while (!s5)
display(shu);
2) 如果要求按鍵退出后再執(zhí)行動作, 應(yīng)該時先檢查按鍵退出,再執(zhí)行動作
即如:
while (!s5)
display(shu);
shu = 0;
5. 按下16個矩陣鍵盤,依次在前三個數(shù)碼管上顯示1~16的平方
程序功能
按下16個矩陣鍵盤,依次在前三個數(shù)碼管上顯示1~16的平方,即按下第一個顯示1,按下第二個顯示4,…按下第16個顯示16*16 (256)
程序源碼
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint);
void display(uint);
void matrixkeyscan();
void main()
{
while (1)
{
matrixkeyscan();
}
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
void display(uint num)
{
dula = 1;
P0 = table[num / 100];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfe;
wela = 0;
delayms(1);
dula = 1;
P0 = table[num % 100 / 10];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfd;
wela = 0;
delayms(1);
dula = 1;
P0 = table[num % 100 % 10];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfb;
wela = 0;
delayms(1);
}
void matrixkeyscan()
{
uchar temp, key;
P3 = 0xfe;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xee:
key = 1;
break;
case 0xde:
key = 2;
break;
case 0xbe:
key = 3;
break;
case 0x7e:
key = 4;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
}
}
P3 = 0xfd;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xed:
key = 5;
break;
case 0xdd:
key = 6;
break;
case 0xbd:
key = 7;
break;
case 0x7d:
key = 8;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
}
}
P3 = 0xfb;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xeb:
key = 9;
break;
case 0xdb:
key = 10;
break;
case 0xbb:
key = 11;
break;
case 0x7b:
key = 12;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
}
}
P3 = 0xf7;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = P3;
switch(temp)
{
case 0xe7:
key = 13;
break;
case 0xd7:
key = 14;
break;
case 0xb7:
key = 15;
break;
case 0x77:
key = 16;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
}
}
display(key * key);
}
程序小結(jié)
1. display(key * key)不能馬上放到每一個按鍵退出檢測后,如果那樣做,數(shù)碼管上只會顯示最后一位數(shù)字(即個位)
換句話說,
程序不能這樣:
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
display(key*key);
而是應(yīng)該放到程序最后結(jié)束處
-
單片機(jī)
+關(guān)注
關(guān)注
6030文章
44489瀏覽量
631968 -
STC52
+關(guān)注
關(guān)注
0文章
2瀏覽量
2978
發(fā)布評論請先 登錄
相關(guān)推薦
評論