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 }

 

时间: 2024-09-20 00:36:51

stm32之GPIO的相关文章

stm32之GPIO(二)

输入上拉:当IO口作为输入时,比如按键输入,而按键是与地连接,按下时为低电平,则没按下时该IO口应为高电平,上拉即是该IO口通过一个电阻与电源相连,则没按下时为高电平,按下即为低电平.      输入下拉:同理此时按键与电源相连,按下即为高电平,下拉就是该IO口通过一个电阻与地相连,没按下为低电平,按下为高电平.        推挽输出:作为普通的IO口输出高低电平 STM32的输入输出管脚有下面8种可能的配置:(4输入.2输出.2复用输出) 1.浮空输入_IN_FLOATING 2.带上拉输入

STM32中GPIO的8种工作模式

一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定.形象点解释:推挽,就是有推有拉,任何时候IO口的电平都是确定的,不需要外接上拉或者下拉电阻.         推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小.效率高.输出既可以向负载灌电流,也可以从负载抽取电流.推拉式

stm32之GPIO库函数开发

关于GPIO库函数的重点函数:P122 GPIO_Init() :根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器: GPIO_ReadInputDataBit():读取指定端口管脚的输入: GPIO_SetBits():设置指定的数据端口位: GPIO_ResetBits(): 清除指定的数据端口位: GPIO_PinRemapConfig(): 改变指定管脚的映射:----------端口映射是很有特色的功能:也是重点知识 GPIO_EXTILineConfig():

STM32F4 输入输出(GPIO)模式理解

stm32的GPIO的配置模式有好几种,包括: 1. 模拟输入: 2. 浮空输入: 3. 上拉输入: 4. 下拉输入: 5. 开漏输出: 6. 推挽输出: 7. 复用开漏输出: 8. 复用推挽输出   如图是GPIO的结构原理图:     1.模拟输入   从上图我们可以看到,我觉得模拟输入最重要的一点就是,他不经过输入数据寄存器,所以我们无法通过读取输入数据寄存器来获取模拟输入的值,我觉得这一点也是很好理解的,因为输入数据寄存器中存放的不是0就是1,而模拟输入信号不符合这一要求,所以自然不能放

arm-STM32GPIO配置的问题??

问题描述 STM32GPIO配置的问题?? GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO宏操作结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB,ENABLE); //外设时钟配置, 开启GPIOB和GPIOD的时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_3; GPIO_InitStructure.G

STM32——GPIO之从库函数到寄存器的前因后果

例子为单片机的"Hello World"级的流水灯实验--虽然只有一个,其中并不是将完整的代码给出,只是给出关键部分来说明"如何调用ST公司的的库来完成对硬件的控制,以及对库文件代码进行跟踪和分析至寄存器级".所以从第一段代码往下看就可以了,要用到的函数和变量大部分会说明,至于寄存器级的,那就只能翻手册了. GPIO(General Purpose Input/Output) - 通用输入/输出  main.c :此函数为主函数,控制LED,亮1s,灭1s 1234

【STM32 .Net MF开发板学习-02】GPIO测试

示例很简单,主要是按钮和LED灯的测试,红牛和EM-STM3210E的按钮和LED有所不同,所以有针对性的对二者pin都做了定义(这些信息,你可以直接看开发板相对应的原理图,很容易就可以获得相关Pin脚的定义). 功能就是 LED每隔1s就亮灭一次,按相关按键,则从调试口输出按键信息. 核心代码如下: #define Redox //红牛开发板 using System; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using Sys

stm32-关于STM32引脚功能复用的问题

问题描述 关于STM32引脚功能复用的问题 1.STM32系列中的48引脚芯片有引脚复用功能吗?在看引脚说明时没有看见有复用的功能(以IIC为例),但是在某些地方又可以看到PB5/PB6/PB7和PB10/PB11/PB12对应为IIC复用功能,很矛盾,求解答. 2.另外,假如某几个引脚的确具有IIC复用功能,仅配置这几个引脚的GPIO性能,具体的时序等用软件实现,可以吗?比如说,PB5/6/7对应IIC功能,仅将这三个引脚的GPIO性能进行配置,时序通过翻转IO来实现,可以吗? 入行不深,提出

《STM32库开发实战指南:基于STM32F4》----导读

目 录 前 言第1章 如何安装KEIL51.1 温馨提示1.2 获取KEIL5安装包1.3 开始安装KEIL51.4 安装STM32芯片包第2章 如何用DAP仿真器下载程序2.1 仿真器简介2.2 硬件连接2.3 仿真器配置2.4 选择目标板2.5 下载程序第3章 初识STM323.1 什么是STM323.2 STM32能做什么3.2.1 智能手环3.2.2 微型四轴飞行器3.2.3 淘宝众筹3.3 STM32选型3.3.1 STM32分类3.3.2 STM32命名方法3.3.3 选择合适的MC