


單鍵開(kāi)關(guān)電路已經(jīng)廣泛應用于PDA、手機和電子詞典等數碼產(chǎn)品中,其實(shí)現方式多種多樣。一般可采用RS觸發(fā)器、計數器以及采用555集成電路等等。在單片機的一些實(shí)際應用中,以上的實(shí)現方式會(huì )增加整個(gè)電路的復雜度,不能達到簡(jiǎn)潔、實(shí)用的效果。本文將介紹一種可以在單片機應用中實(shí)現的,簡(jiǎn)易、穩定的輕觸式單鍵開(kāi)關(guān)電路。
相關(guān)電路如下圖示:
MCU用的是AVR 的ATMEGA16L,電源芯片用的是LM2576-3.3,是低電平開(kāi)啟的,有些電源芯片用的是高電平開(kāi)啟。圖中有標注。
這個(gè)是不能復位的版本。一復位就會(huì )關(guān)機。就是只有上電復位。
說(shuō)明一下第一個(gè)電路工作原理:
S2按下后,D3,Q1,Q3導通,輸出低電平給LM2576的判斷控制端。穩壓芯片工作,為單片機供電。單片機馬上將相應的I/O引腳置為輸出高,這時(shí)Q1和Q2及Q3都導通,整個(gè)電路進(jìn)入工作狀態(tài)。而后單片機再將這個(gè)I/O引腳設置為輸入,由于開(kāi)啟AVR單片機IO的內置上拉電阻,Q1和Q2和Q3一直導通。單片機一直掃描相應I/O輸入狀態(tài),如果S2沒(méi)有按下去,則這個(gè)I/O將始終為高。當S2再次按下去時(shí),D4導通,單片機檢測到這個(gè)I/O引腳輸入為低,此時(shí)作些延時(shí),看延時(shí)合不合預先設定的值,達到則將單片機的這個(gè)I/O設置成輸出為低的狀態(tài)。Q2截止,如果按鍵抬起,Q1也會(huì )截止,穩壓芯片將不會(huì )為單片機提供電壓,整個(gè)電路處于關(guān)斷狀態(tài)。
注意,C10是必不可少的,不然由于單單片機的復位操作會(huì )使系統斷電。
進(jìn)入正常工作后,就將正常工作的代碼寫(xiě)入EEPROM。關(guān)機時(shí)將正常關(guān)機的代碼也寫(xiě)入EEPROM。這樣,還可以檢測是不是正常關(guān)機。
最后,奉上這些boot代碼:
//*****************************GCC for the new lab board ******************************
//****************************** code 02 ***********************************************
#include #include #include #include #define POWER PB0 #define LED PD7 #define ON 0x0f #define OFF 0xf0 //******************************向UART 寫(xiě)一字節************************************** int usart_putchar(char c) { if(c== usart_putchar( ); loop_until_bit_is_set(UCSRA,UDRE); UDR=c; return 0; } //*******************************從UART 讀一字節************************************* int usart_getchar(void) { loop_until_bit_is_set(UCSRA,RXC); return UDR; } //************************************初始化i/o************************************** void Initialuart(void) { //UART 初始化 UCSRB=_BV(RXEN)|_BV(TXEN);/*(1<<><> UBRRL=25; //9600 baud 6MHz:38 4MHz:25 //i/o 流UART 連接 fdevopen(usart_putchar,usart_getchar,0); } //*********************************to start the power,hehe*************************** void Powerpost(void) { unsigned long i=0; unsigned char val; DDRB&=~_BV(POWER); PORTB|=_BV(POWER); eeprom_busy_wait(); val=eeprom_read_byte(0); //從EEPROM 0 地址處讀取一字節賦給RAM 變量val if(val==OFF) { //if(PIND&_BV(K4)) _delay_ms(500);if(PIND&_BV(K4)) while(!(PINB&_BV(POWER))) {i++;if(i>300000) break;} if(i>=300000) { DDRB|=_BV(POWER); PORTB|=_BV(POWER); eeprom_busy_wait(); //等待EEPROM 讀寫(xiě)就緒 eeprom_write_byte(0,ON); //將0xbb 寫(xiě)入到EEPORM 0 地址處 DDRD|=_BV(LED); PORTD|=_BV(LED); } else { eeprom_busy_wait(); //等待EEPROM 讀寫(xiě)就緒 eeprom_write_byte(0,OFF); //將0xbb 寫(xiě)入到EEPORM 0 地址處 DDRB|=_BV(POWER); PORTB&=~_BV(POWER); DDRD|=_BV(LED); PORTD&=~_BV(LED); } } else { DDRD|=_BV(LED); PORTD|=_BV(LED); DDRB|=_BV(POWER); PORTB|=_BV(POWER); eeprom_busy_wait(); //等待EEPROM 讀寫(xiě)就緒 eeprom_write_byte(0,ON); //將0xbb 寫(xiě)入到EEPORM 0 地址處 } } //************************************Shut Down ************************************* void ShutDown(void) { unsigned long i=0; while(!(PINB&_BV(POWER))) {i++;if(i>200000) break;} if(i>=200000) { eeprom_busy_wait(); //等待EEPROM 讀寫(xiě)就緒 eeprom_write_byte(0,OFF); //將OFF 寫(xiě)入到EEPORM 0 地址處 PORTD&=~_BV(LED); DDRB|=_BV(POWER); PORTB&=~_BV(POWER); } } //************************************the entrey************************************* int main() { Powerpost(); Initialuart(); printf("hello,你好嗎?嘿嘿!! // PORTB=0x00; while(1) { ShutDown(); } } 祝大家成功!!!
)
");
聯(lián)系客服