首页 > 编程语言 >M3位带地址映射和汇编对比

M3位带地址映射和汇编对比

时间:2024-05-01 18:11:37浏览次数:27  
标签:位带 LED 比特 地址映射 M3 gpio InitTypeDef GPIO

01. 位带概述
位带操作简单的说,就是把每个比特膨胀为一个 32 位的字,当访问这些字的时候就达到了访问比特的目的,比如说 GPIO 的 ODR 寄存器有 32 个位,那么可以映射到 32 个地址上,我们去访问这 32 个地址就达到访问 32 个比特的目的。这样我们往某个地址写 1 就达到往对应比特位写 1 的目的,同样往某个地址写 0 就达到往对应的比特位写 0 的目的。

支持了位带操作后,可以使用普通的加载、存储指令来对单一的比特进行读写。在CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。

SRAM 区中的位带地址映射

对于片上外设,映射关系如下表所示

03. 位带C语言实现

//位带操作,实现51类似的GPIO控制功能
//IO口操作宏定义
#define BITBAND(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)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入

那么初始化相应的GPIO之后就可以直接使用了。

led.h

#ifndef __LED_H__
#define __LED_H__

#include "sys.h"

//LED初始化
void LED_Init(void);

//位带操作
#define LED1 PFout(9)
#define LED2 PFout(10)


#endif /*__LED_H__*/

led.c

#include "led.h"


//LED初始化
void LED_Init(void)
{
	GPIO_InitTypeDef gpio_InitTypeDef;
	
	gpio_InitTypeDef.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	gpio_InitTypeDef.GPIO_Mode = GPIO_Mode_OUT;
	gpio_InitTypeDef.GPIO_Speed = GPIO_Speed_100MHz;
	gpio_InitTypeDef.GPIO_OType = GPIO_OType_PP;
	gpio_InitTypeDef.GPIO_PuPd = GPIO_PuPd_UP;
	
	//使能时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	//GPIO初始化
	GPIO_Init(GPIOF, &gpio_InitTypeDef);
	
	//设置高电平 LED灭
	GPIO_SetBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10);
}

main.c

#include "stm32f4xx.h"

#include "delay.h"
#include "led.h"

int main(void)
{		
	delay_init(168);
	
	LED_Init();
	
	//3. LED闪烁
	while(1)
	{
		//灭
		LED1 = 1;
		LED2 = 1;
		
		delay_ms(1000);
		
		//亮
		LED1 = 0;
		LED2 = 0;
		delay_ms(1000);
	}	
}

写入对比

读取对比


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/dengjin20104042056/article/details/108124642

标签:位带,LED,比特,地址映射,M3,gpio,InitTypeDef,GPIO
From: https://www.cnblogs.com/icaowu/p/18169506

相关文章

  • rust+stm32+vscode搭建开发调试环境
    1.安装rustrust官网传送门2.安装openocd安装openocd传送门3.安装stlink安装stlink传送门4.搭建gcc-arm-none-eabi编译环境搭建gcc-arm-none-eabi编译环境5.安装vscodevscode官网传送门6.安装相关插件rust-analyzer:使用VSCode开发Rust必备cortex-debug:调试、debug嵌入......
  • stm32F07 HAL 库 通过定时器方式实现呼吸灯 自定义呼吸灯函数 (以参数方式设置io
    效果: 1、通过Stm32CubMX开启定时器、设置对应的io口,然后生成工程STM32CubeMX|STM32HAL库方式的微秒延时函数  2、自定义呼吸灯函数代码://呼吸灯函数//GPIO_TypeDef*GPIOx:GPIO组(A-G)//uint16_tGPIO_Pin:IO口(GPIO_Pin_0--GPIO_Pin_16)//......
  • 下载M3U8/Blob视频教程
     准备工作:以下操作默认为google浏览器,如微信中的视频提示“请在微信客户端打开链接”,则按如下设置微信客户端(默认浏览器设置为google浏览器) 1、安装”篡改猴“           安装成功,其他插件安装方法类似。2、打开视频网站播放视频,并下载......
  • 2024新版本如何配置CLion与cubeMX开发STM32
    2024新版本如何配置CLion与cubeMX开发STM321.为什么我要在网上有很多教程的情况下再做一个新版各种大佬们给出的配置教程原本很详细,但是在时间过了这么久之后已经不完全符合现在的环境了。昨天在教群里萌新安装CLION+CUBEMX时我才发现,在配置过程中新出现的一些变化甚至没有清......
  • 实现FLV,HLS(M3U8)视频播放
    1.安装hls.js和flv.jsnpmihls.jsflv.js<template><div><videocontrolsautoplayloopmutedpreload="auto"width="550"ref="videoEl"></video>......
  • STM32之UASRT试验
    一、实验目的1.实现STM32F407开发板与上位机工具通讯,中断方式 具体实现的效果:上电后,下位机主动发送helloworld,上位机收到并显示;上位机发送数字0~9,回复:zero~nine2.通讯协议,后面补充3.硬件使用野火开发版STM32F4074.与开发板连接的接口是Usb转串口,根据原理图看出选择的......
  • stm32操作SD卡
       https://item.taobao.com/item.htm?spm=a1z09.2.0.0.b1212e8dOgRcLN&id=39107244481&_u=p1qf7bf52f08     /*SDcardbasicfileexampleThisexampleshowshowtocreateanddestroyanSDcardfileThecircuit:SDcardattachedto......
  • macOS配置Clion用于STM32开发找不到stdint.h等头文件问题解决方案
    问题编译工程时发现出现大量类似错误如下/opt/homebrew/Cellar/arm-none-eabi-gcc/13.2.0/lib/gcc/arm-none-eabi/13.2.0/include/stdint.h:9:16:fatalerror:stdint.h:Nosuchfileordirectory问题原因不能使用brewinstallarm-none-eabi-gcc安装编译工具链[1]解决方......
  • 【专题STM32F03】FreeRTOS 队列queue传递结构体,野火例程代码简单修改。
    /************************************************************************@filemain.c*@authorfire*@versionV1.0*@date2018-xx-xx*@briefFreeRTOSV9.0.0+STM32消息队列******************************************************......
  • RT-Thread 4.x STM32F107
    官方文档很坑,新旧不分开,文档缺失/分类很乱有些文档在IDERT-STUDIO文档里,有些在RTThread标准版文档里,逆天坑:不支持STM32CUBEMX的Advanced工程,记得重新保存生成basic工程才能用。不能使用.c/.h分离。坑:适配CUBEMX工程的脚本要自己写driver/stm32f1xx_hal_conf_bak.h不一定会生......