前言
写这篇博客的原因是:我搞不懂STM32的变量到底存到了哪里,是Flash还是RAM?我搞不懂什么时候可以给引脚置位,搞不懂引脚初始化写的地址又是什么?为什么一个控制一个引脚需要写这么多的地址,一个放置引脚数据的地址不就够了吗?
待解决:Q1:什么时候需要划分内存?
存储器
- what:存储器,它是个很广泛的概念,在STM32的总线结构中可以看到,它至少包括FLASH、寄存器、SRAM等。
- 存储器映射是指MCU将一些外设的访问入口放在内存中,当需要访问时,程序员可以用指针的方式去到内存地址所存的位置。STM将4G的内存单元细分成几个Block,每个Block512Kb,注意所划分的地址位数,是4字节的,也就是32位。
寄存器
-
what:寄存器内容不大,可以暂存一些地址、数据、程序。其中存储地址和数据是我们经常用到的。
-
对于引脚的操作:
- 引脚输入(读):直接改
GPIOx_IDR
寄存器的值,一次可读半字。 - 当想要写IO口时需要时序打开相应的时钟,
RCC_APBxENR
- 输出(写):需要进行配置模式与写入数据,配置模式在初始化中即可,利用GPIOx_CRH寄存器。之后可以写数据在GPIOx_ODR中,同样地一次写8字。
- 引脚输入(读):直接改
-
寄存器映射:需要与之前的存储器映射区分,寄存器是用变量来表示地址。如stm32中的定义语句:
#define GPIO_ODR *(unsigned int*) (GPIOB_BASE+0x0C)
FLASH
- FLASH是闪存,常常存放很少需要更改的变量,如IP、WIFI账号密码等。
- 一个闪存被分为多个块(每个64/32K),一个块被分为16个扇区(4K),一个扇区又被分为很多页(256bit/页)。
- 读取半字(一次只能半字,ps:全字有32/64位):
return *(__IO unit 16_t*)address
- 读取全字:先存半字到temp1、temp2,随后
return (temp2<<16)+temp1
- 写操作:包括时钟打开、写入、擦除、保护锁
- 保护锁:在写入/擦除前需要将Flash_CR寄存器的LOCK位 置位S.
- 调用函数时:
FlashClockInit(); /* 初始化Flash控制器时钟 */ FlashErase(InfoB); /* 擦除InfoB,#define InfoB (0x1080) */ FlashWriteByte_P(0x1082,&ByteVar); /* 把0x12写入0x1082 */ FlashWriteWord_P(0x1083,&WordVar); /* 把0xABCD写入0x1082和0x1083 */