STM32F407VG IO位操作

/************************************
     標題:操作GPIO的練習
     軟件平臺:MDK-keil uvision v4.23
     硬件平臺:stm32f4-discovery
     主頻:168M    
     author:大舟
     data:2012-09-04
 *************************************/
 /*sys時鐘爲HSE頻率/PLL_M*PLL_N/PLL_P,定義HSE爲8M,則sys時鐘頻率爲168M */
 #include <stm32f4xx.h> 
 
 
 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))
 #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
 #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
 
 //F4XXIO 口地址映射
 #define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
 #define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
 #define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
 #define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
 #define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
 #define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414
 #define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
 #define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
 #define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
 
 #define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
 #define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
 #define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
 #define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
 #define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
 #define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
 #define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
 #define GPIOH_IDR_Addr (GPIOF_BASE+16) //0x40021C10
 #define GPIOI_IDR_Addr (GPIOG_BASE+16) //0x40022010
 
 //F4XXIO 口操作 , 只對單一的 IO 口 ,n 的值範圍 [0-15]
 #define GPIOAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) 	//GPIOA 某一位輸出
 #define GPIOAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) 	//GPIOA 某一位輸入
 #define GPIOBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) 	//GPIOB 某一位輸出
 #define GPIOBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) 	//GPIOB 某一位輸入
 #define GPIOCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) 	//GPIOC 某一位輸出
 #define GPIOCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) 	//GPIOC 某一位輸入
 #define GPIODout(n) BIT_ADDR(GPIOD_ODR_Addr,n) 	//GPIOD 某一位輸出
 #define GPIODin(n) BIT_ADDR(GPIOD_IDR_Addr,n) 	//GPIOD 某一位輸入
 #define GPIOEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) 	//GPIOE 某一位輸出
 #define GPIOEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) 	//GPIOE 某一位輸入
 #define GPIOFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) 	//GPIOF 某一位輸出
 #define GPIOFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) 	//GPIOF 某一位輸入
 #define GPIOGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) 	//GPIOG 某一位輸出
 #define GPIOGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) 	//GPIOG 某一位輸入
 #define GPIOHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) 	//GPIOH 某一位輸出
 #define GPIOHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) 	//GPIOH 某一位輸入
 #define GPIOIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) 	//GPIOI 某一位輸出
 #define GPIOIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) 	//GPIOI 某一位輸入
 /*************************************************************************/
 
 #define LED1 GPIODout(12) 	// 定義 LED1 爲 GPIOD_Pin_12
 #define LED2 GPIODout(13) 	// 定義 LED1 爲 GPIOD_Pin_13
 #define LED3 GPIODout(14) 	// 定義 LED1 爲 GPIOD_Pin_14
 #define LED4 GPIODout(15) 	// 定義 LED1 爲 GPIOD_Pin_15
 #define KEY1 GPIOAin(0) 	// 定義 KEY1 爲 GPIOC_Pin_0
 
 
 uint32_t Gb_TimingDelay;
 
 void Delay(uint32_t nTime);
 void LED_init(void);
 void key_init(void);
 void key_scan(void);
 
 int main (void)
 {   
 	SysTick_Config(SystemCoreClock / 1000); //設置systemtick一毫秒中斷  
 	RCC->APB2ENR |= (1<<14);  //使能syscfg時鐘
 	
 	LED_init();
 	key_init();
 //  LED1=1;		//LED燈亮
 	while(1)
 	{
 		//流水燈
 		LED1=!LED1;
 		LED2=!LED2;
 		LED3=!LED3;
 		LED4=!LED4;
 		Delay(1000);
 		
 		//按鍵掃描
 		key_scan();	
 	}
 }
 
 void LED_init(void)
 {
 	RCC->AHB1ENR |= 0x00000008; //使能GPIOD時鐘
 	
 	GPIOD->MODER &= 0x00FFFFFF; //設置PD12,13,14,15輸出
 	GPIOD->MODER |= 0x55000000; 
 	
 	GPIOD->OTYPER &= 0xFFFF0FFF; //設置PD12,13,14,15推輓輸出
 	
 	GPIOD->OSPEEDR &= 0x00FFFFFF; //PD12,13,14,15 速度100m
 	GPIOD->OSPEEDR |= 0xff000000;
 	
 	SYSCFG->CMPCR = 0x00000001; //使用IO補償單元,當GPIO速度超過50M的時候要考慮使用此設置
 	
 	GPIOD->PUPDR &= 0x00FFFFFF;  //PD12,13,14,15 無上拉無下拉
 }
 
 void key_init(void)
 {
 	RCC->AHB1ENR |= 0x00000001; //使能GPIOA時鐘
 	
 	GPIOA->MODER &= 0xFFFFFFFC; //設置PA0輸入
 	
 	GPIOA->PUPDR &= 0xFFFFFFFC; //設置PA0爲下拉,因爲PA0的輸入狀態爲1
 	GPIOA->PUPDR |= 0x00000002;	
 }
 
 void key_scan(void)
 {
 	if(KEY1==1) 	// 如果按鍵按下
 	{
 		Delay(10);	//去抖
 		if(KEY1==1)	// 如果按鍵按下
 		{
 			LED1=!LED1;	//LED燈亮
 			while(KEY1==1);//鬆手檢測
 		}
 	}
 }
 
 void Delay(uint32_t nTime)
 { 
   Gb_TimingDelay = nTime;
 
   while(Gb_TimingDelay != 0);
 }
 
 void SysTick_Handler(void)
 {
   if (Gb_TimingDelay != 0x00)
   { 
     Gb_TimingDelay--;
   }
 }
 


說明:以上程序是在以下兩個資料下修改而成的。

(1)“STM32F407VG用位帶別名區實現IO位操作例程”(楊年榮) http://wenku.baidu.com/view/4057a658804d2b160b4ec083.html

(2)“stm32f407學習之四————GPIO(操作寄存器)”  http://blog.csdn.net/w471176877/article/details/7957171

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章