STM32F429外接16位SDRAM写入1字节的影响及空间优化咨询
问题描述
基于STM32F429ZIT6(32位)项目,外接64MB容量SDRAM(规格为4M*16位),当前通过以下代码访问SDRAM实现LCD镜像功能,代码运行正常:
void LCD_mirror(void) { unsigned long L,p; unsigned int rgbT,rgbB; for(L=0;L<LCD_PIXEL_HEIGHT/2;L++) for(p=0;p<LCD_PIXEL_WIDTH;p++) { rgbT=*(__IO uint16_t*) (CurrentFrameBuffer + ((LCD_PIXEL_HEIGHT-L-1)*LCD_PIXEL_WIDTH)*2 + (2*p) ); rgbB=*(__IO uint16_t*) (CurrentFrameBuffer + (L*LCD_PIXEL_WIDTH)*2 + (2*p) ); *(__IO uint16_t*) (CurrentFrameBuffer + (L*LCD_PIXEL_WIDTH)*2 + (2*p) ) = rgbT; *(__IO uint16_t*) (CurrentFrameBuffer + ((LCD_PIXEL_HEIGHT-L-1)*LCD_PIXEL_WIDTH)*2 + (2*p) ) = rgbB; } }
其中CurrentFrameBuffer为SDRAM Bank 2起始地址(0xD0000000)。现咨询两个问题:
- 若仅向该16位SDRAM单元写入1字节,剩余8位会处于何种状态?
- 如何实现8位与16位数据的写入,同时减少存储空间的浪费?
问题解答
1. 单字节写入时剩余8位的状态
STM32F4的FMC控制器支持对16位宽的SDRAM进行字节级访问。当通过uint8_t指针写入单个字节时,FMC会通过字节掩码(DQM)引脚屏蔽未写入的8位,仅修改目标字节内容,剩余8位会保持原有数值,不会被篡改。
需确保FMC配置正确:在FMC_BCRx寄存器中设置MWID为16位模式,并启用字节掩码功能(对应FMC_BTRx的DQMEN位),否则可能出现异常访问行为。
2. 实现8位/16位混合写入并减少空间浪费
(1)正确的混合访问方式
- 16位数据写入:保持现有代码逻辑,用
__IO uint16_t*指针直接访问SDRAM地址,一次操作对应一个16位单元,无空间浪费,适合RGB565这类16位像素数据。 - 8位数据写入:用
__IO uint8_t*指针访问,利用SDRAM的字节寻址特性(地址最低位A0区分高/低字节),直接操作16位单元中的单个字节,无需额外占用空间。示例:__IO uint8_t* sdram_8ptr = (__IO uint8_t*)CurrentFrameBuffer; sdram_8ptr[0] = 0xAA; // 写入16位单元的低8位 sdram_8ptr[1] = 0xBB; // 写入同一16位单元的高8位
(2)优化空间利用率的技巧
如果项目中存在大量8位类型数据(如灰度图、单色数据),不要将单个8位数据单独占用一个16位单元,而是打包存储:将两个8位数据合并到一个16位单元中,充分利用SDRAM的16位带宽。示例代码:
// 存储两个8位数据到一个16位单元 __IO uint16_t* sdram_16ptr = (__IO uint16_t*)CurrentFrameBuffer; uint8_t data1 = 0xAA; uint8_t data2 = 0xBB; sdram_16ptr[0] = (uint16_t)(data1 << 8) | data2; // data1存高8位,data2存低8位 // 读取时拆分数据 uint8_t read_data1 = (uint8_t)(sdram_16ptr[0] >> 8); uint8_t read_data2 = (uint8_t)(sdram_16ptr[0] & 0xFF);
(3)注意事项
- 避免非对齐访问的性能损耗:STM32F4支持非对齐访问,但16位数据尽量按16位地址对齐(地址为偶数),8位数据无对齐要求。
- 按数据类型分块存储:将8位数据块和16位数据块分开连续存储,避免混合存储导致的地址混乱和空间浪费。
内容的提问来源于stack exchange,提问作者DKhusted
相关产品推荐
相关产品推荐

