STM32位带操作实现GPIO输入输出

发布者:SHow111time最新更新时间:2021-12-14 来源: eefocus关键字:STM32  位带操作  GPIO  输入输出 手机看文章 扫描二维码
随时随地手机看文章

前言

位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见。51 单片机中通过关键字 sbit 来实现位定义,STM32 没有这样的关键字,而是通过访问位带别名区来实现。


提示:以下是本篇文章正文内容


一、示意图

在这里插入图片描述

在 STM32 中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 空间,令一个是外设区最低 1MB 空间。这两个 1MB 的空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区把这 1MB 的空间的每一个位膨胀成一个 32 位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。


二、位带区

1.外设位带区

外设外带区的地址为:0X40000000~0X40100000,大小为 1MB,这 1MB 的大小在 103系列大/中/小容量型号的单片机中包含了片上外设的全部寄存器,这些寄存器的地址为:0X40000000~0X40029FFF 。


外设位带区地址为: AliasAddr= =0x42000000+ (A-0x40000000)*8*4 +n*4

0X42000000 是外设位带别名区的起始地址,0x40000000 是外设位带区的起始地址,(A-0x40000000)表示该比特前面有多少个字节,一个字节有 8 位,所以8,一个位膨胀后是 4 个字节,所以4,n 表示该比特在 A 地址的序号,因为一个位经过膨胀后是四个字节,所以也*4。


2.SRAM 位带区

SRAM 的位带区的地址为:0X2000 0000~X2010 0000,大小为 1MB,经过膨胀后的位带别名区地址为:0X2200 0000~0X23FF FFFF,大小为 32MB。

SRAM 位带区地址为: AliasAddr= =0x22000000+ (A-0x20000000)*8*4 +n*4,分析同上。


3.统一公式

为了方便操作,我们可以把这两个公式合并成一个公式,把“位带地址+位序号”转换成别名区地址统一成一个宏。


 // 把“位带地址+位序号”转换成别名地址的宏

 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))


addr & 0xF0000000 是为了区别 SRAM 还是外设,实际效果就是取出 4 或者 2,如果是外设,则取出的是 4,+0X02000000 之后就等于 0X42000000,0X42000000 是外设别名区的起始地址。如果是 SRAM,则取出的是 2,+0X02000000 之后就等于 0X22000000,0X22000000 是 SRAM 别名区的起始地址。

实际应用:


1 // 把一个地址转换成一个指针

2 #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))

3

4 // 把位带别名区地址转换成指针

5 #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))


三、GPIO 位带操作

1.GPIO 寄存器映射

1 // GPIO ODR 和 IDR 寄存器地址映射

2 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C

3 #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C

4 #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C

5 #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C

6 #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C

7 #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C

8 #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C

9

10 #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808

11 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08

12 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008

13 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408

14 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808

15 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08

16 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08


现在我们就可以用位操作的方法来控制 GPIO 的输入和输出了,其中宏参数 n 表示具体是哪一个 IO 口。


2. GPIO 位操作

1 // 单独操作 GPIO 的某一个 IO 口,n(0,1,2...16),n 表示具体是哪一个 IO 口

2 #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出

3 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入

4

5 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出

6 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入

7

8 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出

9 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入

10

11 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出

12 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入

13

14 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出

15 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入

16

17 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出

18 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入

19

20 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出

21 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入


3. 主函数

该工程我们直接从 LED-库函数 操作移植过来,有关 LED GPIO 初始化和软件延时等函数我们直接用,修改的是控制 GPIO 输出的部分改成了位操作。


main 函数

1 int main(void)

2 {

3 // 程序来到 main 函数之前,启动文件:statup_stm32f10x_hd.s 已经调用

4 // SystemInit()函数把系统时钟初始化成 72MHZ

5 // SystemInit()在 system_stm32f10x.c 中定义

6 // 如果用户想修改系统时钟,可自行编写程序修改

7

8 LED_GPIO_Config();

9

10 while ( 1 ) {

11 // PB0 = 0,点亮 LED

12 PBout(0)= 0;

13 SOFT_Delay(0x0FFFFF);

14

15 // PB1 = 1,熄灭 LED

16 PBout(0)= 1;

17 SOFT_Delay(0x0FFFFF);

18 }

19 }


该实验我们让 IO 口输出高低电平来控制 LED 的亮灭,负逻辑点亮。


四、下载验证

把编译好的程序下载到开发板并复位,按下按键可以控制 LED 灯亮、灭状态。

在这里插入图片描述

在这里插入图片描述

五、收获

1.初学者写一部分代码,编译一部分, 不要等到写完一起编译。

2.位带操作可以实现操作寄存器的某一位不改变其他位。

关键字:STM32  位带操作  GPIO  输入输出 引用地址:STM32位带操作实现GPIO输入输出

上一篇:STM32启动文件执行步骤分析
下一篇:STM32固件库实现按键控制

推荐阅读最新更新时间:2024-11-12 13:05

STM32采用Jlink烧写外部Nor Flash
使用STM32-5I开发板测试: https://item.taobao.com/item.htm?spm=a230r.1.14.275.76bf523QxvMsK&id=557618550100&ns=1&abbucket=6#detail 开发板PCB完整工程连接: http://www.cirmall.com/circuit/7 ... F%EF%BC%81#/details 1. 开始 - 所有程序 - SEGGER,打开安装Jlink的驱动SEGGER下的J-Flash 2. File - Open Project… - 打开STM32F103ZE_ST_MB672_CFI_1x16.j
[单片机]
STM32之SHT30温湿度传感器驱动代码
第一部分:SHT30温湿度模块代码头文件(SHT30.h) #ifndef SHT30_H #define SHT30_H #include delay.h #include sys.h #include stdio.h #include usart.h #include string.h #include sys.h extern u8 humiture_buff1 ; extern u8 humiture_buff2 ; extern u8 Refresh_SHT30_Data; extern u8 send_data_fleg; extern u8 Temperature_L; extern u8 Hum
[单片机]
<font color='red'>STM32</font>之SHT30温湿度传感器驱动代码
STM32单片机的八种GPIO口模式
GPIO 是通用输入/输出端口的简称,本文以STM32为例进行说明,其他的单片机功能上都是大同小异,学会STM32的GPIO,我们可以触类旁通。 GPIO 的引脚与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 STM32的八种GPIO口模式 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 复用开漏输
[单片机]
<font color='red'>STM32</font>单片机的八种<font color='red'>GPIO</font>口模式
STM32 定时器输出方波的频率与PSC以及CNT的关系
1.STM32F103的系统时钟最高频率是72MHZ 2.STM32F103的定时器TIM 的CNT计数值最大为65535 3.STM32F103的定时器TIM 的预分频 系数 PSC 的数值 = 72M / 定时器计数频率 因为CNT最大值为65535 所以, 这里有个问题, 当定时器计数频率太高的时候, 例如72M的计数频率. 1秒钟最多有72000000个计数, 当计数到65535个的时候是 0.0009102083秒 也就是 1098.65HZ 要想计数到1秒, 必须修改PSC,提高分频系数. 降低定时器计数频率 经过实际测量, STM32F103C8T6 最高输出方波的频率为18mhz. 再往上就无
[单片机]
STM32的ADC实验
1、ADC 简介 STM32f103系列有3个ADC,精度为12位,每个ADC最多有16个外部通道。其中ADC1和ADC2都有16个外部通道,ADC3一般有8个外部通道,各通道的A/D转换可以单次、连续、扫描或间断执行,ADC转换的结果可以左对齐或右对齐储存在16位数据寄存器中。ADC的输入时钟不得超过14MHz,其时钟频率由PCLK2分频产生。 2、ADC配置 #include stm32f10x.h #include stdio.h //------------------------------------------------------------------------- //函数功能 : 重定向 //-
[单片机]
<font color='red'>STM32</font>的ADC实验
stm32之外部中断该如何使用
  中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大大增加,而且中断的设置也更加复杂。今天就将来探讨一下关于STM32中的中断系统。   1 基本概念   ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。   STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自
[单片机]
STM32串口实现485双机通信原理
RS485通信想必大家都知道,在学习RS232时,都会拿485(RS485下文就用485代替)和其作对比。485优缺点不说,网上有。 我用的是STM32库函数学的485通信,所以接下来就讲讲STM32串口实现485双机通信的原理: 485和232都是基于串口的通讯接口,在数据的收发操作上都是一致的。但是他两的通讯模式却大不相同~!232是全双工(例:A- B的同时B- A,瞬时同步)工作模式,而485是半双工(发时不能收,收时不能发)工作模式。在232通信中,主机在发送数据的同时可以收到从机发过来的数据;但在485通信中,收发要经过模式位的切换来进行,譬如发送数据时,会把模式为置‘1’,表示为发送模式,此时不能接收;当接收
[单片机]
<font color='red'>STM32</font>串口实现485双机通信原理
STM32 CRC寄存器
1、CRC计算公式 所有的STM32芯片都内置了一个硬件的CRC计算模块,可应用到通信程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式: X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2 + X + 1 写成16进制就是:0x04C11DB7 2、使用这个内置CRC模块操作步骤: 复位CRC模块(设置CRC_CR=0x01),这个操作把CRC计算的余数初始化为0xFFFFFFFF 把要计算的数据按每32位分割为一组数据字,并逐个地把这组数据字写入CRC_DR寄存器(既下图中的绿色框) 写完所有的数据字后
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved