//======================================================//
**基于STM32的按鍵控制與外部中斷實例詳解
**為了減少重復(fù)的內(nèi)容,所以將外部中斷的例程與按鍵控制實例
放在一起學(xué)習(xí)。
一開始先在51黑論壇率先上傳了本文,上傳時間不分什么順序,只是希望在學(xué)習(xí)中慢慢寫下自己的思路。
//======================================================//
/********************************************************/
因為涉及的內(nèi)容較多,這里大體說一下整片文章的內(nèi)容分布:
1)、按鍵控制實例
1、按鍵的相關(guān)信息描述
2、按鍵的初始化代碼實現(xiàn)
3、常用按鍵檢測及控制代碼(主要學(xué)習(xí)其實現(xiàn)思路)
2)、外部中斷實例
1、外部中斷的相關(guān)信息描述
2、外部中斷的初始化代碼實現(xiàn)
/********************************************************/
==================================華麗的分界線=================================
//=========================按鍵控制實例=============================//
==================================華麗的分界線=================================
首先,先來講述簡單的按鍵控制,下面來看看按鍵是什么東西,開發(fā)的時候按鍵又有哪些要注意的事情.
釋義:
按鍵開關(guān)是一種電子開關(guān),屬于電子元器件類,使用時以滿足操作力的條件向開關(guān)操作方向施壓開關(guān)功能閉合接通,當(dāng)撤銷壓力時開關(guān)即斷開,其內(nèi)部結(jié)構(gòu)是靠金屬彈片受力變化來實現(xiàn)通斷的。
一般在開發(fā)中涉及按鍵的一般是按鍵消抖。按鍵消抖通常的按鍵所用開關(guān)為機械彈性開關(guān),當(dāng)機械觸點斷開、閉合時,由于機械觸點的彈性作用,一個按鍵開關(guān)在閉合時不會馬上穩(wěn)定地接通,在斷開時也不會一下子斷開。也就是在閉合及斷開的那一瞬間會有一小段的不穩(wěn)定狀態(tài),即伴隨著連續(xù)的抖動。按鍵在電路中一般也就0跟1兩中狀態(tài),正常情況下,按鍵沒有按下的情況下,按鍵所連的引腳狀態(tài)一般都是為1。原因是一般會在引腳上加上一個上拉,然后再與按鍵相連,按鍵的另一端接地,所以在按鍵沒有按下的情況下,引腳返回的一般都是高電平,這是電路決定的。如下圖:
按鍵的抖動就是介于1跟0的不定狀態(tài)。所以為了取得穩(wěn)定狀態(tài),需要在延遲取狀態(tài)值,也就是既然知道有抖動存在了,那么就把取值的時間延遲一下。還有一個東西跟抖動有關(guān),那就是觸發(fā)沿的設(shè)置,比如上升沿和下降沿的觸發(fā)。上升沿是按鍵松開后那一瞬間,電平從0到1的過程,下降沿就與之相反,也就是按鍵按下的一瞬間,電平從1降為0的過程。邊沿觸發(fā)一般會用在外部中斷的過程中。下面的內(nèi)容也會講到。
按鍵相對來說比較簡單,按鍵的初始化跟LED和BEEP蜂鳴器幾乎一致,不同之處也就在于按鍵是輸入設(shè)備,所以GPIO的模式上一般選為輸入模式,緊接著就要設(shè)置上拉/下拉輸入模式,最后設(shè)置初始狀態(tài),這個要根據(jù)電路來間接。
//=======================key.c===============================//
/************************************************
接口:
key0引腳接在 PE4 低電平有效
key1引腳接在 PE3 低電平有效
key_up引腳接在 PA0 高電平有效
************************************************/
#include "stm32f10x.h"
#include "key.h"
#include "delay.h"
void key_Init(void)
{
RCC ->APB2ENR |= 1 << 2;//使能 PORTA 時鐘
RCC ->APB2ENR |= 1 << 6;//使能 PORTE 時鐘
//key_up配置
GPIOA ->CRL &= ~(15 << 0);//先設(shè)置輸入模式
GPIOA ->CRL |= 1 << 3; //PA.0 下拉輸入模式
GPIOA ->ODR &= ~(1 << 0); //設(shè)置下拉,即設(shè)置初始狀態(tài)為低電平
//key1配置
GPIOE ->CRL &= ~(3 << 13);//先設(shè)置輸入模式
GPIOE ->CRL |= 1 << 15; //PE.3 上拉輸入模式
GPIOE ->ODR |= 1 << 3; //設(shè)置上拉,即設(shè)置初始狀態(tài)為高電平
//key0配置
GPIOE ->CRL &= ~(3 << 17);//先設(shè)置輸入模式
GPIOE ->CRL |= 1 << 19; //PE.4 上拉輸入模式
GPIOE ->ODR |= 1 << 4; //設(shè)置上拉,即設(shè)置初始狀態(tài)為高電平
}
/*************************************************************
**功 能:按鍵處理函數(shù)
**輸入?yún)?shù):無
**輸出參數(shù):
//mode:0,不支持連續(xù)按;1,支持連續(xù)按;
//0,沒有任何按鍵按下
//1,KEY0 按下
//2,KEY1 按下
//3,KEY_UP 按下 即 WK_UP
**注 釋:注意此函數(shù)有響應(yīng)優(yōu)先級,KEY0>KEY1>KEY_UP!!
***********************************************************/
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1; //按鍵按松開標(biāo)志
if(mode)key_up=1; //支持連按
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{
delay_ms(10); //去抖動
key_up=0;
if(KEY0==0)return 1;
else if(KEY1==0)return 2;
else if(WK_UP==1)return 3;
}
else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;
return 0;// 無按鍵按下
}
//======================================================//
注釋:按鍵檢測函數(shù),原理是檢測按鍵的電平,而mode的作用就是一直把key_up置1,那么就會一直進入按鍵按下的檢測,而不會進入按鍵松開的檢測。
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))這句是進行按鍵按下的檢測,
else if(KEY0==1&&KEY1==1&&WK_UP==0)這句是進行按鍵松開的檢測。
如果沒有按鍵按下的話,雖然key_up為1,但是沒有按鍵,那么就只會返回0。
==================================華麗的分界線=================================
//===========================key.h===========================//
#ifndef __KEY_H_
#define __KEY_H_
#include "stm32f10x.h"
#include "sys.h"
#define KEY0 PEin(4) //PE4
#define KEY1 PEin(3) //PE3
#define WK_UP PAin(0) //PA0 WK_UP 即 KEY_UP
#define KEY0_PRES 1 //KEY0 按下
#define KEY1_PRES 2 //KEY1 按下
#define WKUP_PRES 3 //KEY_UP 按下(即 WK_UP/KEY_UP)
extern void key_Init(void);
extern u8 KEY_Scan(u8 mode);
#endif
//======================================================//
==================================華麗的分界線=================================
//==========================main.c============================//
/*************************************************************
**功 能:按鍵處理函數(shù)
//1,KEY0 按下 控制LED0
//2,KEY1 按下 控制LED1
//3,KEY_UP 按下 即 WK_UP 控制蜂鳴器
***********************************************************/
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
int main(void)
{
u8 key=0;
Stm32_Clock_Init(9); //系統(tǒng)時鐘設(shè)置
delay_init(72); //延時初始化
led_Init();//LED初始化
beep_Init(); //beep初始化
key_Init(); //key初始化
while(1)
{
key=KEY_Scan(0); //得到鍵值
if(key)
{
switch(key)
{
case WKUP_PRES: //控制蜂鳴器
GPIOB ->ODR |= (1 << 8);//PB.8 輸出高,即蜂鳴器開
delay_ms(10000);//延時
GPIOB ->ODR &= ~(1 << 8);//PB.8 輸出低,即蜂鳴器關(guān)
break;
case KEY1_PRES: //控制 LED1
GPIOB ->ODR &= ~ (1 << 5);//PB.5輸出低電平,即點亮LED
delay_ms(10000); //延時
GPIOB ->ODR |= 1 << 5;//PB.5輸出高電平,即滅掉LED
break;
case KEY0_PRES: //控制 LED0
GPIOE ->ODR &= ~(1 << 5);//PB.5輸出低電平,即點亮LED
delay_ms(10000); //延時
GPIOE ->ODR |= 1 << 5;//PB.5輸出高電平,即滅掉LED
break;
}
}
else delay_ms(10);
}
}
//======================================================//
==================================華麗的分界線=================================
//=========================外部中斷實例=============================//
**注釋:特別鳴謝CSDN博客的博主->“zzwdkxx”的博文,在外部中斷的學(xué)習(xí)中直接的幫助!
博文地址:http://blog.csdn.net/zzwdkxx/article/details/9036679
==================================華麗的分界線=================================
接著下面將進行外部和中斷的講解,講之前先對中斷先做一定了解。
//============================百度搜索==========================//
簡介:
中斷是處理器處理外部突發(fā)事件的一個重要技術(shù)。它能使處理器在運行過程中對外部事件發(fā)出的中斷請求及時地進行處理,處理完成后又立即返回斷點,繼續(xù)進行處理器原來的工作。引起中斷的原因或者說發(fā)出中斷請求的來源叫做中斷源。根據(jù)中斷源的不同,可以把中斷分為硬件中斷和軟件中斷兩大類,而硬件中斷又可以分為外部中斷和內(nèi)部中斷 兩類。
外部中斷一般是由計算機外設(shè)發(fā)出的中斷請指求,如:鍵盤中斷、打印機中斷、定時器中斷等。外部中斷是可以屏蔽的中斷,也就是說,利用中斷控制器可以屏蔽這些外部設(shè)備 的中斷請求。
內(nèi)部中斷是指因硬件出錯(如突然掉電、奇偶校驗錯等)或運算出錯(除數(shù)為零、運算溢出、單步中斷等)所引起的中斷。內(nèi)部中斷是不可屏蔽的中斷。
軟件中斷其實并不是真正的中斷,它們只是可被調(diào)用執(zhí)行的一般程序。
優(yōu)先級:
CPU為了處理并發(fā)的中斷請求,規(guī)定了中斷的優(yōu)先權(quán),中斷優(yōu)先權(quán)由高到低的順序是: (1)除法錯、溢出中斷、軟件中斷 (2)不可屏蔽