基础知识
进制
计算机以二进制代码储存信息,每个二进制数表示一位 (bit),每8个二进制数表示一个字节 (Byte) , 而再往上的KB,就是210倍的字节,总结有以下进制关系。
1 Byte = 8 bit
1 KB = 1024Byte(210=1024)
1 MB = 1024KB
1 GB = 1024MB
1 GB = 230Byte
内存地址
内存地址使用16进制数表示,内存地址只是一个编号表示,一个内存空间,计算机以字节存储数据,所以一个内存地址对应的应该是一个字节(8 bit)的大小,这个之后会详细解释。
这里用32位机的内存做一个图例。32位机的内存地址用8位16进制数表示。
0x00000000----->[8bit];
0x00000001----->[8bit];
0x00000002----->[8bit];
0x00000003----->[8bit];
32位机
32位表示CPU一次可以处理32位数据or一次可以寻址32位,就是4个字节的数据。也就是CPU一次可以读取的数据可以有 232种不同的数,从0000 0000 到1111 1111,这一共232个不同的数。这 232个数就是232个地址,每个地址对应8个实际的二进制位,也就是一个地址管理一个字节的数据。
这也就是CPU寻址能力的来由,32位机的最大寻址能力就是 232Byte = 4GB;
对于32位机,高于4GB的内存将无法一次性寻得,所以32位机理论最大内存是 4GB。
内存的理解
下面的图将说明计算机的内存地址,实际存储样式和人所看到的表现。
现在我们向内存中写入“A” “B”"C"看看实际的存储是怎样的关系。
注:这里的数据是编造的。
第一行的ABC是用户输入的数据,第二行是计算机实际储存的数据
而第三行就是内存地址,可见一个内存地址对应一个字节,而计算机就靠这个地址来找到储存的信息。
对STM32的理解
寄存器地址
首先我们看一下STM32的参考手册
可以看到,这里的内存地址使用8位16进制储存的。一个地址对应一个字节的二进制数。
再以GPIO的寄存器为例
每个寄存器首地址以4个字节递增,每个寄存器占4个字节,对于BSRR寄存器可以画出这样的图
由此我们可以理解:
每个GPIO端口有16个IO口,
而每个 GPIO端口 有7个寄存器对这16个 IO 口进行各种设置,如:输入,输出,模式,速度等等,
每个寄存器占4个字节(Byte),32位(bit)。所以用这个32位就可以对16个 IO 口进行设置。一般这32位有以下集中分配方式:
一·每两位对应一个 IO 口,如 CRL,CRH
二·每一位对应一个IO,但只使用低16位进行设置,高16位保留,如 IDR, ODR, BRR, LCKR
三·每一位对应一个IO,低16位对应一种操作,高十六位对应另一种操作,如 BSRR
位带操作
位带操作是对STM32寄存器的位进行直接操作,有如51单片机中的“sbit”关键字。且只有GPIO 和 SRAW 中的低 1Mb 空间可以被位带操作。
其中寄存器的每一位数据在别名膨胀成4个字节,但只有最后一位有效。如此膨胀的原因是stm32为32位机,一次处理32位数据效率最高。
由以上的分析,位带别名区的转化公式也就很好理解了。
计算公式
如GPIO的计算公式:
AliasAddr = 0x42000000 + (A-0x40000000)*8*4+n*4
首先要明白,这个公式是计算字节的也就是内存地址
A为寄存器地址, 0x40000000 外设基地址是,A-0x40000000 就可以算出寄存器相对外设基地址的偏移了多少个字节(地址),又一个字节有8个位,每个位又膨胀为4个字节,所以先乘8再乘4。
算完寄存器的偏移就要计算位的偏移了,前面算出的其实是每个寄存器0位的偏移量,而 n 表示位号,每位膨胀为4个字节,所以乘4。
最后加上GPIO对应别名区的首地址 0x42000000 ,就可以算出寄存器某位对应别名区的地址了。
同理,SRAM的计算公式只是把对应别名区首地址修改
AliasAddr = 0x22000000 + (A-0x40000000)*8*4+n*4
统一公式
( (addr & 0xF0000000) +0x02000000+ ( (addr & 0x00FFFFFF)<<5 ) + bitnum<<2 )
addr 是要操作的为所在寄存器的地址
bitnum 位号,在寄存器的第几位。
公式解释:
addr & 0xF0000000 留下最高位的数字,再加上0x02000000 就可以得到二者分别公式中的第一项。
addr & 0x00FFFFFF 去除最高的两位,算出寄存器地址和基地址的偏移, <<5 左移5位即为乘32。
bitnum<<2 左移2位即为乘4。
开始编程
使用位带操作,完成按下按键LED点亮和熄灭的操作。电路图如下。
首先,检测按键,要用到GPIO的输入功能,先配置端口输入模式,再读取寄存器 IDR 就可以知道IO端口电平变化。
点亮led灯必须先配置IO输出模式,再对ODR或BRR,BSRR操作即可置位和清零。
第一,制作一个计算器,可以帮对上面位带操作的公式计算
#define SetBit(addr,n) *(unsigned int*)
((addr & 0xF0000000) +0x02000000+
( (addr & 0x00FFFFFF)<<5 ) + (n<<2))
使用一个带参宏就可以完成这个工作。传入 addr 为寄存器的地址, n 为位在寄存器中的位置。
为了检测代码可行性,先尝试对IDR寄存器的读取,以便判断按键是否按下,和对 ODR 的置位,以便点亮LED灯。而对GPIO输入输出的配置沿用之前固件库编程的代码。
一下为检测按键按下的代码
#define GPIOA_IDR GPIOA_BASE + 0x08
#define SetBit(addr,n) *(unsigned int*)((addr & 0xF0000000) +0x02000000+ ( (addr & 0x00FFFFFF)<<5 ) + (n<<2))
int main(void)
{
while(1)
{
if(SetBit(GPIOA_IDR,0) == 1)
{
while(SetBit(GPIOA_IDR,0) == 1);
LED_G_TOGGLE;
}
}
}
GPIOA_BASE 是固件库中GPIOA 的基地址,0x08 是参考手册中的地址偏移,二者相加就是 GPIOA 的 IDR 寄存器的基地址。
if语句检测按下,while语句检测松手。要注意的是,要读取的位是 0 位,这点要注意。最后用一个宏定义 LED_G_TOGGLE 完成led灯的反转。
LED_G_TOGGLE的宏定义如下:
#define GPIOB_ODR GPIOB_BASE + 0x0C
#define SetBit(addr,n) *(unsigned int*)((addr & 0xF0000000) +0x02000000+ ( (addr & 0x00FFFFFF)<<5 ) + (n<<2))
#define LED_G_TOGGLE {SetBit(GPIOB_ODR,0) ^= 1;}
使用异或运算完成对这一位的反转。
完整的代码如下:
#define GPIOA_IDR GPIOA_BASE + 0x08
#define GPIOB_ODR GPIOB_BASE + 0x0C
#define SetBit(addr,n) *(unsigned int*)((addr & 0xF0000000) +0x02000000+ ( (addr & 0x00FFFFFF)<<5 ) + (n<<2))
#define LED_G_TOGGLE {SetBit(GPIOB_ODR,0) ^= 1;}
int main(void)
{
KEY_GPIO_Config();//配置输入端口为浮空,50M,Pin0
LED_GPIO_Config();//配置输出端口为推挽,50M,Pin0
while(1)
{
if(SetBit(GPIOA_IDR,0) == KEY_ON)
{
while(SetBit(GPIOA_IDR,0) ==KEY_ON);
LED_G_TOGGLE;
}
}
}
其中使用固件库配置端口输入输出模式的
KEY_GPIO_Config() 和LED_GPIO_Config() 代码这里不再展示。
上一篇:STM32固件库的小结
下一篇:STM32 SysTick小结
推荐阅读最新更新时间:2024-11-11 11:49
推荐帖子
- 疑惑,关于触摸板在控制windows媒体播放器
- 今天刚拿到触摸板,就迫不及待的去用一下什么效果,在操作windows媒体播放器时(默认的媒体播放器),用触控操作怎么不能操作windows媒体播放器,反倒把酷狗播放器打开了,对酷狗进行的触摸操作疑惑,关于触摸板在控制windows媒体播放器原帖由yunhaiking于2011-10-917:12发表今天刚拿到触摸板,就迫不及待的去用一下什么效果,在操作windows媒体播放器时(默认的媒体播放器),用触控操作怎么不能操作windows媒体播放器,反倒把酷狗播放器打开了,对酷狗
- yunhaiking 微控制器 MCU
- 加法器为什么不能通过编译呢
- 用DSPBuilder设计16阶FIR滤波器,4个4阶级联一起的,结果最后16阶的加法器就出现下面错误,而4阶的加法器是正确的,谁知道怎么解决啊,我输入数据时9位,输出时20位。提示错误信息:ErrorreportedbyS-function\'sGeneric\'in\'fir16/ParallelAdderSubtractor\':Couldnotinferatypeforportfir16/ParallelAdderSubtractor:d
- eeleader FPGA/CPLD
- avr应用开发实例
- avr应用开发实例avr应用开发实例谢谢,正在学习谢谢啦学习中,谢谢楼主分享了!十分感谢顶楼主,谢谢了。看看后在评论谢谢楼主了!!!!!!!!!对应的书能发上来就好了收藏了。正在复习,AVR,谢谢你。谢谢。多谢了板子虽然用不上,但是感谢楼主共享!~板子虽然用不上,但是感谢楼主共享!~板子虽然用不上,但是感谢楼主共享!~谢谢分享谢谢楼主的贡献谢谢非常感谢学习中是不是说明一下大体内容啊正在学习avr谢谢分享哟西把错吧错,学习学习谢谢,看看
- ahshan Microchip MCU
- #以拆会友#-拆解一多功能台灯及简易的改造
- #以拆会友#-拆解一多功能台灯及简易的改造1这是九十年代后期集疝离子灯照明和吹出清新高压负离子微风的造型和收纳适宜的一款台灯,疝离子灯管一坏便遭淘汰;其外观和机身尚好,可將现有先进技术等替换集成其内,必不可练练手还有新的收获。拆解一番,看其内脏,其内由220伏电源转疝离子灯电源、负离子电源及负离子放电装置、清新风扇、转换开关等组装,电路还是较为简单(待续)#以拆会友#
- bjwl_6338 以拆会友
- 请教:SP485REN-L/TR频繁损坏原因
- 大家好,请教一个关于485的问题。整个设备是金属外壳,用于船用发电机组发电机状态的监控。金属外壳外壳链接一根保护地线经由主设备PCB上的连接器连接到外部,与电源地和信号地没有电气连接。该485网络有五个节点,其中两个节点配置了120欧姆的终端电阻,每个节点上的A都加1K下拉电阻,B都连接1K上拉电阻。每个485节点的布线都很短,不超过50厘米(由于节点都在金属外壳内,因此没有使用隔离方案),四个从设备的电源均来自主设备。请教:SP485REN-L/T
- chenzhouyu 模拟电子
- 电感分裂式推挽换向软开关技术的研究
- 摘要:提出一种电感分裂式推挽换向软开关电路,分析该电路的工作原理及实现软开关的条件,仿真结果表明该电路控制简单、性能可靠,特别适用于中、小功率场合。关键词:电感分裂式推挽换向软开关仿真推挽电路因控制简单、无直通现象等优点,在中、低电压输入变换器中得到广泛应用,但推挽电路中两个开关管处于硬开关状况,随着开关频率的增高,开通功耗较大。桥臂换向软开关在桥式变换器(包括半桥变换器)中得到广泛应用,如移相全桥软开关电路,但桥臂换向软开关无法在推挽电路中应用,虽然文献,对推挽软开关作过探讨,
- zbz0529 PCB设计
设计资源 培训 开发板 精华推荐
- LT6656BCDC-5、5V 精密电流和升压电压基准的典型应用
- AND8159/D, 使用压扩器NE570/SA571进行快起慢速硬限幅器的应用电路
- ACPL-798J 评估板套件,带(PMOD Type-1 接口)使用带 LVDS 接口的 ACPL-798J 隔离式 Sigma-Delta 调制器
- 【ART-Pi】FPGA虚拟扩展板-403619A
- 用于完整 3V、12 位、1MHz 模数转换系统的 AD8604ARZ 运算放大器的典型应用
- lm2596通用 固定电压/可调
- 符合 IrDA 标准的发射器/接收器
- 用于处理器电源管理的 1.2 至 3.5V DC 至 DC 多输出电源
- 用于消费电子产品的 100W、24V 交流转直流单路输出电源
- LTC6259HMS 1.3MHz、20uA 高功率高效轨至轨 I/O 运算放大器的典型应用