打印
[STM32F1]

STM32F10x GPIO配置 之 位绑定

[复制链接]
2220|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
vigous1|  楼主 | 2015-3-30 10:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 vigous1 于 2015-3-30 10:45 编辑

对GPIO进行未绑定,好处:加快对位操作的速度。1、位绑定公式(操作不同地址区域的位,用下面不同的公式)

2、下面以GPIOA端口的配置进行讲解:




3、对少量位进行绑定的程序例举:
[objc] view plaincopy


  • /**************************************************************************************************
  • *  硬件平台: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 ;  
  • }  
沙发
vigous1|  楼主 | 2015-3-30 10:46 | 只看该作者
4、利用宏定义函数对大量的位进行位绑定的步骤:













使用特权

评论回复
板凳
vigous1|  楼主 | 2015-3-30 10:49 | 只看该作者

  • 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)  
  •   


使用特权

评论回复
地板
vigous1|  楼主 | 2015-3-30 10:49 | 只看该作者
  • /*----------------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 ;  
  • }  

使用特权

评论回复
5
周董| | 2015-3-30 11:04 | 只看该作者
谢谢楼主分享

使用特权

评论回复
6
lovecat2015| | 2015-3-30 16:36 | 只看该作者
发的这个太有帮助了,图文并茂,很容易理解
谢谢你了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

88

主题

427

帖子

15

粉丝