IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> stm32f4xx-位带操作 -> 正文阅读

[嵌入式]stm32f4xx-位带操作

一、位带操作

eg:51代码

sfr P0 = 0x10; //将P0端口设置为0x10 00010000

P1_0 = 1; //将P1(GPIOP1_0)端口0号引脚设置为高电平

A = P2_2; //获取P2端口2号引号的电平

根据上述的方法,我们可以发现快速定位修改某个引脚的电平还有获取引脚的状态

Bit-band operation support allows a single load/store operation to access (read/write) to a single data bit. In the Cortex ? -M3 and Cortex-M4 processors, this is sup-ported in two pre-defined memory regions called bit-band regions.

位带操作的概念其实30年前就有了,那还是 CM3 将此能力进化,这里的位带操作是 8051 位寻址区的威力大幅加强版

位带区: 支持位带操作的地址区

位带别名: 对别名地址的访问最终作 用到位带区的访问上(注意:这中途有一个 地址映射过程)

二、位带操作的优越性

位带操作对于硬件 I/O 密集型的底层程序最有用处

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

关于IO引脚对应的访问地址,可以参考以下公式

寄存器位带别名 = 0x42000000 + (寄存器的地址-0x40000000)*32 + 引脚编号*4

三、寄存器的地址转换成别名地址

1、确定某端口访问起始地址

如:端口F访问的起始地址GPIOF_BASE

#define GPIOF ((GPIO_TypeDef *)GPIOF_BASE)

在这里插入图片描述

2、根据要访问的寄存器地址计算偏移值

GPIOF的某个寄存器地址 = GPIOF_BASE+偏移地址

例如:

GPIOF的ODR寄存器的地址 = GPIOF_BASE + 0x14

3、根据以下公式进行换算

寄存器位带别名 = 0x42000000 + (寄存器的地址-0x40000000)*32 + 引脚编号*4

4、设置PF9引脚电平代码如下:

uint32_t *PF9_BitBand =
*(uint32_t *)(0x42000000 + ((uint32_t )&GPIOF->ODR– 0x40000000) *32 + 9*4)

四、代码调整

将端口的访问封装为Pxout、Pxin,例如端口F引脚电平设置PFout

#define PFout(x) *(volatile uint32_t *)(0x42000000 + ((uint32_t )&GPIOF->ODR – 0x40000000) *32 + x*4)

注意:

当你使用位带功能时,要访问的变量必须用volatile来定义。因为C编译器并不知道同一个比特可以有两个地址。所以就要通过volatile,使得编译器每次都如实地把新数值写入存储器,而不再会出于优化的考虑,在中途使用寄存器来操作数据的复本直,到最后才把复本写回(这和cache的原理是一样的)。

在这里插入图片描述

四、test

#include "stm32f4xx.h"
//key gpio a 0 e 2  3  4
//led gpio f 9 10  e 13  14
//beep gpio f 8
//位带操作
//寄存器边界起始地址 0x42000000
//寄存器位带别名 = 0x42000000 + (寄存器的地址-0x40000000)*32 + 引脚编号*4
#define PAin(n)  *(volatile uint32_t *)(0x42000000+(((uint32_t)&GPIOA->IDR - 0x40000000)<<5) + (n<<2))
#define PEin(n)  *(volatile uint32_t *)(0x42000000+(((uint32_t)&GPIOE->IDR - 0x40000000)<<5) + (n<<2))
#define PFout(n) *(volatile uint32_t *)(0x42000000+(((uint32_t)&GPIOF->ODR - 0x40000000)<<5) + (n<<2))
#define PEout(n) *(volatile uint32_t *)(0x42000000+((uint32_t)&GPIOE->ODR - 0x40000000)*32+n*4)
//库函数方式
#define KEY0	GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY1	GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)
#define KEY2	GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)
#define KEY3	GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)
//位带操作
#define KEY00	PAin(0)
#define KEY11	PEin(2)
#define KEY22	PEin(3)
#define KEY33	PEin(4)

//定义需要配置的硬件结构体
static GPIO_InitTypeDef GPIO_InitStruct;
static GPIO_InitTypeDef GPIO_InitStructKey;
static uint16_t flag = 1;
void delay(uint32_t ms)
{
	int i=0;
	while(ms--)
	{	for(i=0;i<18000;i++)
		{
		}
	}
}
//初始化LED beep
void init_led_beep()
{
	//1、使能AHB1硬件时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOE, ENABLE);
	//2、硬件配置
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;		//端口模式配置为输出
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;		//输出配置为推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10 | GPIO_Pin_8;			//配置引脚编号为9号引脚
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;		//上拉
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	//快速50Mhz输出速度
	
	GPIO_Init(GPIOF, &GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;	
	GPIO_Init(GPIOE, &GPIO_InitStruct);
	//3、使能硬件工作
	//GPIO_SetBits(GPIOF, GPIO_Pin_9|GPIO_Pin_10);//设置GPIOF9引脚为高电平,灯灭
}
void Key_init(void)
{
	//1、使能AHB1硬件时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	//2、硬件配置
	GPIO_InitStructKey.GPIO_Mode = GPIO_Mode_IN;	//端口模式配置为输入
	GPIO_InitStructKey.GPIO_OType = GPIO_OType_PP;	//输入配置为推挽输入
	GPIO_InitStructKey.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 |GPIO_Pin_4;
	GPIO_InitStructKey.GPIO_PuPd = GPIO_PuPd_UP;		//上拉
	GPIO_InitStructKey.GPIO_Speed = GPIO_Speed_100MHz;	//快速50Mhz输出速度
	GPIO_Init(GPIOF, &GPIO_InitStructKey);//初始化GPIOE2,3,4
	
	GPIO_InitStructKey.GPIO_Pin = GPIO_Pin_0;//WK_UP对应引脚PA0
	GPIO_InitStructKey.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉
	GPIO_Init(GPIOA, &GPIO_InitStructKey);//初始化GPIOA0
}

uint32_t Key_Scan1(void)
{
	if(KEY0 == 0)
		return 1;
	else if( KEY1 == 0 )
		return 2;
	else if( KEY2 == 0 )
		return 3;
	else if( KEY3 == 1 )
		return 4;
	return 0;
}

uint32_t Key_Scan2(void)
{
	if(KEY00 == 0)
		return 1;
	else if( KEY11 == 0 )
		return 2;
	else if( KEY22 == 0 )
		return 3;
	else if( KEY33 == 1 )
		return 4;
	return 0;
}

void Led_All_On1(void)
{
	GPIO_ResetBits(GPIOF, GPIO_Pin_9|GPIO_Pin_10);
	GPIO_ResetBits(GPIOE, GPIO_Pin_13|GPIO_Pin_14);
}
void Led_All_off1(void)
{
	GPIO_SetBits(GPIOF, GPIO_Pin_9|GPIO_Pin_10);
	GPIO_SetBits(GPIOE, GPIO_Pin_13|GPIO_Pin_14);
}
void Led_All_On2(void)
{
	PFout(9) = 0;
	PFout(10) = 0;
	PEout(13) = 0;
	PEout(14) = 0;
}
void Led_All_off2(void)
{
	PFout(9) = 1;
	PFout(10) = 1;
	PEout(13) = 1;
	PEout(14) = 1;
}
void Led_pao(void)
{
	PFout(9) = 0;
	PFout(10) = 1;
	PEout(13) = 1;
	PEout(14) = 1;
	delay(800);
	PFout(9) = 1;
	PFout(10) = 0;
	PEout(13) = 1;
	PEout(14) = 1;
	delay(800);
	PFout(9) = 1;
	PFout(10) = 1;
	PEout(13) = 0;
	PEout(14) = 1;
	delay(800);
	PFout(9) = 1;
	PFout(10) = 1;
	PEout(13) = 1;
	PEout(14) = 0;
	delay(800);	
}
int main(void)
{	
	init_led_beep();
	Key_init();
	while(1)
	{
		uint32_t res = Key_Scan1();
		//uint32_t res = Key_Scan2();
		delay(20);
		switch(res)
		{
			case 1:
				//Led_All_On1();
				//Led_All_On2();
				Led_pao();
				break;
			case 2:
				//Led_All_off1();
				Led_All_off2();
				break;
			case 3:
				PFout(8) = 1;	
				delay(1000);
				break;
			case 4:
				PFout(8) = 0;
				break;
			default:
				break;
		}
	}
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:27:45  更:2022-09-04 01:29:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 13:48:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码