微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > stm32的5组GPIO口

stm32的5组GPIO口

时间:10-02 整理:3721RD 点击:
stm32之GPIO[size=13.63636302948px]

  stm32有5组GPIO口,GPIOA  GPIOB  GPIOC  GPIOD  GPIOE

每个GPIO端口有:

    2个配置寄存器GPIOx_CRL, GPIOx_CRH(32位);

    2个数据寄存器GPIOx_IDR, GPIOx_ODR(32位);

    1个置位/复位寄存器GPIOx_BSRR(32位);

    1个复位寄存器GPIOx_BRR(16位);

    1个锁定寄存器GPIOx_LCKR(32位);

输入模式:

  —输入浮空:顾名思义也就是输入什么信号才是什么信号,对于浮空输入要保证有明确的输入信号。
  ─ 输入上拉:上拉输入模式:区别在于没有输入信号的时候默认输入高电平(因为有弱上拉)
  ─ 输入下拉:下拉输入模式:区别在于没有输入信号的时候默认输入低电平(因为有弱下拉)
  ─ 模拟输入:用于模拟量输入;仅仅拥有ADC

输出模式:

  ─ 开漏输出:随IO变化

  ─ 推挽式输出:推挽具有比较好的驱动能力。

  ─ 推挽式复用功能
  ─ 开漏复用功能

  1. #include "stm32f10x_gpio.h"

  2. int main()
  3. {
  4.    
  5.     //设置GPIOA的工作模式,何种输入方式、何种输出方式, 以及工作速率的设定;
  6. //      GPIOA->CRL = 0x33;
  7. //     //在相应引脚上设置相应电平
  8. //     GPIOA->ODR = 0x00; //输出低电平
  9. //     GPIOA->ODR = 0x03; //设置为1,0x0011,即第1位,第2位输出高电平,等同于51中的1;
  10.    
  11.     //设置GPIOA工作模式;
  12.     //PA0 设置为输出模式,50hz, PA8 设置为输入;
  13.     GPIOA->CRL = 0x03;   
  14.     GPIOA->CRH = 0X04;
  15.    
  16.     while(1)
  17.     {
  18.         if((GPIOA->ODR & 0x0100) ==0x0100)
  19.         {
  20.             GPIOA->ODR = 0x01;
  21.         }
  22.         else
  23.         {
  24.             GPIOA->ODR = 0x00;
  25.         }
  26.     }
  27.    
  28.     return 0;
  29. }

复制代码


[size=13.63636302948px]位绑定:即找到需要绑定的寄存器地址;选择具体的那个位(8位中的一位);

[size=13.63636302948px]  宏观看:就是将需要绑定的寄存器中的具体某一位映射到具体的一个32位的地址中,通过操作这个32位地址来操作寄存器的位;这样mcu运行更快;

[size=13.63636302948px]地址绑定公式:

[size=13.63636302948px]  SRAM区: 0x2000 0000 到 0x200f ffff 1M大小空间用于绑定作用;
    AliasAddr = 0x2200 0000 + ((A-0x2000 0000)*8 + n)*4     (n属于0~7,这点待确定;下面第二段代码有例子,)
           = 0x2200 0000 + (A-0x2000 0000)*32 + 4n
   此处A属于:0x2000 0000 到 0x200f ffff

[size=13.63636302948px]  片上外设: 0x4000 0000 ~ 0x400f ffff 1M大小;
    AliasAddr = 0x4200 0000 + ((A-0x4000 0000)*8+n)*4
           = 0x4200 0000 + (A-0x400 0000)*32 + 4*n
    此处A属于:0x4000 0000 到 0x400f ffff

[size=13.63636302948px]

  1. #include "stm32f10x_gpio.h"

  2. int main()
  3. {
  4.     //0x4200 0000 + ((A-0x4000 0000)*8+n)*4
  5.     u32 *PAO4 = (u32*)(0x42000000 + ((GPIOA_BASE+0x0C-0x40000000)*8+4)*4);
  6.     u32 *PAI12 = (u32*)(0x42000000 + ((GPIOA_BASE+0x09-0x40000000)*8+4)*4);
  7.     //设置GPIOA引脚上的工作模式,GPIOA: 0, GPIOA:1 推挽输出而不是复用输出, 工作速率:50hz;
  8. //      GPIOA->CRL = 0x33;
  9. //     //在相应引脚上设置相应电平;
  10. //     GPIOA->ODR = 0x00; //输出0
  11. //     GPIOA->ODR = 0x03; //设置11,输出高电平,而不再是单片机中1;
  12.    
  13.     //设置GPIOA工作模式;
  14.     //PA0 输出, 50hz,PA8  输入
  15.     GPIOA->CRL = 0x33333333;   
  16.     GPIOA->CRH = 0X44444444;
  17.    
  18.     while(1)
  19.     {
  20.         if(((GPIOA->IDR) & 0x0100) ==0x0100)  GPIOA->ODR = GPIOA->ODR | 0x01;
  21.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x01;
  22.         if(((GPIOA->IDR) & 0x0200) ==0x0200)  GPIOA->ODR = GPIOA->ODR | 0x02;
  23.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x02;
  24.         if(((GPIOA->IDR) & 0x0400) ==0x0400)  GPIOA->ODR = GPIOA->ODR | 0x04;
  25.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x04;

  26.         if(((GPIOA->IDR) & 0x0800) ==0x0800)  GPIOA->ODR = GPIOA->BSRR | 0x08;     //BSRR端口位设置/复位寄存器
  27.         else                                   GPIOA->ODR = GPIOA->BRR & ~0x08;     //    BRR端口位复位寄存器(GPIOx_BRR)
  28.          
  29.          //根据位绑定公式;
  30.          //A = GPIOA_BASE+IDR的偏移地址是GPIOA->IDR = GPIOA_BASE+0x08    n = 4;
  31.          // A = GPIOA_BASE+ODR的偏移地址是GPIOA->ODR = GPIOA_BASE+0x0C    n = 4;
  32.          //n=4 ,因为是GPIOA->ODR中的第四位(0x10,从0位开始算);
  33. //        if(((GPIOA->IDR) & 0x1000) ==0x1000)  *PAO4 = 1;        //GPIOA->ODR = GPIOA->ODR | 0x10;
  34. //        else                                   *PAO4 = 0;                    //GPIOA->ODR = GPIOA->ODR & ~0x10;
  35.         if(*PAI12 == 1) *PAO4 = 1;
  36.         else             *PAO4 = 0;


  37.         if(((GPIOA->IDR) & 0x2000) ==0x2000)  GPIOA->ODR = GPIOA->ODR | 0x20;
  38.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x20;   
  39.         if(((GPIOA->IDR) & 0x4000) ==0x4000)  GPIOA->ODR = GPIOA->ODR | 0x40;
  40.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x40;   
  41.         if(((GPIOA->IDR) & 0x8000) ==0x8000)  GPIOA->ODR = GPIOA->ODR | 0x80;
  42.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x80;   
  43.     }
  44.    
  45.     return 0;
  46. }

复制代码

使用#define(宏)强大功能优化代码:

  1. #include "stm32f10x_gpio.h"
  2. #define GPIOA_ODR_A (GPIOA_BASE+0x0C)
  3. #define GPIOA_IDR_A (GPIOA_BASE+0x08)
  4. #define GPIOA_ODR_B (GPIOB_BASE+0x0C)
  5. #define GPIOA_IDR_B (GPIOB_BASE+0x08)
  6. #define GPIOA_ODR_C (GPIOC_BASE+0x0C)
  7. #define GPIOA_IDR_C (GPIOC_BASE+0x08)
  8. #define GPIOA_ODR_D (GPIOD_BASE+0x0C)
  9. #define GPIOA_IDR_D (GPIOD_BASE+0x08)
  10. #define GPIOA_ODR_E (GPIOE_BASE+0x0C)
  11. #define GPIOA_IDR_E (GPIOE_BASE+0x08)

  12. //使用volatile关键字使得编译器不优化volatile关键字之后的代码;还有个其他功能待定
  13. #define BitBand(Addr, BitNum) *((volatile unsigned long *)((Addr&0xF0000000)+0x2000000 +((Addr&0xfffff)<<5)+(BitNum<<2)))
  14. #define PAout(n) BitBand(GPIOA_ODR_A, n)
  15. #define PAin(n)     BitBand(GPIOA_IDR_A, n)

  16. int main()
  17. {
  18.     //0x4200 0000 + ((A-0x4000 0000)*8+n)*4
  19.     u32 *PAO4 = (u32*)(0x42000000 + ((GPIOA_BASE+0x0C-0x40000000)*8+4)*4);
  20.     u32 *PAI12 = (u32*)(0x42000000 + ((GPIOA_BASE+0x09-0x40000000)*8+4)*4);
  21.     //设置GPIOA引脚上的工作模式,GPIOA: 0, GPIOA:1 推挽输出而不是复用输出, 工作速率:50hz;
  22. //      GPIOA->CRL = 0x33;
  23. //     //在相应引脚上设置相应电平;
  24. //     GPIOA->ODR = 0x00; //输出0
  25. //     GPIOA->ODR = 0x03; //设置11,输出高电平,而不再是单片机中1;
  26.    
  27.     //设置GPIOA工作模式;
  28.     //PA0 输出, 50hz,PA8  输入
  29.     GPIOA->CRL = 0x33333333;   
  30.     GPIOA->CRH = 0X44444444;
  31.    
  32.     while(1)
  33.     {
  34.         if(((GPIOA->IDR) & 0x0100) ==0x0100)  GPIOA->ODR = GPIOA->ODR | 0x01;
  35.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x01;
  36.         if(((GPIOA->IDR) & 0x0200) ==0x0200)  GPIOA->ODR = GPIOA->ODR | 0x02;
  37.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x02;
  38.         if(((GPIOA->IDR) & 0x0400) ==0x0400)  GPIOA->ODR = GPIOA->ODR | 0x04;
  39.         else                                   GPIOA->ODR = GPIOA->ODR & ~0x04;

  40.         if(((GPIOA->IDR) & 0x0800) ==0x0800)  GPIOA->ODR = GPIOA->BSRR | 0x08;     //BSRR端口位设置/复位寄存器
  41.         else                                   GPIOA->ODR = GPIOA->BRR & ~0x08;     //    BRR端口位复位寄存器(GPIOx_BRR)
  42.          
  43.          //根据位绑定公式;
  44.          //A = GPIOA_BASE+IDR的偏移地址是GPIOA->IDR = GPIOA_BASE+0x08    n = 4;
  45.          // A = GPIOA_BASE+ODR的偏移地址是GPIOA->ODR = GPIOA_BASE+0x0C    n = 4;
  46.          //n=4 ,因为是GPIOA->ODR中的第四位(0x10,从0位开始算);
  47. //        if(((GPIOA->IDR) & 0x1000) ==0x1000)  *PAO4 = 1;        //GPIOA->ODR = GPIOA->ODR | 0x10;
  48. //        else                                   *PAO4 = 0;                    //GPIOA->ODR = GPIOA->ODR & ~0x10;
  49.         if(*PAI12 == 1) *PAO4 = 1;
  50.         else             *PAO4 = 0;


  51. //        if(((GPIOA->IDR) & 0x2000) ==0x2000)  GPIOA->ODR = GPIOA->ODR | 0x20;
  52. //        else                                   GPIOA->ODR = GPIOA->ODR & ~0x20;   
  53. //        if(((GPIOA->IDR) & 0x4000) ==0x4000)  GPIOA->ODR = GPIOA->ODR | 0x40;
  54. //        else                                   GPIOA->ODR = GPIOA->ODR & ~0x40;   
  55. //        if(((GPIOA->IDR) & 0x8000) ==0x8000)  GPIOA->ODR = GPIOA->ODR | 0x80;
  56. //        else                                   GPIOA->ODR = GPIOA->ODR & ~0x80;   
  57.         if(PAin(13)==1) PAout(5)=1;
  58.         else             PAout(5)=0;
  59.          if(PAin(14)==1) PAout(6)=1;
  60.         else             PAout(6)=0;
  61.         if(PAin(15)==1) PAout(7)=1;
  62.         else             PAout(7)=0;
  63.     }
  64.    
  65.     return 0;
  66. }

复制代码




Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top