STM32按鍵輸入、所需要的C語言複習、時鐘系統框圖

樂小樹發表於2015-11-08

第一部分:

STM32按鍵輸入是我的第二個在STM32 平臺上有輸入的小例項。思路為,先查詢硬體圖看清按鍵是低電平有效還是高電平有效,根據我的開發環境得知四個按鍵有三個按鍵是低電平有效,有一個按鍵是高電平有效。然後設計程式碼,設計程式碼之前得分析清楚,按鍵有兩種情況,可持續按鍵和不可持續按鍵。可持續按鍵的意思是,按一下放開後,繼續按還會有用,而不可持續按鍵就不行。

分清按鍵型別就可以照一般運用外設的三步走戰略前進,第一步初始化按鍵輸入時鐘,第二步初始化所運用的IO時鐘,第三步掃描鍵盤

初始化時鐘選擇時鐘系統中的高速匯流排掛載的時鐘,APB2所包含的時鐘函式RCC_APB2PeriphClockCmd()。具體下面的時鐘系統分析會清晰的講述。

接下來呼叫IO初始化函式GPIO_Init();

最後一步用於掃描鍵盤,掃描鍵盤設定了掃描引數,為兩種模式,模式0是不持續按鍵,模式1是持續按鍵,具體掃描引數如下程式碼:

u8 key_scan(u8 mode)
{
static u8 key_up=1;//mode0是不持續按鍵,mode1是持續按鍵
  if(mode==1) key_up=1;
if(key_up&&(key0==0||key1==0||key2==0||wk_up==1))
{
delay_ms(30);
key_up=0;
if(key0==0)return key0_pres;//
else if(key1==0) return key1_pres;
else if(key2==0) return key2_pres;
else if(wk_up==1) return wkup_pres;
}
else if(key0==1&&key1==1&&key2==1&&wk_up==0)key_up=1;
return 0;
}

所寫的標頭檔案主要是函式申明和一些所需要的預編譯如下:

#ifndef __Key_Init
#define __Key_Init
#include "sys.h"//包含位帶操作
//採用位帶操作
//#define key0  PEin(4)
//#define key1  PEin(3)
//#define key2  PEin(2)
//#define wk_up PAin(0)
//採用庫函式
#define key0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)
#define key1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)
#define key2  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)
#define wk_up GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define key0_pres 1//控制led0
#define key1_pres 2//控制led0
#define key2_pres 3//控制跑馬燈
#define wkup_pres 4//控制蜂鳴器
//採用暫存器

void __key_init(void);
u8 key_scan(u8);
#endif
採用暫存器進行操作,主要是操作CRL和ODR暫存器,由於採用的是上拉下拉輸入,而上拉下拉的控制是由ODR暫存器控制

第二部分:

接下來的內容是對STM32 中經常用到的C語言知識的複習回顧,按鍵輸入中用到的不持續按鍵就用到了static變數,讓變數儲存於靜態區,以利於鍵值的保持。

對於STM32中用到比較多的C語言是下述

n位操作
n  define巨集定義關鍵詞
n  ifdef條件編譯
n  extern變數申明
n  typedef型別別名
n  結構體
n  static關鍵字
位操作主要有六種,按位與,或,取反,異或左移右移
按位或主要運用在如上面對GPIO口的初始化中GPIO_InitKEY.GPIO_Pin= GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
可以節省程式碼量。
後面的ifdef等屬於預編譯,主要有的程式碼塊可以執行也可以不執行,一般用到ifdef預編譯。
extern申明這個變數或者函式可以在別的檔案中引用
typedef主要就是給資料型別取一個別名如u8等,和#define型別,但差別又很大,#define可以定義任何別名,而typedef一般用於資料型別
static主要就是把全域性或區域性變數儲存於靜態儲存區,運用其所謂的記憶功能
結構體則具有很強的作用,很重要的作用,尤其對於程式碼的擴充套件性來說,如一個函式有很多的引數,若想新增引數則,整個檔案所有運用到這個函式的地方都得改動,而用結構體只需在引用時引用在結構體中新增即可。
增加一個內容,STM32中的暫存器地址對映:
以地址是如何計算到GPIOA為例,首先地址找到的是外設的基地址,然後加上偏移找到APB2匯流排的地址,再加上GPIOA的地址偏移量,計算出GPIOA的基地址,其他的七個暫存器地址依次加入偏移量即可,原理圖如圖一。
第三部分:

我認為第三部分是整個STM32中最重要的地方,很多地方把時鐘系統比喻為系統的心臟,我覺得更貼切的是比喻為血液,一個器官有血液流過,才帶來氧用於提供器官所需能量。
時鐘系統原理圖在最下面給出。首先給出時鐘系統的總結如下:

1.STM32 5個時鐘源:HSIHSELSILSEPLL

     ①、HSI是高速內部時鐘,RC振盪器,頻率為8MHz,精度不高。
   ②、
HSE是高速外部時鐘,可接石英/陶瓷諧振器,或者接外部時

                鍾源,頻率範圍為4MHz~16MHz
   ③、
LSI是低速內部時鐘,RC振盪器,頻率為40kHz,提供低功耗時鐘。WDG
   ④、
LSE是低速外部時鐘,接頻率為32.768kHz的石英晶體。RTC
   ⑤、
PLL為鎖相環倍頻輸出,其時鐘輸入源可選擇為HSI/2HSE或者HSE/2

              倍頻可選擇為2~16倍,但是其輸出頻率最大不得超過72MHz
2. 系統時鐘SYSCLK可來源於三個時鐘源:
       
①、HSI振盪器時鐘

        ②、HSE振盪器時鐘

        ③、PLL時鐘

3.STM32可以選擇一個時鐘訊號輸出到MCO(PA8)上,可以選擇為PLL

  輸出的2分頻、HSIHSE、或者系統時鐘。

4.任何一個外設在使用之前,必須首先使能其相應的時鐘。

下面給出系統比較重要的時鐘:

1SYSCLK(系統時鐘) :
2AHB匯流排時鐘:總共有六種分頻因子,用來提供APB1和APB2
3APB1匯流排時鐘(低速): 速度最高36MHz,主要用來提供低速外設的
4APB2匯流排時鐘(高速): 速度最高72MHz,主要用來提供高速外設
5PLL時鐘,鎖相環所提供的時鐘主要用來倍頻。

typedefstruct

{

  __IO uint32_tCR;                //HSI,HSE,CSS,PLL等的使能和就緒標誌位

  __IO uint32_tCFGR;           //PLL等的時鐘源選擇,分頻係數設定

 __IO uint32_t CIR;              //清除/使能 時鐘就緒中斷

 __IO uint32_t APB2RSTR;  //APB2線上外設復位暫存器

 __IO uint32_t APB1RSTR;   //APB1線上外設復位暫存器

  __IO uint32_tAHBENR;    //DMASDIO等時鐘使能

  __IO uint32_tAPB2ENR;   //APB2線上外設時鐘使能

  __IO uint32_tAPB1ENR;   //APB1線上外設時鐘使能

 __IO uint32_t BDCR;        //備份域控制暫存器

 __IO uint32_t CSR;           //控制狀態暫存器

} RCC_TypeDef;

控制上述時鐘的各個狀態就靠暫存器,任何MCU的控制最終都是暫存器的控制。
今天學的大概就這些,有一些自己的理解,有可能不對,歡迎大家指出。


相關文章