Understanding the STM32F0's GPIO
Understanding the STM32F0's GPIO
This is the first part of the GPIO tutorial for the STM32F0Discovery.
The tutorial will include the following topics:
- Understanding the Structure of the GPIO Registers on the STM32F0 Microcontroller
- Understanding how to access the registers
- Setting and clearing output pins
The STM32F051 microcontroller on the STM32F0Discovery board
has 5 general purpose input/output (GPIO) ports named Port A, B, C, D and F.
Each port can have up to 16 pins, and each port has associated with it the following set of registers:
- GPIO port mode register (GPIOx_MODER)
- GPIO port output type register (GPIOx_OTYPER)
- GPIO port output speed register (GPIOx_OSPEEDR)
- GPIO port pull-up/pull-down register (GPIOx_PUPDR)
- GPIO port input data register (GPIOx _IDR)
- GPIO port outp ut data register (GPIOx_ODR)
- GPIO port bit set/reset register (GPIOx _BSRR)
- GPIO port configuration lock register (GPIOx_LCKR)
- GPIO alternate function low register (GPI Ox_AFRL)
- GPIO alternate function high register (GPIOx_AFRH)
- GPIO Port bit reset register (GPIOx_BRR)
where the 'x' in each register name acronym represents the port i.e.
the GPIOx_MODER associated with port A is called GPIOA_MODER.
Let's take a closer look at each register:
GPIO port mode register (GPIOx_MODER)
This is a 32-bit register where each set of two consecutive bits represent the mode of a single I/O pin.
For example bits 0 and 1 of the MODER register associated with GPIOC (GPIOC_MODER),
represent the mode of GPIO pin PC0 and bits 26 and 27 of the same register represent the mode of GPIO pin PC13.
These two bits can be set to:
- '00'-> input mode, which allows the GPIO pin to be used as an input pin,
- '01'-> Output mode, which allows the GPIO pin to be used as an output pin,
- '11'-> Analog mode, which allows the GPIO pin to be used as an Analog input pin and finally,
- '10'-> Alternate function mode which allow the GPIO pins to be used by peripherals such as the UART, SPI e.t.c.
It is important to note that if a pin's MODE is set to alternate function,
any GPIO settings for that pin in the GPIO registers will be overridden by the peripheral.
GPIO port output type register (GPIOx_OTYPER)
This is a 16-bit register where each bit denotes the 'type' of a single pin in the register.
This register sets the type of output pins to either push-pull or open drain.
For example if pin PC7 is configured as an output pin,
clearing bit 7 (or leaving its state at zero) of the OTYPER register associated with GPIOC (GPIOC_TYPER),
will set the output type of the GPIO output pin PC7 to "Push-Pull".
- GPIO port output speed register (GPIOx_OSPEEDR)
This is a 32-bit register where each set of two bits represent the speed of a single output pin.
For example bits 0 and 1 of the OSPEEDR register associated with port C (GPIOC_OSPEEDR),
represent the speed setting of the output pin PC0 and bits 26 and 27 of the same register
represent the speed setting of the output pin PC13. These two bits can be set to:
- 'x0': 2MHz Low speed
- '01':10MHz Medium speed
- '11': 50MHz High speed
So why have a speed setting on I/O ?
To save power.
On the 2MHz setting the GPIO would consume less current than on the 50MHz setting
I'd imagine but would have relatively longer rise/fall time specs.
The User Manual for the STM32F0 claims that the the output pins fastest toggle speed is every two clock cycles.
Assuming a maximum operation speed of 48MHz, the fastest toggle speed for the GPIO on the STM32f0 is 24 MHZ,
which means the highest frequency square wave that can be produced by the GPIO is 12MHz.
NOTE:
A quick look at the default startup code found in"system_stm32f0xx.c"
will identify that the microcontroller is indeed operating at a maximum speed of 48MHz at startup.
In a future entry I will demonstrate how this speed can be changed.
- GPIO port pull-up/pull-down register (GPIOx_PUPDR)
The GPIOx_PUPDR registers configures the internal pull-ups and pull-down resistors on each I/O pin.
The internal pull-up/down resistors can be configured on GPIO pins set as input or output
(though I'd imagine they'd be more popular on input pins).
The Pullup/down resistors have a typical value of 40KOhms but can range from 30-50Kohms.
Again each two consecutive bits represent the internal pull-up/down resistor setting for each pin within a single port.
- GPIO port input data register (GPIOx _IDR)
This is a 16-bit read-only register. Each bit represents the input value on a corresponding pin.
Reading a '0' in bit 8 of this GPIOC _IDR register indicates that the voltage on PC8 is 0V (GND).
While reading a '1' in bit 8 of this GPIOC _IDR register indicates that the voltage on PC8 is 3.3V (VDD)
GPIO port output data register (GPIOx_ODR)
This is a 16-bit read/write register. Each bit represents the output value on a corresponding pin.
Writing a '0' in bit 8 of this GPIOC _ODR register indicates that the voltage on PC8 is driven by the micro to 0V (GND).
While writing a '1' in bit 8 of this GPIOC _ODR register indicates that the voltage on PC8 is driven by the micro to 3.3V (VDD).
Writing to the ODR register is good if you want to write to the entire port.e.g.
GPIOC->ODR = 0xF0FE
The above statement changes the state of every pin on the GPIOC peripheral from its previous (and now discarded) state,
to the one indicated by the statement; 0xF0FE (0b1111000011111110).
However if you want to set only a single pin;
lets say PC8 without affecting the state of the rest of the pins on GPIOC,
you have to perform a read-modify-write (RMW) access.
To set pin PC8 independent of all other pins on GPIOC (RMW) you could use:
GPIOC->ODR |= 0x00000100; //( 0b00000000000000000000000100000000)
To clear pin PC8 independent of all other pins on GPIOC (RMW) you could use:
GPIOC->ODR &= ~(0x00000100); //( 0b00000000000000000000000100000000)
This works just fine, but you have to read the ODR register,
OR (|) or AND(&) (modify) it with a mask
and then write it back to the ODR register.
This means that at the assembly language level, at least three instructions
are used to set/clear an I/O which can significantly slow down toggling speed.
A better way would be to use the BSRR register and the BRR registers for setting and clearing pins.
They enable 'atomic' access that allows the I/O pin to be clear/set in as short a time as possible.
GPIO port bit set/reset register (GPIOx _BSRR)
Note: If both BSx and BRx are set, BSx has priority.
As mentioned in the preceding paragraph the BSRR register allows us to set/clear a particular pin (or groups of pins)
while preserving the state of the rest of the pins on a GPIO peripheral atomically
i.e. a fast as possible, without having to resort to the slower read-modify-write (RMW) accesses.
The least significant 16 bits are used to atomically set pin values to VDD
whereas the most significant 16 bits are used to atomically clear pin values to GND.
So if I wanted to set PC8 independent of all other pins on GPIOC I could use:
GPIOC->BSRR = 0x00000100;//( 0b00000000000000000000000100000000)
or
GPIOC->BSRR = (1<<8);
To clear pin PC8 independent of all other pins on GPIOC you could use:
GPIOC->BSRR = 0x01000000; //( 0b00000001000000000000000000000000)
or
GPIOC->BSRR = (1<<24);
Notice how in both scenarios a simple assignment operator '=' (atomic)
was used rather than an '|=' or an '&=' which denote RMW accesses.
Furthermore, note that to clear the pin value of PC8 to GND,
I had to set the 24th bit in the BSRR (8th bit of the most significant 16 bits).
While to set the pin value of PC8 to VDD, I had to set the 8th bit in the BSRR.
The awkwardness of atomic clearing being mapped to the most significant 16-bits of the BSRR register
is compensated for by the inclusion of the BRR register.
The BRR register maps the most significant 16-bits of the BSRR register into itself.
So to clear pin PC8 independent of all other pins on GPIOC you could use:
GPIOC->BRR = (1<<8);
Finally there are three more registers;
the GPIOx_AFRH, GPIOx_AFRL, and the GPIOx_LCKR registers.
The first two allow GPIO pins to be used for alternate functions.
There is a really neat pin muxing mechanism that allows each GPIO to be mapped
to multiple alternate functions depending on how these two registers are set.
I will spend more time on the AFRL/AFRH registers in future entries.
The last GPIOx_LCKR register can be used once GPIO
is configured to 'lock' the configuration so that it does not change until the micro is reset.
I encourage you to look up these three registers in the user manual.
Understanding the STM32F0's GPIO的更多相关文章
- STM32f10xxx 之 GPIO口配置
背景 配置stm32f103使其完成PWM输出的过程中,在配置GPIO口的时候,按照习惯配置GPIO口的speed为50MHZ,突然就意识到,为什么大部分例程习惯配置为50MHZ,而不是其它值,即有了 ...
- STM32F0单片机基于Hal库温控智能风扇
一.项目概述 设计采用STM32F0系列单片机做主控芯片,通过DHT11采集温湿度,将温度显示在OLED 屏幕上.根据温度的不同,利用STM32对风扇进行调速,总体硬件设计如下图所示 1.效果展示 2 ...
- [转]: stm328种GPIO模式
[原创]:这段时间开始研究stm32,今天撸着一段代码一直追,追到了GPIO口模式的枚举类型这里,遂去网上查看这8种模式到底是什么,网上一查,看到了一个答案被很多博主转载或者原创,那我也就不重复废话了 ...
- 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)
作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...
- 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(2)
作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...
- 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(1)
作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...
- android gpio口控制
android gpio口控制 GPIO口控制方式是在jni层控制的方式实现高低电平输出,类似linux的控制句柄方式,在linux系统下将每个设备看作一个文件,android系统是基于linux内 ...
- STM32F412应用开发笔记之二:基本GPIO控制
NUCLEO-F412ZG板子上的元器件并没有完全焊接,除去ST-LINK部分和电源部分后,还有用一个USB主机接口,三个LED灯和两个按钮,不过很多功能引脚都已经引到了插针.查看原理图可发现,由原理 ...
- 通过数组和枚举简化GPIO操作编码
在工作中,经常遇到大量使用GPIO作为数字量输入输出来控制设备或采集状态,每次定义操作不同的GPIO针脚既麻烦又容易出错,于是就想要简化操作过程.对于数字量输入来说就是采集对应针脚的状态:而输出则是根 ...
随机推荐
- vue实践中的狗血事件之:mock数据引发的血坑
在项目实践中,遇到了这么一档子事 开发环境下,很快乐,什么事儿都没有,于是想打包一下测一下自动登录的效果 好家伙,一开始登录没有效,改来改去,最后连路由都切换不了, 明明开发环境下好好的,为毛打包后就 ...
- 数位dp(D - How Many Zeroes? LightOJ - 1140 )
题目链接:https://cn.vjudge.net/contest/278036#problem/D 题目大意:T组测试数据,每一次输入两个数,求的是在这个区间里面,有多少个0,比如说19203包括 ...
- innodb和myisam数据库文件存储详解以及mysql表空间
数据库常用的两种引擎有Innodb和Myisam,关于二者的区别参考:https://www.cnblogs.com/qlqwjy/p/7965460.html 1.关于数据库的存储在两种引擎的存储是 ...
- linux 图形配置网络
命令:setup 打开网络等系统信息的图形配置 yyp复制 vi /etc/sysconfig/network-scripts/ifcfg-eth0 配置网络参数 重启网卡:/etc/init.d/n ...
- mac ssh 自动登陆设置
1.首先找到.ssh目录 一般在用户名目录下. ls -a查看 如果没有就重新创建一个 chennan@bogon :mkdir .ssh chennan@bogon 查看当前的 bogon:.ssh ...
- 基于 Apache 在本地配置多个虚拟主机
如何使用 Apache 在本地配置出多个虚拟主机呢?而且使用不同的“域名”来访问本地不同的站点呢? 一般情况下,咱们都使用 localhost 来访问本机上的服务器,在我们的 C:/WINDOWS/s ...
- 虚拟机Failed to start LSB: Bring up/down networking
1.执行 service network restart 出现以下错误 Restarting network (via systemctl): Job for network.service f ...
- javaweb笔记七
过滤器:是一个web中间组件,用于拦截从客户端发送给服务器的请求和响应.当客户端向服务器发出请求时,服务器会查看是否有过滤器和该请求匹配,如果有,则交给过滤器执行,业务操作后,可以将请求继续向目标资源 ...
- 003_Java笔记3:Eclipse添加jar包
本文以jedis包为例,演示Eclipse如何添加和使用jar包. 1 建立一个名为ImportJarDemo的Java Project.在该工程下建立一个libs的文件夹. 2 将下载的jedi ...
- .NetCore SkyWalking APM实现服务器监控环境安装及基础使用
下载Java 8 SDK wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fw ...