最佳答案

//絕對除錯透過,AVR-GCC,mega16,帶數位顯示,單鍵開關多功能控制

#include avr/io.h

#include avr/interrupt.h

#include tone.h

#include avr/pgmspace.h

#define uchar unsigned char

#define uint unsigned int

#define key_input PINA

#define pgm16(A) ((typeof(A))pgm_read_word(&(A)))

const unsigned char seg_code[] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x7f,0x3f};

const uint music[] PROGMEM={M3,F2,M5,B1,M3,F4,M2,F4,M1,B2,L6,F2,M1,F2,MM,M1,F2,L6,F2,L5,B2, L6,F2,M1,B1,MM,M1,F2,L6,F2,M6,F2,L5,F2,M3,F2,M2,F2,MM,M2,F4,M1,F4,L6,F2,M3,F2,M2,B2, M3,F2,MM,M3,F2,MM,M3,F2,M2,F2,M1,B2,L6,F2,M1,F2,L7,F2,L5,F2,L6,B2, L5,F2,L6,F2,MM,L6,F2,L5,F2,M6,F2,M5,F2,MM,M5,F2,M3,F2,M2,F2,MM,M2,F4,M3,F4,M3,F2,M2,F2,M1,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,F2,MM,H1,F2,M6,F2,MM,M6,F2,M5,F2,MM,M5,F2,M3,F2,M5,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,F2,MM,H1,F2,M6,F2,M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,B2, M3,B1,MM,M3,F2,M5,F2,M6,F2,M5,F2,MM,M5,F2,M3,F2,MM,M3,F2,M2,F2,MM,M2,F2,M1,F2,L6,B2, L5,F2,M5,F4,MM,M5,F4,MM,M5,F2,M6,F2,M5,F2,M3,F2,M2,F2,M3,F2,MM,M3,F2,M2,B1,L6,F2,M1,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,B1,M6,F2,MM,M6,F2,M5,F2,MM,M5,F2,M3,F2,M5,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,B1,M6,F2, M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,B2,MM, M2,F2,MM,M2,F4,M1,F4,M2,F2,M3,F2,M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,F2,MM,M2,F4,M3,F4,M2,F2,M1,F2,L6,B2, L5,F2,M5,F4,MM,M4,F4,MM,M5,F2,M6,F2,M5,F2,M3,F2,M2,F2,M2,F4,M3,F4,MM,M3,F2,M2,B1,L6,F2,M1,B3,0XFF,0XFF};

//因為兩個相同的音符之間無停頓,人為插入了MM(極短暫的

volatile uint i=1;

volatile uchar timeOK=0;

uchar key_scan(void);

ISR(TIMER0_COMP_vect) //CTC模式,控制音調高低

{

OCR0=pgm16(music[i-1]);

}

ISR(TIMER1_OVF_vect) //時間溢位模式,控制節拍長短

{

i =2;

TCNT1H=(65536-pgm16(music[i]))/256; //相當於(65536-beat[i])/256

TCNT1L=(65536-pgm16(music[i]))%6; //相當於(65536-beat[i])%6

if(pgm16(music[i])==0xff)i=1; //在音調陣列的最後加一個0xff,作為終止訊號

if(pgm16(music[i])==0x00)TIMSK&=(~(1OCIE0));

else TIMSK|=(1OCIE0);

}

ISR(TIMER2_OVF_vect) //時間溢位模式,用於檢測按鍵,週期10ms

{

TCNT2=100;

timeOK=1;

}

void timer0_init(void)

{

TCCR0=0x00;

TCNT0=0x00;

OCR0=pgm16(music[i-1]);

TCCR0=0x1a;

//TIMSK|=(1OCIE0);

}

void timer1_init(void)

{

TCCR1B=0x00;

TCNT1H=(65536-pgm16(music[i]))/256;

TCNT1L=(65536-pgm16(music[i]))%6;

TCCR1A=0x00;

TCCR1B=0x05;

//TIMSK|=(1TOIE1);

}

void timer2_init(void)

{

TCCR2=0x00;

TCNT2=100;

TCCR2=0x03;

TIMSK|=(1TOIE2);

}

void MCU_init(void)

{

DDRA=0X00;

DDRB=0X00;

DDRC=0XFF;

DDRD=0XFF;

PORTB=0X00;

PORTC=0xfe;

PORTD=0xff;

}

uchar key_scan(void) //按鈕掃描函式

{

static uchar key_state=0,key_time1=0,key_time0=0; //靜態變數,呼叫以後,值被保留;

uchar key_press,key_return=0;

key_press=(~key_input)0x01; //有鍵1,無鍵0

switch(key_state) //狀態機

{

case 0: //狀態0:無按鈕按下狀態

if(key_press)key_state=1;

break;

case 1: //狀態1:檢測到有按鈕被按下

if(key_press) //按鈕仍按下,轉2

{

//TIMSK^=(1TOIE0);

key_state=2;

key_time1=0; //按下時間初始

}

else //按鈕已經釋放,消抖

key_state=0;

break;

case 2: //狀態2:等待釋放或等待按下時間達到長按要求

if(!key_press) //按鈕已經釋放,轉3,繼續判斷是雙按還是單按

{

key_state=3;

key_time0=0; //釋放時間初始

}

else if ( key_time1=100) //按下時間達到1000ms,返回值2,作長按判斷,轉7等待按鈕釋放

{

key_state=8;

key_time1=0;

key_return=2;

}

break;

case 8:

if(!key_press)

{

key_state=0;

key_time1=0;

}

else if ( key_time1=50)

{

key_return=2;

key_time1=0;

}

break;

case 3: //狀態3:雙按的第二次按鈕輸入前的等待間隙,設定100ms(經過測試,100ms為比較合適的時間間隙,即為人體普通可以雙擊的速度

if(key_press)key_state=4; //在此時間,如果有按鈕被按下,將當作釋放抖動,轉4進一步作出判斷

else if ( key_time04) //如果沒有按鈕被按下,則等待此100ms過去,然後轉5

{

key_state=5;

key_time0=0;

}

break;

case 4: //狀態4:第二按的消抖處理

if(key_press)key_state=2; //快速連按(被認為人手指達不到要求的速率)將被返回到2,當作第一按處理

else key_state=3; //如果第二按只出現一次,不到10ms,消抖

break;

case 5: //狀態5:第二按前等待時間到達,進入正常的第二按等待輸入狀態,第二按只允許在此時間內輸入方為有效

if(key_press)key_state=6; //此時間內有被按下,轉6,判決抖動;

else if( key_time014) //無輸入,則等待輸入有效時間過去,時間滿後,判定為單按,返回值1,狀態位回到0

{

key_state=0;

key_time0=0; //雙擊間隔時間一般為100ms,能夠穩定做到第二擊完成時間總共約180~200ms(因人而異)

key_return=1; //為增加取樣成功率,可適當縮短第二按前的間隙時間,增加第二按等待輸入時間,但總時間不可短於150ms

} //小於150ms,手指將很難達到雙擊的速度要求,如果時間太長則單按判斷時間過長,按鈕不靈敏,此處180ms經測試較為合適

break;

case 6: //狀態6:第二按的抖動判斷

if(key_press) //按鈕仍有效,按下有效,返回3,雙按成立,轉7等待按鈕釋放

{

key_state=7;

key_return=3;

}

else key_state=5; //抖動消除,退回5繼續等待輸入或等待輸入有效時間過去

case 7: //按鈕釋放等待狀態,所有已按下並被識別操作目的的按鈕狀態都將轉到7等待按鈕釋放,並將所有計時初始

if(!key_press)key_state=0;

key_time1=0;

key_time0=0;

break;

}

return key_return;

}

int main(void)

{

MCU_init();

timer0_init();

timer1_init();

timer2_init();

sei();

while(1)

{

if(timeOK)

{

cli();

uchar key;

key=key_scan();

if(key0)PORTD=seg_code[key];

switch(key)

{

case 1:

TIMSK^=((1OCIE0)|(1TOIE1)); DDRB^=(1DDB3); PORTC=0xfd;

break;

case 2:

//TIMSK|=((1OCIE0)&(1TOIE1));

if(i1)i =10;

if (i=(sizeof(music)-20))

{

i=1;

TIMSK&=(~((1OCIE0)|(1TOIE1)));

DDRB&=~(1DDB3);

}

PORTC=0xf0;

break;

case 3:

TIMSK&=(~((1OCIE0)|(1TOIE1)));

i=1;

TIMSK|=((1OCIE0)|(1TOIE1));

PORTC=0xfe;

break;

default:

break;

}

timeOK=0;

sei();

}

}

}

繼續學習常見問答

小學數學斤和克的換算是幾年級學

應該在小學三年級或四年級學,主要學國際單位換算,斤是我國曆史遺留下來的重量單位,現在商場商品重量單位都以公斤與克表示,國際重量單位換算1噸=1000公斤,1公斤=1000克如果要轉換成國內的斤,兩,那麼1公斤=2市斤,1斤=10市兩,在改革...


千克和克的物品有哪些

用克表示的物品有貴金屬,金、銀等手飾,中藥方中的藥材,小包裝的食品、調料、調味品,西藥藥片、粒劑量,貴重藥材如人参、靈芝等,羽絨服的填充物等等。用千克表示物品有菜市場的各種蔬菜,水果店各種水果,各種袋裝的麵粉、大米,肉品店豬、羊、牛肉,雞蛋...


華為mete40pro和蘋果12pro掃二維碼那個快

當然是蘋果的掃描速度更快一些。詳細原因如下:有國外媒體為此專門進行測試,使用iPhone6和三星上一代旗艦機S9多次掃描同一個二維碼,iPhone6識別速度總是超過S9,而且每次都可以實現秒識別。對比兩款裝置的CPU,iPhone6搭載的A...


藍芽耳機一邊有聲音一邊沒聲音怎麼辦安卓手機

藍芽耳機一邊有聲音一邊沒聲音的問題可能在於藍芽連線、耳機硬體或裝置設定。以下是一些建議來解決這個問題:1.重新連線藍芽耳機:&&首先,確保您的藍芽耳機已關閉。然後,開啟藍芽耳機,使其進入配對模式(通常可以透過按住耳機上的某個按鈕進入配對模式...


安卓系統手機,自動連線藍芽耳機的辦法

1,安卓系統手機沒有辦法可以自動連線藍芽耳機的。2,必須是在藍芽耳機進入配對狀態,手機才能搜到,然後連線使用的。3,安卓系統手機和藍芽耳機的連線方式如下步驟:第一步:手機手機開啟藍芽功能,進入藍芽搜尋狀態。第二步:使藍芽耳機開機狀態,需要長...


安卓藍芽耳機一個響一個不響

1、手機耳機只有一邊有聲音,首先檢查耳機線是否完好,可能是一邊的耳機線折斷了,導致沒有聲音。2、可能是因為音量控制中的左右聲道平衡給調節到一邊了,只需要在設定中把聲道平衡滑塊調到中間就行了。3、可能是耳機插孔損壞了,或者某個聲道接觸不良,把...


安卓藍芽耳機整盒丟了怎麼找回

如果您的安卓藍芽耳機整盒丟失了,您可以嘗試以下方法找回它們:1.使用手機查詢功能:如果您的耳機與手機已經配對,您可以嘗試使用手機的查詢功能來尋找耳機。在手機的藍芽設定中,找到已配對的裝置列表,點選耳機名稱旁邊的“查詢”按鈕,耳機會發出聲音,...


如何關閉微信小程式中的個人資訊的授權

在使用微信的時候通常會用到微信小程式,一些微信小程式需要我們授權微信個人資訊(頭像、暱稱、地址等)才能使用,在不使用該小程式後要如何關閉個人資訊的授權呢?接下來就給大家分享一下怎樣關閉微信小程式中的個人資訊的授權。工具/原料手機方法/步驟1...


光影精靈6怎麼檢視型號

可以透過裝置管理器檢視光影精靈6的型號。裝置管理器是Windows作業系統提供的一個系統工具,可以列出計算機的所有裝置資訊,包括硬體裝置、驅動程式等等。在裝置管理器中,使用者可以檢視光影精靈6的硬體配置資訊,例如處理器、記憶體、顯示卡等等資...


膝上型電腦型號在哪看

正規的筆記本會在筆記本底部有紙張標籤有產品引數序列號型號的或者筆記本明顯位置有型號品牌。實在不知道可以進系統然後裝置管理器檢視擴充套件知識:膝上型電腦(Laptop),簡稱筆記本,又被稱為“行動式電腦,手提電腦、掌上電腦或膝上型電腦”,其最...