天天看點

STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。

對GPIO進行未綁定,好處:加快對位操作的速度。

1、位綁定公式(操作不同位址區域的位,用下面不同的公式)

STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。

2、下面以GPIOA端口的配置進行講解:

STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。

3、對少量位進行綁定的程式例舉:

/**************************************************************************************************
 *	硬體平台:STM32F103VC
 *	學習重點:GPIOx的位綁定
 *	實作功能:對于GPIOA端口的第八位輸出 跟随 高八位的輸入
 **************************************************************************************************/

 /*=============================================================================
 * 位綁定公式:
 * 1、SRAM區域 :0X2200 0000 ----0X200F FFFF
 *    Aliasaddr = 0X22000000 + ( A -0X20000000 )*32 + n*4
 * 2、片上外設區域 :0X4200 0000 ----0X400F FFFF
 *    Aliasaddr = 0X42000000 + ( A -0X40000000 )*32 + n*4
 * 參數解釋:
 *          Aliasaddr : 設定“端口GPIOx的第n位”的寄存器_相應位的實際位址
 *          A : 端口GPIOx的基位址(GPIOx_BASE) + 相應寄存器的偏移位址
 *          n : 配置的是相應寄存器的第n位
 * 寄存器的偏移位址 :CRL  CRH  IDR  ODR  BSRR  BRR  LCKR
 *                    00H  04H  08H  0CH  10H   14H  18H 
 =============================================================================*/


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"	  //包含了所有的頭檔案 它是唯一一個使用者需要包括在自己應用中的檔案,起到應用和庫之間界面的作用。
#include "stm32f10x_map.h"


/*-----------------------------------------------------------------------------------------------------------
 *将GPIOA的第3位作為輸出引腳,寄存器ODR的偏移位址為0X0C 
 *	A = GPIOA_BASE + 0X0C = (APB2PERIPH_BASE + 0X0800) + 0X0C = ((PERIPR_BASE + 0X1000) + 0X0800) + 0X0C
 *						  = ((0X40000000 + 0X1000) + 0X0800) + 0X0C	= 0X4001080C
 *	n = 3  (設定寄存器ODR的第3位)
 *  将GPIOA的第11位作為輸入引腳,寄存器IDR的偏移位址為0X08
 *	A = GPIOA_BASE + 0X08 = (APB2PERIPH_BASE + 0X0800) + 0X08 = ((PERIPR_BASE + 0X1000) + 0X0800) + 0X08
 *						  = ((0X40000000 + 0X1000) + 0X0800) + 0X08	= 0X40010808
 *	n = 11 (設定寄存器IDR的第11位)
 ------------------------------------------------------------------------------------------------------------*/

u32 *PAO0 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 0*4) ;
u32 *PAO1 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 1*4) ;
u32 *PAO2 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 2*4) ;
u32 *PAO3 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 3*4) ;
u32 *PAO4 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 4*4) ;
u32 *PAO5 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 5*4) ;
u32 *PAO6 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 6*4) ;
u32 *PAO7 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 7*4) ;

u32 *PAI8 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 8*4) ;
u32 *PAI9 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 9*4) ;
u32 *PAI10 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 10*4) ;
u32 *PAI11 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 11*4) ;
u32 *PAI12 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 12*4) ;
u32 *PAI13 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 13*4) ;
u32 *PAI14 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 14*4) ;
u32 *PAI15 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 15*4) ;

/* Private functions -----------------------------------------------------------------------------*/ 
/**************************************************************************************************
* Function Name  : main
* Description    : 從GPIOA.8-.16輸入一個電平信号,GPIOA.0-.7口分别将對應引腳輸入的電平信号輸出
* Input          : None
* Output         : None
* Return         : None
****************************************************************************************************/
int main(void)
{

	/*--------控制STM32引腳GPIOA.0 GPIOA.1推挽輸出高電平--------*/
	//1、設定GPIOA的引腳的工作模式,即配置寄存器GPIOA_CRL 、 GPIOA_CRH
		//GPIOA.0-.7推挽輸出,速度50MHZ , GPIOA.8-.16浮空輸入
		GPIOA->CRL = 0x33333333 ; // CNF0 = 00 MODE0 = 11
		GPIOA->CRH = 0x44444444 ; // CNF0 = 01 MODE0 = 00

	//2、配置寄存器GPIOA_ODR、GPIOA_IDR ,實作GPIOA.0輸出 跟随 GPIOA.8的輸入
	  	while(1)
	  	{	
		/*----------------------第0位----------------------*/
			if( *PAI8 == 1)	 //寄存器GPIOA->IDR的第8位為1,表示從在GPIOA.8口輸入了高電平
			{
				*PAO0 = 1 ;  //對寄存器GPIOA->ODR的第0位置一
			}
			else
			{
				*PAO0 = 0 ;	//對寄存器GPIOA->ODR的第0位清零
			}
		/*----------------------第1位----------------------*/
			if( *PAI9 == 1)	 //寄存器GPIOA->IDR的第9位為1,表示從在GPIOA.9口輸入了高電平
			{
				*PAO1 = 1 ;  //對寄存器GPIOA->ODR的第1位置一
			}
			else
			{
				*PAO1 = 0 ;	//對寄存器GPIOA->ODR的第1位清零
			}
		/*----------------------第2位----------------------*/
			if( *PAI10 == 1)	 //寄存器GPIOA->IDR的第10位為1,表示從在GPIOA.10口輸入了高電平
			{
				*PAO2 = 1 ;  //對寄存器GPIOA->ODR的第2位置一
			}
			else
			{
				*PAO2 = 0 ;	//對寄存器GPIOA->ODR的第2位清零
			}
		/*----------------------第3位----------------------*/
			if( *PAI11 == 1)	 //寄存器GPIOA->IDR的第11位為1,表示從在GPIOA.11口輸入了高電平
			{
				*PAO3 = 1 ;  //對寄存器GPIOA->ODR的第3位置一
			}
			else
			{
				*PAO3 = 0 ;	//對寄存器GPIOA->ODR的第3位清零
			}
		/*----------------------第4位----------------------*/
			if( *PAI12 == 1)	 //寄存器GPIOA->IDR的第12位為1,表示從在GPIOA.12口輸入了高電平
			{
				*PAO4 = 1 ;  //對寄存器GPIOA->ODR的第4位置一
			}
			else
			{
				*PAO4 = 0 ;	//對寄存器GPIOA->ODR的第4位清零
			}
		/*----------------------第5位----------------------*/
			if( *PAI13 == 1)	 //寄存器GPIOA->IDR的第13位為1,表示從在GPIOA.13口輸入了高電平
			{
				*PAO5 = 1 ;  //對寄存器GPIOA->ODR的第5位置一
			}
			else
			{
				*PAO5 = 0 ;	//對寄存器GPIOA->ODR的第5位清零
			}
		/*----------------------第6位----------------------*/
			if( *PAI14 == 1)	 //寄存器GPIOA->IDR的第14位為1,表示從在GPIOA.14口輸入了高電平
			{
				*PAO6 = 1 ;  //對寄存器GPIOA->ODR的第6位置一
			}
			else
			{
				*PAO6 = 0 ;	//對寄存器GPIOA->ODR的第6位清零
			}
		/*----------------------第7位----------------------*/
			if( *PAI15 == 1)	 //寄存器GPIOA->IDR的第15位為1,表示從在GPIOA.15口輸入了高電平
			{
				*PAO7 = 1 ;  //對寄存器GPIOA->ODR的第7位置一
			}
			else
			{
				*PAO7 = 0 ;	//對寄存器GPIOA->ODR的第7位清零
			}
		 
	  	}

		return 1 ;
}
           

4、利用宏定義函數對大量的位進行位綁定的步驟:

STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。
STM32F10x GPIO配置 之 位綁定對GPIO進行未綁定,好處:加快對位操作的速度。

5、對大量的位進行位綁定的程式例舉:

/**************************************************************************************************
 *	硬體平台:STM32F103VC
 *	學習重點:GPIOx的位綁定
 *	實作功能:對于GPIOA端口的第八位輸出 跟随 高八位的輸入
 **************************************************************************************************/

 /*=============================================================================
 * 位綁定公式:
 * 1、SRAM區域 :0X2200 0000 ----0X200F FFFF
 *    Aliasaddr = 0X22000000 + ( A -0X20000000 )*32 + n*4
 * 2、片上外設區域 :0X4200 0000 ----0X400F FFFF
 *    Aliasaddr = 0X42000000 + ( A -0X40000000 )*32 + n*4
 * 參數解釋:
 *          Aliasaddr : 設定“端口GPIOx的第n位”的寄存器_相應位的實際位址
 *          A : 端口GPIOx的基位址(GPIOx_BASE) + 相應寄存器的偏移位址
 *          n : 配置的是相應寄存器的第n位
 * 寄存器的偏移位址 :CRL  CRH  IDR  ODR  BSRR  BRR  LCKR
 *                    00H  04H  08H  0CH  10H   14H  18H 
 =============================================================================*/


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"	  //包含了所有的頭檔案 它是唯一一個使用者需要包括在自己應用中的檔案,起到應用和庫之間界面的作用。
#include "stm32f10x_map.h"


///*-----------------------------------------------------------------------------------------------------------
// *将GPIOA的第3位作為輸出引腳,寄存器ODR的偏移位址為0X0C 
// *	A = GPIOA_BASE + 0X0C = (APB2PERIPH_BASE + 0X0800) + 0X0C = ((PERIPR_BASE + 0X1000) + 0X0800) + 0X0C
// *						  = ((0X40000000 + 0X1000) + 0X0800) + 0X0C	= 0X4001080C
// *	n = 3  (設定寄存器ODR的第3位)
// *  将GPIOA的第11位作為輸入引腳,寄存器IDR的偏移位址為0X08
// *	A = GPIOA_BASE + 0X08 = (APB2PERIPH_BASE + 0X0800) + 0X08 = ((PERIPR_BASE + 0X1000) + 0X0800) + 0X08
// *						  = ((0X40000000 + 0X1000) + 0X0800) + 0X08	= 0X40010808
// *	n = 11 (設定寄存器IDR的第11位)
// ------------------------------------------------------------------------------------------------------------*/
//
//u32 *PAO0 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 0*4) ;
//u32 *PAO1 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 1*4) ;
//u32 *PAO2 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 2*4) ;
//u32 *PAO3 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 3*4) ;
//u32 *PAO4 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 4*4) ;
//u32 *PAO5 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 5*4) ;
//u32 *PAO6 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 6*4) ;
//u32 *PAO7 = (u32 *)(0X42000000 + (0X4001080C - 0X40000000)*32 + 7*4) ;
//
//u32 *PAI8 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 8*4) ;
//u32 *PAI9 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 9*4) ;
//u32 *PAI10 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 10*4) ;
//u32 *PAI11 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 11*4) ;
//u32 *PAI12 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 12*4) ;
//u32 *PAI13 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 13*4) ;
//u32 *PAI14 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 14*4) ;
//u32 *PAI15 = (u32 *)(0X42000000 + (0X40010808 - 0X40000000)*32 + 15*4) ;

/******************************快速位綁定**********************************************************/
/*----------------1、宏定義要操作的寄存器位址---------------------------------------------*/
 #define GPIOA_ODR (GPIOA_BASE + 0X0C)
 #define GPIOA_IDR (GPIOA_BASE + 0X08)

 #define GPIOB_ODR (GPIOB_BASE + 0X0C)
 #define GPIOB_IDR (GPIOB_BASE + 0X08)

 #define GPIOC_ODR (GPIOC_BASE + 0X0C)
 #define GPIOC_IDR (GPIOC_BASE + 0X08)

 #define GPIOD_ODR (GPIOD_BASE + 0X0C)
 #define GPIOD_IDR (GPIOD_BASE + 0X08)

 #define GPIOE_ODR (GPIOE_BASE + 0X0C)
 #define GPIOE_IDR (GPIOE_BASE + 0X08)

/*----------------2、擷取端口GPIOx(A-E)的對應寄存器的某一操作位的位位址-------------------*/
// #define BitBand(Addr , BitNum) *( (volatile unsigned long *)(Addr & 0xf0000000) + 0x2000000 + ((Addr&0xfffff)*32) + (BitNum*4) ) 
// 因為 左移、右移 語句的執行速度比乘除法語句的運動速度快,是以将上述語句改成如下方式
 #define BitBand(Addr , BitNum) *( (volatile unsigned long *)( (Addr & 0xf0000000) + 0x2000000 + ((Addr&0xfffff)<<5) + (BitNum<<2) ) ) 
  
/*----------------3、宏定義函數,對固定的位綁定 進行功能封裝------------------------------*/
 #define PAout(n) BitBand(GPIOA_ODR , n) 
 #define PAin(n) BitBand(GPIOA_IDR , n)

 #define PBout(n) BitBand(GPIOB_ODR , n) 
 #define PBin(n) BitBand(GPIOB_IDR , n)

 #define PCout(n) BitBand(GPIOC_ODR , n) 
 #define PCin(n) BitBand(GPIOC_IDR , n)

 #define PDout(n) BitBand(GPIOD_ODR , n) 
 #define PDin(n) BitBand(GPIOD_IDR , n)

 #define PEout(n) BitBand(GPIOE_ODR , n) 
 #define PEin(n) BitBand(GPIOE_IDR , n)



/* Private functions -----------------------------------------------------------------------------*/ 
/**************************************************************************************************
* Function Name  : main
* Description    : 從GPIOA.8-.16輸入一個電平信号,GPIOA.0-.7口分别将對應引腳輸入的電平信号輸出
* Input          : None
* Output         : None
* Return         : None
****************************************************************************************************/
int main(void)
{

	/*--------控制STM32引腳GPIOA.0 GPIOA.1推挽輸出高電平--------*/
	//1、設定GPIOA的引腳的工作模式,即配置寄存器GPIOA_CRL 、 GPIOA_CRH
		//GPIOA.0-.7推挽輸出,速度50MHZ , GPIOA.8-.16浮空輸入
		GPIOA->CRL = 0x33333333 ; // CNF0 = 00 MODE0 = 11
		GPIOA->CRH = 0x44444444 ; // CNF0 = 01 MODE0 = 00

	//2、配置寄存器GPIOA_ODR、GPIOA_IDR ,實作GPIOA.0輸出 跟随 GPIOA.8的輸入
	  	while(1)
	  	{	
		/*----------------------第0位----------------------*/
			if( PAin(8) == 1)	 //寄存器GPIOA->IDR的第8位為1,表示從在GPIOA.8口輸入了高電平
			{
				PAout(0) = 1 ;  //對寄存器GPIOA->ODR的第0位置一
			}
			else
			{
				PAout(0) = 0 ;	//對寄存器GPIOA->ODR的第0位清零
			}
		/*----------------------第1位----------------------*/
			if( PAin(9) == 1)	 //寄存器GPIOA->IDR的第9位為1,表示從在GPIOA.9口輸入了高電平
			{
				PAout(1) = 1 ;  //對寄存器GPIOA->ODR的第1位置一
			}
			else
			{
				PAout(1) = 0 ;	//對寄存器GPIOA->ODR的第1位清零
			}
		/*----------------------第2位----------------------*/
			if( PAin(10) == 1)	 //寄存器GPIOA->IDR的第10位為1,表示從在GPIOA.10口輸入了高電平
			{
				PAout(2) = 1 ;  //對寄存器GPIOA->ODR的第2位置一
			}
			else
			{
				PAout(2) = 0 ;	//對寄存器GPIOA->ODR的第2位清零
			}
		/*----------------------第3位----------------------*/
			if( PAin(11) == 1)	 //寄存器GPIOA->IDR的第11位為1,表示從在GPIOA.11口輸入了高電平
			{
				PAout(3) = 1 ;  //對寄存器GPIOA->ODR的第3位置一
			}
			else
			{
				PAout(3) = 0 ;	//對寄存器GPIOA->ODR的第3位清零
			}
		/*----------------------第4位----------------------*/
			if( PAin(12) == 1)	 //寄存器GPIOA->IDR的第12位為1,表示從在GPIOA.12口輸入了高電平
			{
				PAout(4) = 1 ;  //對寄存器GPIOA->ODR的第4位置一
			}
			else
			{
				PAout(4) = 0 ;	//對寄存器GPIOA->ODR的第4位清零
			}
		/*----------------------第5位----------------------*/
			if( PAin(13) == 1)	 //寄存器GPIOA->IDR的第13位為1,表示從在GPIOA.13口輸入了高電平
			{
				PAout(5) = 1 ;  //對寄存器GPIOA->ODR的第5位置一
			}
			else
			{
				PAout(5) = 0 ;	//對寄存器GPIOA->ODR的第5位清零
			}
		/*----------------------第6位----------------------*/
			if( PAin(14) == 1)	 //寄存器GPIOA->IDR的第14位為1,表示從在GPIOA.14口輸入了高電平
			{
				PAout(6) = 1 ;  //對寄存器GPIOA->ODR的第6位置一
			}
			else
			{
				PAout(6) = 0 ;	//對寄存器GPIOA->ODR的第6位清零
			}
		/*----------------------第7位----------------------*/
			if( PAin(15) == 1)	 //寄存器GPIOA->IDR的第15位為1,表示從在GPIOA.15口輸入了高電平
			{
				PAout(7) = 1 ;  //對寄存器GPIOA->ODR的第7位置一
			}
			else
			{
				PAout(7) = 0 ;	//對寄存器GPIOA->ODR的第7位清零
			}
		 
	  	}

		return 1 ;
}
           

繼續閱讀