M3位带地址映射

news/2024/10/15 6:14:04

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/26575.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

aardio封装库) 微软开源的js引擎(ChakraCore)

前言 做爬虫肯定少不了JavaScript引擎的使用,比如在Python中现在一般用pyexecjs2来执行JavaScript代码,另外还有一些其他执行JavaScript的库:https://github.com/eight04/node_vm2: rpc调用nodejs,需要安装node https://github.com/eight04/deno_vm: rpc调用deno,需要安装…

shell编程

!/bin/bash set -u -e 安全 export 环境变量 cat /porc/$PID/export 位置变量 $0: 表示脚本或命令本身的名称。 $1, $2, $3, ...: 表示第一个、第二个、第三个等参数的值。 $* 或 $@: 表示所有位置参数的列表。 $#: 表示传递给脚本或命令的位置参数的个数。 echo $[12^4] =8 …

python雨滴谱删除不需要的粒径列值

粒径的取值范围为:0.31~8mm 因此excel中标记红色的都需要删除: txt文件为(红框为留下来的数据),一共五组数,也就是五个时间的数: 那么我只留下我需要的d的n的数据,删除不需要的列:# -*- coding:utf-8 -*- """ @author: su @file: deletlie.py @time: 2…

[题解]P4597 序列 sequence

P4597 序列 sequence 是CF13C Sequence的加强版,\(N\leq 5*10^5\)。 如果想了解\(O(N^2)\)的DP解法请看此文。给定\(N\)个数,每次操作可以选其中一个数\(+1\)或\(-1\)。请问要让这个数列不降,最少需要多少次操作? 看到数据范围发现不能用\(O(N^2)\)的dp了,需要换一种思路。…

关于雨滴谱数据的处理

粒径的取值范围为:0.31~8mm 因此excel中标记红色的都需要删除: txt文件为(红框为留下来的数据),一共五组数,也就是五个时间的数: 那么我只留下我需要的d的n的数据,删除不需要的列:# -*- coding:utf-8 -*- """ @author: su @file: deletlie.py @time: 2…

1.验整码的发送与检验

通过restTemplate.exchage()来发送验证码,需要4个参数,url,请求方式,请求内容,需要相应类型) 响应的结果为map结合,我们需要取出key值,用俩次map取值可以取出key 检验验证 需要输入验证码和key restTeMPLATE.exhcange(url,....);//发送请求获得验证码 请求内容为空 判断…

如何在本地局域网中通过SMB协议加密共享文件

Windows网络发现共享是Windows操作系统中的一个功能,通过该功能,用户可以在局域网内自动发现和访问其他计算机上共享的资源,如文件夹、打印机等。这个功能通常使用SMB(Server Message Block)协议来实现文件共享和网络资源访问。V1.0 于2024年5月1日发布于博客园序言Window…

二值信号量和计数信号量

信号量常用于控制对共享资源的访问和任务同步。 其中控制共享资源可以从停车场的例子去理解。比如现在这个停车场最大容量为100。这个100就是共享资源。假如要把车停进去这个停车场,就需要查看当前停车场中的数量。当前的停车数量就是信号量。信号量的增加对应停车场的车开出停…