• stm32之GPIO


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

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

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

    地址绑定公式:

      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

      片上外设: 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

     1 #include "stm32f10x_gpio.h"
     2 
     3 int main()
     4 {
     5     //0x4200 0000 + ((A-0x4000 0000)*8+n)*4
     6     u32 *PAO4 = (u32*)(0x42000000 + ((GPIOA_BASE+0x0C-0x40000000)*8+4)*4);
     7     u32 *PAI12 = (u32*)(0x42000000 + ((GPIOA_BASE+0x09-0x40000000)*8+4)*4);
     8     //设置GPIOA引脚上的工作模式,GPIOA: 0, GPIOA:1 推挽输出而不是复用输出, 工作速率:50hz;
     9 //      GPIOA->CRL = 0x33;
    10 //     //在相应引脚上设置相应电平;
    11 //     GPIOA->ODR = 0x00; //输出0
    12 //     GPIOA->ODR = 0x03; //设置11,输出高电平,而不再是单片机中1;
    13     
    14     //设置GPIOA工作模式;
    15     //PA0 输出, 50hz,PA8  输入
    16     GPIOA->CRL = 0x33333333;    
    17     GPIOA->CRH = 0X44444444;
    18     
    19     while(1)
    20     {
    21         if(((GPIOA->IDR) & 0x0100) ==0x0100)  GPIOA->ODR = GPIOA->ODR | 0x01;
    22         else                                   GPIOA->ODR = GPIOA->ODR & ~0x01;
    23         if(((GPIOA->IDR) & 0x0200) ==0x0200)  GPIOA->ODR = GPIOA->ODR | 0x02;
    24         else                                   GPIOA->ODR = GPIOA->ODR & ~0x02;
    25         if(((GPIOA->IDR) & 0x0400) ==0x0400)  GPIOA->ODR = GPIOA->ODR | 0x04;
    26         else                                   GPIOA->ODR = GPIOA->ODR & ~0x04;
    27 
    28         if(((GPIOA->IDR) & 0x0800) ==0x0800)  GPIOA->ODR = GPIOA->BSRR | 0x08;     //BSRR端口位设置/复位寄存器
    29         else                                   GPIOA->ODR = GPIOA->BRR & ~0x08;     //    BRR端口位复位寄存器(GPIOx_BRR)
    30          
    31          //根据位绑定公式;
    32          //A = GPIOA_BASE+IDR的偏移地址是GPIOA->IDR = GPIOA_BASE+0x08    n = 4;
    33          // A = GPIOA_BASE+ODR的偏移地址是GPIOA->ODR = GPIOA_BASE+0x0C    n = 4;
    34          //n=4 ,因为是GPIOA->ODR中的第四位(0x10,从0位开始算);
    35 //        if(((GPIOA->IDR) & 0x1000) ==0x1000)  *PAO4 = 1;        //GPIOA->ODR = GPIOA->ODR | 0x10;
    36 //        else                                   *PAO4 = 0;                    //GPIOA->ODR = GPIOA->ODR & ~0x10;
    37         if(*PAI12 == 1) *PAO4 = 1;
    38         else             *PAO4 = 0;
    39 
    40 
    41         if(((GPIOA->IDR) & 0x2000) ==0x2000)  GPIOA->ODR = GPIOA->ODR | 0x20;
    42         else                                   GPIOA->ODR = GPIOA->ODR & ~0x20;    
    43         if(((GPIOA->IDR) & 0x4000) ==0x4000)  GPIOA->ODR = GPIOA->ODR | 0x40;
    44         else                                   GPIOA->ODR = GPIOA->ODR & ~0x40;    
    45         if(((GPIOA->IDR) & 0x8000) ==0x8000)  GPIOA->ODR = GPIOA->ODR | 0x80;
    46         else                                   GPIOA->ODR = GPIOA->ODR & ~0x80;    
    47     }
    48     
    49     return 0;
    50 }

     使用#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 17 int main() 18 { 19 //0x4200 0000 + ((A-0x4000 0000)*8+n)*4 20 u32 *PAO4 = (u32*)(0x42000000 + ((GPIOA_BASE+0x0C-0x40000000)*8+4)*4); 21 u32 *PAI12 = (u32*)(0x42000000 + ((GPIOA_BASE+0x09-0x40000000)*8+4)*4); 22 //设置GPIOA引脚上的工作模式,GPIOA: 0, GPIOA:1 推挽输出而不是复用输出, 工作速率:50hz; 23 // GPIOA->CRL = 0x33; 24 // //在相应引脚上设置相应电平; 25 // GPIOA->ODR = 0x00; //输出0 26 // GPIOA->ODR = 0x03; //设置11,输出高电平,而不再是单片机中1; 27 28 //设置GPIOA工作模式; 29 //PA0 输出, 50hz,PA8 输入 30 GPIOA->CRL = 0x33333333; 31 GPIOA->CRH = 0X44444444; 32 33 while(1) 34 { 35 if(((GPIOA->IDR) & 0x0100) ==0x0100) GPIOA->ODR = GPIOA->ODR | 0x01; 36 else GPIOA->ODR = GPIOA->ODR & ~0x01; 37 if(((GPIOA->IDR) & 0x0200) ==0x0200) GPIOA->ODR = GPIOA->ODR | 0x02; 38 else GPIOA->ODR = GPIOA->ODR & ~0x02; 39 if(((GPIOA->IDR) & 0x0400) ==0x0400) GPIOA->ODR = GPIOA->ODR | 0x04; 40 else GPIOA->ODR = GPIOA->ODR & ~0x04; 41 42 if(((GPIOA->IDR) & 0x0800) ==0x0800) GPIOA->ODR = GPIOA->BSRR | 0x08; //BSRR端口位设置/复位寄存器 43 else GPIOA->ODR = GPIOA->BRR & ~0x08; // BRR端口位复位寄存器(GPIOx_BRR) 44 45 //根据位绑定公式; 46 //A = GPIOA_BASE+IDR的偏移地址是GPIOA->IDR = GPIOA_BASE+0x08 n = 4; 47 // A = GPIOA_BASE+ODR的偏移地址是GPIOA->ODR = GPIOA_BASE+0x0C n = 4; 48 //n=4 ,因为是GPIOA->ODR中的第四位(0x10,从0位开始算); 49 // if(((GPIOA->IDR) & 0x1000) ==0x1000) *PAO4 = 1; //GPIOA->ODR = GPIOA->ODR | 0x10; 50 // else *PAO4 = 0; //GPIOA->ODR = GPIOA->ODR & ~0x10; 51 if(*PAI12 == 1) *PAO4 = 1; 52 else *PAO4 = 0; 53 54 55 // if(((GPIOA->IDR) & 0x2000) ==0x2000) GPIOA->ODR = GPIOA->ODR | 0x20; 56 // else GPIOA->ODR = GPIOA->ODR & ~0x20; 57 // if(((GPIOA->IDR) & 0x4000) ==0x4000) GPIOA->ODR = GPIOA->ODR | 0x40; 58 // else GPIOA->ODR = GPIOA->ODR & ~0x40; 59 // if(((GPIOA->IDR) & 0x8000) ==0x8000) GPIOA->ODR = GPIOA->ODR | 0x80; 60 // else GPIOA->ODR = GPIOA->ODR & ~0x80; 61 if(PAin(13)==1) PAout(5)=1; 62 else PAout(5)=0; 63 if(PAin(14)==1) PAout(6)=1; 64 else PAout(6)=0; 65 if(PAin(15)==1) PAout(7)=1; 66 else PAout(7)=0; 67 } 68 69 return 0; 70 }
  • 相关阅读:
    考拉兹猜想,100万以内的数
    给任意a、b、c三个数作为边盘都是否能构成三角形
    计数算法-对200万考生的成绩就行排序
    冒泡排序
    插入排序
    Echarts
    vue+tinymce
    java RestTemplate.postForObject请求传参
    java计算今天起后7天时间 +昨天八点+今天前7天的日期
    layui+echarts+动态数据
  • 原文地址:https://www.cnblogs.com/chris-cp/p/3901645.html
Copyright © 2020-2023  润新知