自学STM32---GPIO

1、STM32有5组GPIO引脚,分别是GPIOA,GPIOB,GPIOC,GPIOD,GPIOE,每组GPIO有16个引脚。
2、每个引脚都有4个位来配置其端口,可以配置出不同的输入\输出模式
表1配置IO口输出方式

配置模式 CNF1 CNF2 M1  M0 

推挽式输出 0   0 1 1 50MHz速度

开漏输出 0 1   0   1 10MHz速度

复用推挽式输出 0 0 1 0 2MHz速度
复用开漏输出 1 1 1 1 50MHz速度
模拟输入 0 0   0    0
浮空输入 0 1   0    0
下拉输入 1 0   0   0  
上拉输入 1 1  0    0  

M0 M1 输出速度 0  1   10MHz ;   1     0   2MHz;   1     1   50MHz
3、GPIOA->CRL(32位) 是用来配置低8个引脚的,GPIOA->CRH(32位) 是用来配置高8个引脚的。配置方式见参考手册
4、GPIOA->IDR(32位,只用到低16位配置对应16个引脚)是用来配置端口输入数据寄存器的(外设->MCU)。
5、GPIOA->ODR(32位,只用到低16位配置对应16个引脚)是用来配置端口输出数据寄存器的(MCU->外设)。
6、用软件仿真的时候,如果在一个引脚给如一个高电平,只能在Pins相应的位打上√(看程序里的第3次课代码调试)
7、位运算主要有&  |  ~(取反)  <<  >>  ^(异或)  等操作,因为都是针对寄存器编程,寄存器的引脚状态就0和1,所以一般用位运算。STM32不同于51和其他单片机,它内部有集成了2个对位运算的寄存器(BSRR对某一位置1,BRR对某一位清0)。这样运算的速度快,代码量少,效率高出很多倍。(具体见GPIO程序第4节课的例子)。(位运算与或的作用,清0,置1,隐藏)。
8、位绑定 把某一位映射到内存地址上,对地址的最低位进行操作来把引脚这一位给置1和清0.
位n 映射 内存地址a
n = 0/1 a = 0 2 4 8(最低位为0)/1 3 5 7(最低位为1)
传统置1和清0需要3步完成,读  修改  写
只有STM32以下2个区的位才可以进行位绑定(可以看参考手册2.3节内存分布图)
SRAM区 0x2000 0000~ 0x200f ffff 1M(20位,2~20=1M)(n = 0~7,A=0x2000 0000~0x200f ffff)
公式:AliasAddr = 0x22000000 + ((A-0x2000 0000)*8 +n)*4
      = 0x22000000 + (A-0x2000 0000)*32 +n*4
片上外设 0x4000 0000~ 0x400f ffff 1M  (n = 0~31,A=0x4000 0000~0x400f ffff)
公式:AliasAddr = 0x42000000 + ((A-0x4000 0000)*8 +n)*4
      = 0x42000000 + (A-0x4000 0000)*32 +n*4
  例子:把GPIOA的6位作为输出,GPIOA的14位作为输入,用位绑定的方式对其进行位操作
//A = GPIOA_BASE + ODR偏移地址 = GPIOA_BASE + 0x0c      n = 6
//A = GPIOA_BASE + IDR偏移地址 = GPIOA_BASE + 0x08        n = 14
//AliasAddr = 0x42000000 + (A-0x4000 0000)*32 +n*4
u32 *PAO6 = (u32 *) (0x42000000 + (0x4001080c - 0x40000000)*32 + 6*4);0c为输出的偏移地址(手册),第6位n=6
u32 *PAI14 = (u32 *) (0x42000000 + (0x40010808 - 0x40000000)*32 + 14*4);08为输入的偏移地址(手册),第14位n=14

if (*PAI14 == 1) *PAO6 = 1;//1也可以换成其他的奇数,只要满足最低位为1
else *PAO6 = 0;//0也可以换成其他的偶数,只要满足最低位为0

/***通用位绑定GPIO端口****/
#define GPIOA_ODR_A  (GPIOA_BASE+0x0c)
#define GPIOA_IDR_A  (GPIOA_BASE+0x08)
#define GPIOA_ODR_B  (GPIOB_BASE+0x0c)
#define GPIOA_IDR_B  (GPIOB_BASE+0x08)
#define GPIOA_ODR_C  (GPIOC_BASE+0x0c)
#define GPIOA_IDR_C  (GPIOC_BASE+0x08)
#define GPIOA_ODR_D  (GPIOD_BASE+0x0c)
#define GPIOA_IDR_D  (GPIOD_BASE+0x08)
#define GPIOA_ODR_E  (GPIOE_BASE+0x0c)
#define GPIOA_IDR_E  (GPIOE_BASE+0x08)
位绑定的指定位的地址中的值 绑定的地址的类型    取地址最高位(2或4)   次高位   取低5位并*32    相应的位n*4
#define BitBand(Addr,BitNum) *(volatile unsigned long *)((Addr & 0xf0000000) + 0x2000000+ ((Addr & 0xfffff)<<5) + (BitNum<<2))
//在MCU运算处理器中,位运算比乘法运算要快(左移n等价于乘以2~n;右移n位等价于除以2~n),volatile关键字的作用是告诉编译器,这处的代码不需要
//去优化它,直接从源头处去读取就行了。

#define PAout(n)   BitBand(GPIOA_ODR_A,n)
#define PAin(n)    BitBand(GPIOA_IDR_A,n)
#define PBout(n)   BitBand(GPIOB_ODR_B,n)
#define PBin(n)    BitBand(GPIOB_IDR_B,n)
#define PCout(n)   BitBand(GPIOC_ODR_C,n)
#define PCin(n)    BitBand(GPIOC_IDR_C,n)
#define PDout(n)   BitBand(GPIOD_ODR_D,n)
#define PDin(n)    BitBand(GPIOD_IDR_D,n)
#define PEout(n)   BitBand(GPIOE_ODR_E,n)
#define PEin(n)    BitBand(GPIOE_IDR_E,n)

/****操作测试****/
if(PAin(14) == 1) PAout(6) = 1;
else PAout(6) = 0

你可能感兴趣的:(c,stm32)