藍橋杯單片機(二) 數碼管與按鍵
1.數碼管

數碼管的動態掃描使用1ms的定時器掃描,放在中斷服務函式中,數碼管顯示很穩定
例子:數碼管后五位顯示12345
#include<stc15f2k60s2.h>
typedef unsigned char uchar;
typedef unsigned int uint;
uchar dsp_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar dsp_show[8]={0xff,0xff,0xff}; //數碼管前三位熄滅,后五位顯示12345
uint number=12345;
void Timer0Init(void) //中斷初始化,1毫秒@11.0592MHz
{
AUXR |= 0x80; //定時器時鐘1T模式
TMOD &= 0xF0; //設定定時器模式
TL0 = 0xCD; //設定定時初值
TH0 = 0xD4; //設定定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0=1; //記得加上這兩句
EA=1;
}
void Timer0_Service() interrupt 1 //中斷入口
{
static uchar bit_com=0;
P0=0; //消影,使所有數碼管熄滅
P2=0xc0;
P2=0;
P0=dsp_show[bit_com]; //段選內容,即要顯示的數字
P2=0xe0; //打開鎖存器控制數碼管段選
P2=0; //關閉鎖存器
P0=1<<bit_com; //位選左移一位
P2=0xc0; //打開鎖存器控制數碼管位選
P2=0;
if(++bit_com==8)
bit_com=0;
}
void main()
{
Timer0Init(); //中斷初始化
dsp_show[3]=dsp_code[number/10000];
dsp_show[4]=dsp_code[number/1000%10];
dsp_show[5]=dsp_code[number/100%10];
dsp_show[6]=dsp_code[number/10%10];
dsp_show[7]=dsp_code[number%10];
while(1)
{
;
}
}
2.按鍵

按鍵部分分為獨立按鍵與矩陣按鍵,跳帽J5接在BTN(button)時即原理圖中23,獨立按鍵生效,接在KBD(keyboard)時即原理圖中12,矩陣按鍵生效,
2.1 獨立按鍵:
跳線帽需要短接J5口的3和2引腳,按鍵能使用的僅有第一列(即上圖中S4、S5、S6、S7),當按鍵按下時,相應的P30-33口輸入為低電平,由此撰寫獨立按鍵掃描函式,
void KEY_1(void)
{
static u8 key_flag = 1;
if(key_flag && (P30 == 0||P31 == 0|| P32 == 0||P33 == 0))
{
key_flag = 0;
if(P30 == 0) //S7
{
}
else if(P31 == 0) //S6
{
}
else if(P32 == 0) //S5
{
}
else if(P33 == 0) //S4
{
}
}
else if(P33 && P32 && P31 && P30) key_flag = 1;
}
例子:將跳帽J5接在BTN,按下S4點亮L4,按下S5點亮L5,按下S6點亮L6,按下S7點亮L7,每次只點亮一個LED
#include<stc15f2k60s2.h>
typedef unsigned char uchar;
typedef unsigned int uint;
uchar cnt,trg;
uchar count_key; //控制按鍵重繪率的變數
void scan_button()
{
uchar readdat=P3^0xff;
trg=readdat&(readdat^cnt); //???
cnt=readdat;
if(trg&0x01) //檢測到按下S7,即0001,用trg==0x01會使按鍵不靈敏
P0=~0x40; //點亮L7
else if(trg&0x02) //檢測到按下S6,即0010
P0=~0x20;
else if(trg&0x04) //檢測到按下S5,即0100
P0=~0x10;
else if(trg&0x08) //檢測到按下S4,即1000
P0=~0x08;
P2=0x80;
P2=0;
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定時器時鐘1T模式
TMOD &= 0xF0; //設定定時器模式
TL0 = 0xCD; //設定定時初值
TH0 = 0xD4; //設定定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0=1; //記得加上這兩句
EA=1;
}
void Timer0_Service() interrupt 1 //中斷入口
{
++count_key;
}
void main()
{
P0=0x00;
P2=0xa0; //打開鎖存器控制蜂鳴器和繼電器
P2=0;
P0=0xff;
P2=0x80; //打開鎖存器控制LED
P2=0;
Timer0Init();
while(1)
{
if(count_key>9) //10ms重繪一次,相當于消抖
{
count_key=0; //控制重繪率的變數清零
scan_button(); //呼叫獨立按鍵處理函式
}
}
}
2.2矩陣按鍵
跳線帽需要短接J5口的1和2引腳,按鍵能使用16個(即上圖中S4-S19),矩陣按鍵的掃描方法可采用行列掃描法,分為兩步:
- 將行的輸出設為低電平(0),檢測列的電平輸入值,
- 將列的輸出設為低電平(0),檢測行的電平輸入值,
將兩個檢測值進行疊加,計算判斷哪個按鍵被按下
例子:按下S7使數碼管顯示+1.按下S11使顯示的數-1,數的范圍0~200,當其為奇數時打開蜂鳴器關閉繼電器,為偶數時打開繼電器關閉蜂鳴器,
#include<stc15f2k60s2.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit buzzer=P0^6;
sbit relay=P0^4;
uchar dsp_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //顯示內容(0~9
uchar dsp_value[8]={0xff,0xff,0xff,0xff,0xff};//初始化,使前5位數碼管熄滅
uchar number=10;
uchar count_key;//控制數碼管重繪率
void Timer0_sevice() interrupt 1
{
static uchar dsp_com=0;
uchar P0_keeper=0,P2_keeper=0;
P0_keeper=P0;P2_keeper=P2; //現場保護
P0=0;
P2=0xc0; //消影,使所有數碼管熄滅
P2=0;
P0=dsp_value[dsp_com];
P2=0xe0; //打開鎖存器控制數碼管段選
P2=0;
P0=1<<dsp_com;
P2=0xc0; //打開鎖存器控制數碼管位選
P2=0;
if(++dsp_com==8) dsp_com=0;
P0=P0_keeper;P2=P2_keeper;//回傳現場
++count_key;
}
void scan_key()
{
static uchar key_stat=0;
uchar key_val=0,key_x=0,key_y=0;
P3=0x0f;P4=0x00;//行掃描
if(!P30) key_x=3;
else if(!P31) key_x=2;
else if(!P32) key_x=1;
else if(!P33) key_x=0;
P3=0xf0;P4=0xff;//列掃描
if(!P34) key_y=4;
else if(!P35) key_y=3;
else if(!P42) key_y=2;
else if(!P44) key_y=1;
key_val=key_x+key_y*4;//綜合行、列掃描的結果,判斷具體位置
switch(key_stat)
{
case 0:
if(key_val!=0) key_stat=1;//第一次檢測到有按鍵按下,狀態為1
break;
case 1:
if(key_val==0) key_stat=0;//第二次(10ms后)若檢測到無按鍵按下,回傳狀態0,按鍵防抖
else
{
key_stat=2;//第二次(10ms后)再次檢測到有按鍵按下,狀態為2
switch(key_val)
{
case 7: //按下S7數字加一
if(number<200)//注意判斷后再執行,防止數超出范圍
{
++number;
}
break;
case 11: //按下S11數字減一
if(number>0)
{--number;}
break;
}
}
break;
case 2: //按鍵防抖設計
if(key_val==0)key_stat=0;//第三次若檢測到無按鍵按下,回傳狀態0
break;
}
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定時器時鐘1T模式
TMOD &= 0xF0; //設定定時器模式
TL0 = 0xCD; //設定定時初值
TH0 = 0xD4; //設定定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0=1; //記得加上這兩句
EA=1;
}
void main()
{
P0=0xff;P2=0x80;P2=0;
P0=0x00;P2=0xa0;P2=0;
Timer0Init();
while(1)
{
if(number%2==1)
{
buzzer=1;
relay=0;
}
else
{
relay=1;
buzzer=0;
}
P2=0xa0;P2=0;
if(number>9)
dsp_value[6]=dsp_code[number/10%10];
else
dsp_value[6]=0xff;
dsp_value[7]=dsp_code[number%10];
if(count_key>9) //10ms重繪一次,相當于消抖10ms
{
count_key=0; //控制重繪率的變數清零
scan_key(); //呼叫矩陣按鍵處理函式
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/260046.html
標籤:其他
上一篇:每日一題2
