案例說明stm32官方庫函數使用方法 (庫版本v3.5, Keil MDK 5)

相關文件下載:於文章最後

stm32的官方庫非常方便,但是裏面的使用手冊是英文的,而且也沒有很詳細的使用說明,對新手來說入門比較困難,而且網上現存的教程要麼是針對v2.x的庫的,要麼是針對keil 4.x的,這兩個東西更新後差別都蠻大。有新的可用爲何不用最新的呢?

一: 用keil 5構建模板工程。在keil頂部選Project->New uVision Project, 輸入工程名稱,進入device選擇界面。注意,因爲keil 5變成了在線安裝Package的模式(即剛安裝好軟件並不附帶各種芯片的包,用哪個下哪個),如果你已經安裝了ST的Package,不要用那個Package!!Keil 5暫時不兼容官方庫,如果用了的話編譯會報錯。解決方案:1.使用附帶的ARM - ARM Cortex M3    2.如果還不行就下載我這個吧,下載好之後模板就全部構建完成了。

在你想要創建工程的文件夾下創建三個文件夾:Library、Project和Output,把剛纔創建的工程所有文件剪切進Project文件夾。好了之後,我們需要添加庫函數文件。解壓庫函數包,把解壓目錄下Library文件夾中的CM3文件夾和STM32F10x_StdPeriph_Driver文件夾複製到工程目錄下Library文件夾下,把標準庫目錄下的:STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_Std Periph_Template文件夾下的main.c、stm32f10x_conf.h、stm32f10x_it.h、 stm32f10x_it.c 拷貝到你的工程\Project目錄下。

用keil打開你剛纔創建的工程,右鍵點擊Source Group->Manage Project Item

把Groups改成下圖這樣:

然後選擇STARTUP,點擊右下方的Add Files,添加startup_stm32f10x_md.s ( . Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm

),注意後綴,.s爲彙編文件。(具體添加哪一個需要根據你的板載芯片來定,我的芯片Flash是128k的,屬於MD,因此添加startup_stm32f10x_md.s,若爲256k,則應添加startup_stm32f10x_hd.s,其他請參見官方文件進行選擇)然後選擇Library,在library組裏面添加 “Libraries\STM32F10x_StdPeriph_Driver\src”裏面的全部文件 。

再選擇CMSIS,添加Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x”路徑下的 system_stm32f10x.c文件,以及Libraries\CMSIS\CM3\CoreSupport下的core_cm3.c 文件。注意,除了了一個.s文件外,只添加.c即可,不需要添加.h。
添加完之後是這個樣子(剛添加完沒每個文件前有那個加號,編譯一次之後就有了):

 添加完之後還不能編譯,因爲此時Keil還是從默認的路徑去尋找要包括的頭文件,肯定是找不到的,因此我們要更改一下路徑設置,點擊魔棒按鈕:

點上面C/C++那一欄,點開之後下面有一個Include Paths,點開,修改成下圖這樣

就是從庫函數存放的位置尋找頭文件。根據庫函數的聲明,我們需要根據自己不同的芯片uncomment掉相應的註釋。庫函數stm32f10x.h原話如下: 

但大家可以試一下,修改這個文件是修改不了的,因爲它是隻讀的。一種做法是找到這個文件之後右鍵勾掉只讀選項再修改,但這種做法太麻煩。Keil提供了一個宏定義的功能,我們只需要在剛纔C/C++選項框那裏Define欄寫上相應代號就行了,相同的還有USE_STDPERIPH_DRIVER, 定義這個才能使用外設庫。在Define欄輸入USE_STDPERIPH_DRIVER,STM32F10X_MD。

這就相當於在程序中寫:#define USE_STDPERIPH_DRIVER

#define STM32F10X_MD

省事很多。

還有在Output選項卡中勾選Create HEX File, 點Select Folder for Objects,選擇你建立的Output文件夾(這樣所有的生成文件都在Output下,方便管理)。至此,構建就完成了。

大家寫程序只需要在main.c中寫就行,那麼如何引用庫函數呢?只需要在main開頭寫一句include “stm32f10x.h”就可以了,這樣就已經包含進了所需的所有庫函數。

現在可以編譯一下試一下。如果失敗,那麼可能有兩種原因,一是你操作的過 程失誤,重新來一下;二是keil5提供的devices還是不兼容,剛纔建立工程的時候大家選擇的是ARM - ARM Cortex M3 ,其實應該什麼都不選的,但什麼都不選工程無法建立,那大家可以通過直接下載我的這個工程來規避這個問題。

 

下面解釋一下在Project文件夾下剛纔複製進的幾個文件:

1.stm32f10x_conf.h文件:該文件不需要手動添加進工程,會自動添加。打開之後會發現,該文件就是include了各種外設的頭文件。我們需要用那個,就保留哪個include即可,其他可以刪掉或註釋掉。默認是全部包含,當然我們不去改動也完全可以。

2.stm32f10x_it.c文件:這個文件包含了所要使用的中斷,如果有的話加入即可。

 

大家可以注意到解壓開庫函數zip之後有一個chm文件,那個就是官方固件庫文檔,使用很方便,用哪個查哪個即可,不過當然是全英文。

這裏舉幾個例子說明如何使用這個文檔吧,以按鍵控制LED爲例。

首先一定要仔細讀這個文檔首頁的幾個鏈接的內容。看完之後,我們首先明白使用GPIO,就要先用PPP_InitTypeDef函數定義相應結構體,

GPIO_InitTypeDef GPIO_InitStruct;

然後使能對應的時鐘,即RCC。用哪個函數呢?打開文檔,選擇Modules-STM32F10x_Periph_Driver-RCC-RCC_Exported_Functions,這個就是RCC相關的函數了,通過硬件原理圖我們可以發現GPIO使用的是APB2時鐘,因此就是這個函數了:

 該函數參數:

因此我們寫成:

RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE ) ;

就是這樣,其他的函數使用方法和這個大同小異。

同時,大家也要下載官方硬件的Reference Manual,代號RM0008,可以到我個人網頁中下載。推薦仔細閱讀前幾個章節,後面的需要用那個讀哪個。

案例程序main.c:

/*************************************************************
 *       		 作者:Alan Zhao			     *
 *       		 博客:alanzjl.sinaapp.com	     *
 *        	CSDN博客:http://blog.csdn.net/alanzjl	     *
 *************************************************************
 *    針腳說明:Key1-PA0,Key2-PA1,LED1-PA2,LED2-PB2,LED3-PA3  *
 *************************************************************
*/
#include "stm32f10x.h"

enum{LED1,LED2,LED3}LED;
enum{Key1,Key2}Key;

void delay(int nms){			//延時
	for(;nms>=0;nms--){
		int n;
		for(n=1200;n>=0;n--);
	}
}

void LED_Init(GPIO_TypeDef* Pin_Mode, uint16_t pin){	//LED初始化
		GPIO_InitTypeDef GPIOInitStructure;
		if(Pin_Mode == GPIOA)		//由於LED1和LED3爲PA,LED2爲PB,因此此處需判斷
			RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
		else if(Pin_Mode == GPIOB)
			RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
		GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
		GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz;
		GPIOInitStructure.GPIO_Pin = pin;
		GPIO_Init(Pin_Mode,&GPIOInitStructure);
}

void Key_Init(uint16_t pin){				//按鍵初始化
		GPIO_InitTypeDef GPIO_InitStruct;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
		GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
		GPIO_InitStruct.GPIO_Pin = pin;
		//GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;	
		GPIO_Init (GPIOA,&GPIO_InitStruct);
}

int Keyscan(uint16_t pin){			//鍵盤掃描 pin爲按鍵管腳
		uint8_t status;
		status=GPIO_ReadInputDataBit(GPIOA,pin);	//讀取按鍵狀態,0爲按下
		if(status==0){
			return 1;
		}
		else
			return 0;
}

void LED_ON(LED){				//開燈函數
		if(LED==LED1){
				GPIOA->BRR=GPIO_Pin_2;
		}
		else if(LED==LED2){
				GPIOB->BRR=GPIO_Pin_2;
		}
		else if(LED==LED3){
				GPIOA->BRR=GPIO_Pin_3;
		}
		return;
}

void LED_OFF(LED){					//關燈函數
		if(LED==LED1){
				GPIOA->BSRR=GPIO_Pin_2;
		}
		else if(LED==LED2){
				GPIOB->BSRR=GPIO_Pin_2;
		}
		else if(LED==LED3){
				GPIOA->BSRR=GPIO_Pin_3;
		}
		return;
}
/****************************************************************/

int main(void){

		LED_Init(GPIOA,GPIO_Pin_3);
		LED_Init(GPIOA,GPIO_Pin_2);
		LED_Init(GPIOB,GPIO_Pin_2);
		Key_Init(GPIO_Pin_0);
		Key_Init(GPIO_Pin_1);

		LED_OFF(LED1);			//初始化時全部關燈
		LED_OFF(LED2);
		LED_OFF(LED3);

		while(1){
				LED_ON(LED2);
				delay(1000);
				LED_OFF(LED2);
				delay(1000);			//LED2不停閃爍
				if(Keyscan(GPIO_Pin_0)){							
						delay(200);	//去抖動
						if(Keyscan(GPIO_Pin_0)){
								while(Keyscan(GPIO_Pin_0));
								GPIOA->ODR ^= GPIO_Pin_2;				//燈狀態取反
						}
				}
				if(Keyscan(GPIO_Pin_1)){
						delay(200);			//去抖動
						if(Keyscan(GPIO_Pin_1)){
								while(Keyscan(GPIO_Pin_1));
								GPIOA->ODR ^= GPIO_Pin_3;   //燈狀態取反
						}
				}
		}

}


相關文件下載:STM32官方固件庫v3.5     http://download.csdn.net/detail/alanzjl/8638291

STM32官方固件庫v3.5模板工程    http://download.csdn.net/detail/alanzjl/8638303




發佈了31 篇原創文章 · 獲贊 14 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章