stm32跑马灯实验
7组GPIO的端口映射地址为:
#define GPIOA_BASE #define GPIOB_BASE #define GPIOC_BASE #define GPIOD_BASE #define GPIOE_BASE #define GPIOF_BASE #define GPIOG_BASE 使用时有如下定义: #define _GPIO #define _GPIOA #define _GPIOB #define _GPIOC #define _GPIOD
给个实例,比如我们要设置PORTC的11位为上拉输入,12位为推挽输出。代码如下: GPIOC->CRH&=0XFFF00FFF;//清掉这2个位原来的设置,同时也不影响其他位的设置 GPIOC->CRH|=0X00038000; //PC11输入,PC12输出 GPIOC->ODR=1<<11;//PC11上拉 通过这 3 句话的配置,我们就设置了 PC11 为上拉输入,PC12 为推挽输出。
1.LED 驱动 2.直接 GPIO 寄存器控制
硬件分析:
如上所示,4 个 LED 链接在 4 个不同管脚上,即 GPIOF6,GPIOF7,GPIOF8,GPIOC7. 当这 4 个管脚被置为低电平时,二极管导通。
通用输入输出接口(GPIO)介绍:
多达112多功能的双向IO口:80%的IO口利用率 所有的IO被分成7个端口,即7组GPIO口(GPIOA..GPIOG); 多达21路模拟输入; 可改变功能引脚(如:USARTx、TIMx、I2Cx、x、CAN、USB等); 多达112个IO口可以设置为外部中断(同时可最多可有16个); 一个IO口可用于将MCU从待机模式唤醒(PA.0); 一个IO口可用作防入侵引脚(PC.13); 标准的I/O口可承受5V; IO口可以吸收25mA(总共可吸收150mA); 18MHz翻转速度; 可设置输出速度达到50MHz; 使用BSRR和BRR寄存器可对IO口的位进行位设置或清除; 锁定机制可以避免对IO口的寄存器的误写操作: 每个GPIO引脚都可以由软件配置成输出(推挽或开漏)、输入(带或不带上拉或下拉)或复用的外设功能端口。 多数GPIO引脚都与数字或模拟的复用外设共用。 除了具有模拟输入功能的端口,所有的GPIO引脚都有大电流通过能力。 在需要的情况下,I/O引脚的外设功能可以通过一个特定的操作锁定,以避免意外的写入I/O寄存器。
I/O 口的输出模式下,有 3 种输出速度可选(GPIO_Speed_2MHz 最高输出速率 2MHz 、GPIO_Speed_10MHz 最高输 出速率 10MHz 和 GPIO_Speed_50MHz 最高输出速率 50MHz), 这个速度是指 I/O 口驱动电路的响应速度而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在 I/O 口 的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路)。 通过选择速度来选择不同的输出驱动模块,达到最佳的噪声 控制和降低功耗的目的。 高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的 EMI 性能。 如果要输出较高频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。 如: 对于串口,假如最大波特率只需 115.2k,那么用 2M 的 GPIO 的引脚速度就够了。
实验目的:
1.分析和学习固件库 2.理解固件库的结构 3.通过 stm32f10x_gpio.c/.h 文件,熟悉 GPIO 的控制和工作原理 4.对开发板 LED 灯的再次软件封装
实验要求:
1.利用原理图和固件库的实例,移植开发板 LED 灯的驱动程序,即自己创建一个 LED.c/.h 2.用两种方法实现跑马灯程序:
简单来说开漏是 0 的时候接 GND 1 的时候浮空 推挽是 0 的时候接 GND 1 的时候接 VCC
下表为端口模式配置表:
GPIO 寄存器使用
必须以字(32 位)的方式操作这些外设寄存器。
端口配置低寄存器(GPIOx_CRL) (x=A..E)
31:30, 27:26, 23:22, 19:18, 15:14, 11:10, 7:6, 3:2 位(CNFy)为:端口配置位(y = 0…7) (Port x configuration bits)
GPIO 寄存器工作模式
根据数据手册中列出的每个 I/O 端口的特定硬件特征, GPIO 端口的每个位可以由软件分别配置成多种模式。 共有以下 8 中模式可以选择: (1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING 浮空输入 (3)GPIO_Mode_IPD 下拉输入 (4)GPIO_Mode_IPU 上拉输入 这几种输入电路是用那一种,要根据外围电路来决定。 所谓高阻,可以简单理解为输出端处于浮空状态(没有电流流动),其电平随外部电平高低而定,即门电路放弃对 输出端电路的控制。而上拉就是将不确定的信号通过一个电阻嵌位在高电平,电阻同时起限流作用。下拉同理, 只不过上拉是对器件注入电流,下拉是输出电流。至于弱上拉和强上拉,只是上拉电阻的阻值不同,没有什么严 格区分。简言之,上拉就是在端口没有输入的情况下,将端口的电平稳定在高电平。 (5)GPIO_Mode_Out_OD 开漏输出 (6)GPIO_Mode_Out_PP 推挽输出 (7)GPIO_Mode_AF_OD 复用开漏输出 (8)GPIO_Mode_AF_PP 复用推挽输出
对于 I2C 接口,假如使用 400k 波特率,若想把余量留大些,那么用 2M 的 GPIO 的引脚速度或许不够,这时可以选 用 10M 的 GPIO 引脚速度。 对于 SPI 接口,假如使用 18M 或 9M 波特率,用 10M 的 GPIO 的引脚速度显然不够了,需要选用 50M 的 GPIO 的引脚 速度。 除此之外,使用端口设置时,有以下几点需要注意: GPIO 口设为输入时,输出驱动电路与端口是断开,所以输出速度配置无意义。 在复位期间和刚复位后,复用功能未开启,I/O 端口被配置成浮空输入模式。 所有端口都有外部中断能力。为了使用外部中断线,端口必须配置成输入模式。 GPIO 口的配置具有上锁功能,当配置好 GPIO 口后,可以通过程序锁住配置组合,直到下次芯片复位才能解锁。
在输入模式(MODE[1:0]=00)下: 00:模拟输入模式 01:浮空输入模式(复位后的状态) 10:上拉/下拉输入模式 11:保留 在输出模式(MODE[1:0]>00)下: 00:通用推挽输出模式 01:通用开漏输出模式 10:复用功能推挽输出模式 11:复用功能开漏输出模式
详见上面端口模式配置表
详见上面端口模式配置表
该寄存器的复位值为0X4444 4444,从上图可以看到,复位值其实就是配置端口为浮空输入模式。从上图还可 以得出:STM32的CRL控制着每个IO端口(A~G)的低8位的模式。每个IO端口的位占用CRL的4个位,高两位为 CNF,低两位为MODE。这里我们可以记住几个常用的配置,比如0X4表示模拟输入模式(ADC用)、0X3表示推 挽输出模式(做输出口用,50M速率)、0X8表示上/下拉输入模式(做输入口用)、0XB表示复用输出(使用IO口 的第二功能,50M速率)。
(APB2PERIPH_BASE + 0x0800) (APB2PERIPH_BASE + 0x0C00) (APB2PERIPH_BASE + 0x1000) (APB2PERIPH_BASE + 0x1400) (APB2PERIPH_BASE + 0x1800) (APB2PERIPH_BASE + 0x1C00) (APB2PERIPH_BASE + 0x2000)
在固件库中的定义如下所示: typedef enum {
GPIO_Mode_AIN = 0x0, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x28, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mode_Out_PP = 0x10, GPIO_Mode_AF_OD = 0x1C, GPIO_Mode_AF_PP = 0x18 }GPIOMode_TypeDef; 通常有 5 种方式使用某个引脚功能,它们的配置方式如下: 1.作为普通 GPIO 输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对 应的所有复用功能模块。 2.作为普通 GPIO 输出:根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模 块。 3.作为普通模拟输入:配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。 4.作为内置外设的输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应 的某个复用功能模块。 5.作为内置外设的输出:根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用 功能模块。
29:28, 25:24, 21:20, 17:16, 13:12, 9:8, 5:4, 1:0位(MODy)为:端口模式位(y = 8…15) (Port x mode bits) 00:输入模式(复位后的状态) 01:输出模式,最大速度10MHz 10:输出模式,最大速度2MHz 11:输出模式,最大速度50MHz
在固件库中定义如下: typedef struct {
__IO uint32_t CRL; __IO uint32_t CRH; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR;
__IO uint32_t BRR; __IO uint32_t LCKR; } GPIO_TypeDef; #ifdef _GPIOA GPIOA = (GPIO_TypeDef *) GPIOA_BASE; #endif /*_GPIOA */ #ifdef _GPIOB GPIOB = (GPIO_TypeDef *) GPIOB_BASE; #endif /*_GPIOB */ #ifdef _GPIOC GPIOC = (GPIO_TypeDef *) GPIOC_BASE; #endif /*_GPIOC */ #ifdef _GPIOD GPIOD = (GPIO_TypeDef *) GPIOD_BASE; #endif /*_GPIOD */ #ifdef _GPIOE GPIOE = (GPIO_TypeDef *) GPIOE_BASE; #endif /*_GPIOE */