为了像51单片机一样能够对某个管脚单独操作,引入了位带操作这样的操作机制。
如下图,位带(Bit band)区就是就是你想单独操作的IO的区域,比如PA1、PA2。而位带别名区就是你给每一位重新起了个名字的那一片地址区域。可以看下表,M3内核存储器映射表,你能看到1M内存的BitBand区,还有与之对应的32M内存的BitBand别名区,因为你将每一位膨胀成为了一个32位的地址,所以相应的别名区的内存也会是位带区的32倍。
想进行位带操作,应该先去找该位对应的别名区的地址,找到了这个地址,对这个地址进行操作,那么实际上也就是对该位进行操作了。
官方给出了如下相应的计算公式:
AliasAddr
=0x42000000+((A‐0x40000000)*8+n)*4
=0x42000000+(A‐0x40000000)*32+n*4
其中,AliasAddr是别名区的地址,A是GPIOA->ODR的地址,n是该端口的上的某一位。
0x42000000是位带别名区域的起始地址,A是输出数据寄存器GPIOA->ODR的地址,A的地址先减去位带区基地址,得到的是相对于位带区基地址的偏移地址,那么膨胀之后还是一个偏移地址,是相对于位带别名区基地址的偏移量,加上位带别名区域基地址,就得到了其对应的别名区地址。
多数情况下,大家见到的代码,应该是以下这个样子,一共分为三步:
#defineBITBAND(addr,bitnum)((addr&0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
第一步,就是我们上面分析的,得到位带别名区域的32位地址。
第二步,就是将第一步得到的32位地址,给转换成一个指针变量,并且操作这个地址里的值,唯一的区别,就是由于安全的考虑,多加了一个volatile 这样的关键字。
举个例子
如下,想直接访问0x00000001这个地址,并且给这个地址写1,该怎么做呢?
#defineADDR0x00000001
*(int*)ADDR=1;
第三步,就是将前两部,结合在一起,根据传入的addr和bit计算得到32位的地址,然后强制类型转换,使得我们可以去操作这个地址里的值。
提示:bitnum<<2相当于bitnum2乘以4,实际上在计算机底层乘法也是基于位运算实现的。
关键字:STM32开发 位运算 位带操作
引用地址:
STM32开发中的位运算以及位带操作
推荐阅读最新更新时间:2024-11-12 14:02
STM32 开发板入门教程 (一) GPIO
这个章节我们将学习最基本的 STM32 的 GPIO 的应用. 我们将分为两个章节来学习. 第一部份: GPIO 的基本应用和 IO 口的配置 第二部份: 外部中断的使用 -------------------------------------------------------------------------- 1: 设计要求: 开发板上有 2 个 LED, 我们的目的为有规律的点亮 LED1 和 LED2. 当按键按下去的时候所有的灯灭, 等待 2 秒钟后恢复有规律的点亮. 2: 硬件电路: 3: 软件程序设计: (1) 根据要求配置 GPIOA 中的 PA0,PA1 为输出, PA3, PA
[单片机]
STM32开发笔记93: SX1268驱动程序的移植1
单片机型号:STM32L053R8T6 本文详述将SX1268官方驱动程序,移植到C++程序设计框架的方法。 1、文件结构 在系统中加入以下文件。 2、屏蔽和硬件相关的数据类型 sx126x.h文件,屏蔽以下语句。暂时屏蔽,后续需要解决。 typedef struct SX126x_s { // Gpio_t Reset; // Gpio_t BUSY; // Gpio_t DIO1; // Gpio_t DIO2; // Gpio_t DIO3; // Spi_t Spi; PacketParams_t PacketParams; PacketStatus
[单片机]
STM32开发笔记30:STM32L0低功耗设计-STOP_RTC模式下的休眠时间
单片机型号:STM32L053R8T6 本文介绍STOP_RTC模式下,设置进入低功耗休眠时间的方法。 低功耗的休眠时间的设置首先需要确定RTC的基准时间,我们一般将其设置为1秒,这在《STM32L0低功耗设计4: RTC模块1秒时钟的产生方法》中已经介绍过,大家看一下就好。 接下来,就需要对HAL_RTCEx_SetWakeUpTimer_IT函数的第2个参数进行设置了。 具体计算公式:数值 = 定时时间(秒)*(RTC时钟)/16,其中16为该参数的第2个参数,RTC时钟要看具体的时钟源,在我设计的项目中,使用的是LSI,则为37000。 进一步计算:数值 = 定时时间(秒) * 370
[单片机]
STM32开发环境(3)----下载调试
下载调试 STM32 程序下载主要有两种方法:串口和JLINK。串口下载也可以扩展为USB,JLINK支持JTAG、 SWD。 STM32 的串口下载一般是通过串口 1 下载的,使用USB下载其实也是应用这种方式。只是要在PC端下载USB转串口的驱动,在硬件端加一片USB转串口的片子。USB转串口的片子常用的是CH340,在PC端下端其驱动程序就可。另外还需使用STM32串口下载软件,受正点原子影响我使用FLYMCU,这个软件好用、易用,打开就能知道怎么用。该软件可以在 www.mcuisp.com 免费下载。 特别提醒:不要选择使用 RamIsp,否则,可能没法正常下载。 需要在线调试时,JTAG
[单片机]
STM32开发板学习笔记--通用定时器
定时器可以说是单片机最常用的内部资源,连续几天都在看STM32定时器的使用方法,看固件库使用手册看的头都大了,总算学会了基本的应用。 1、首先在void NVIC_Configuration(void)中开启中断: NVIC_DeInit(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPrio rity = 2; NVIC_InitStructure.NVIC_IRQChannel
[单片机]
STM32开发笔记83: SX1268驱动程序设计(芯片复位)
单片机型号:STM32L053R8T6 本系列开发日志,将详述SX1268驱动程序的整个设计过程,本篇介绍芯片复位驱动程序。 一、数据手册 1、NRESET是芯片第15引脚,低有效。 2、通过15引脚NREST,可以达到完整的芯片复位。复位后,会执行标准的校准程序,先前的内容将丢失。复位最短时间为50us,给100us较为合适。 3、这张图是芯片各个模式的引脚的状态表,可以看到除复位模式外,其余模式NREST引脚的状态都为IN PU,其意思是输入上拉,其上拉值为50K。 二、程序 1、由于其内部上来,我们可以给出低功耗的程序,不将单片机控制NREST的引脚设置为输出,而设置为analog引脚,程序如下: c
[单片机]
STM32开发笔记69: 外设启动的先后次序
单片机型号:STM32F070F6P6 今天,在程序框架中增加了Timer16定时器驱动,但程序不能正常运行,本篇日志记录其原因。 驱动程序框架,定义了回调函数Timer16_InterruptFunction,写在main.cpp中用于逻辑层设计。Timer16_InterruptFunction调用的间隔为1ms,具体程序如下: void Timer16_InterruptFunction(void) { Target.HAL.L2.Turn(); } 此程序完成以1ms为间隔L2闪烁的程序,但是将此程序烧写到目标板后,程序不能正常运行。经过调试,最后将问题锁定在启动顺序上,看一下程序外设的启动顺序,具体程序
[单片机]
ubuntu中安装配置STM32开发环境
笔者做嵌入式开发的,主要用到linux系统来做开发,有时候遇到既要开发arm linux,又要挂载MCU的情况(主要是STM32这款),这两个芯片跨平台,指令不兼容。以前开发STM32是在windows下的IDE,使用keil或者IAR来开发,自从搞arm linux以来,很少开windows系统,两个系统切来切去着实麻烦。这篇文章主要针对长期使用Linux系统的用户,有什么不对的地方,欢迎指正。 接下教教大家怎么在linux下部署STM32开发环境 首先安装一个stm32cubemx,该软件可以在st官网下载,要注册账号,还要搞邮件的乱七八糟的步骤就不说了,自行解决 下载下来的文件中就用到下面两个文件 Setup
[单片机]