在单片机中,片内Flash的地址表示方法通常与芯片架构和内存映射方式有关。以下是常见的表示方法及注意事项:

1. 片内Flash地址的基本概念

单片机的Flash存储器用于存储程序代码(Code)、常量数据(const)或用户数据(如EEPROM模拟)。其地址表示方式一般遵循以下规则:

(1) 绝对地址(物理地址)

由芯片厂商定义,在数据手册(Datasheet)或参考手册(Reference Manual)中给出。

例如:

STM32F103 的Flash起始地址为 0x08000000。

ATmega328P 的Flash起始地址为 0x0000(16位地址,但实际物理地址可能更复杂,因为AVR采用哈佛架构)。

(2) 相对地址(偏移地址)

某些情况下,开发者可能使用相对于Flash起始地址的偏移量:

#define FLASH_BASE 0x08000000 // STM32的Flash起始地址

uint32_t* data_address = (uint32_t*)(FLASH_BASE + 0x1000); // 偏移4KB

2. 不同架构的Flash地址表示

(1) ARM Cortex-M(如STM32)

Flash通常映射到 0x08000000(默认启动地址)。

示例:

// 访问Flash的某个地址(如读取前4字节)

uint32_t* flash_addr = (uint32_t*)0x08000000;

uint32_t value = *flash_addr; // 读取数据

(2) AVR(如ATmega系列)

Flash地址是 16位 的(但实际物理地址可能更大,因为Flash可能超过64KB)。

需要使用 pgm_read_byte() 或 pgm_read_word() 访问:

#include

const uint8_t data[] PROGMEM = {0x01, 0x02, 0x03}; // 数据存储在Flash

uint8_t value = pgm_read_byte(&data[0]); // 读取第一个字节

(3) 8051

Flash(CODE空间)通常用 16位地址 访问。

使用 code 关键字定义常量:

uint8_t code my_data[] = {0x01, 0x02, 0x03}; // 数据存储在Flash

uint8_t value = my_data[0]; // 读取数据

3. 如何获取Flash地址?

(1) 查看芯片数据手册

例如:

STM32F103:Flash起始于 0x08000000,每个扇区大小可能为 1KB/2KB。

ATmega328P:Flash起始于 0x0000,但实际物理地址可能涉及分页。

(2) 使用厂商提供的宏

STM32 HAL库提供 FLASH_BASE:

#define FLASH_BASE 0x08000000

(3) 通过链接脚本(Linker Script)定义

在 *.ld 文件中定义Flash的起始和大小:

MEMORY

{

FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K

RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K

}

4. 常见操作

(1) 读取Flash数据

// STM32示例

uint32_t read_flash(uint32_t address) {

return *(__IO uint32_t*)address;

}

(2) 写入Flash(需解锁+擦除+编程)

// STM32 HAL库示例

HAL_FLASH_Unlock();

FLASH_Erase_Sector(FLASH_SECTOR_1, VOLTAGE_RANGE_3);

HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08010000, 0x12345678);

HAL_FLASH_Lock();

(3) 检查Flash是否为空(通常擦除后为0xFF)

bool is_flash_empty(uint32_t address, uint32_t size) {

uint8_t* ptr = (uint8_t*)address;

for (uint32_t i = 0; i < size; i++) {

if (ptr[i] != 0xFF) return false;

}

return true;

}

5. 注意事项

对齐访问:

ARM Cortex-M 通常要求 32位/64位对齐访问,否则可能触发 HardFault。

写保护:

写入Flash前需解锁,并确保目标地址已擦除(通常全为 0xFF)。

哈佛架构(如AVR):

Flash和RAM地址空间独立,不能直接用指针访问,需使用 pgm_read_* 函数。

优化编译:

常量数据可能被编译器优化到Flash,使用 const + PROGMEM(AVR)或 __attribute__((section(".rodata")))(ARM)确保存储位置。

总结

架构Flash起始地址访问方式STM320x08000000直接指针访问AVR0x0000(逻辑)pgm_read_byte/word80510x0000code 关键字

正确理解Flash地址表示方法对固件开发、Bootloader、OTA升级等至关重要,务必参考芯片手册!