BD网盘链接:
https://pan.baidu.com/s/1dmtMWcK1TII-vutsS8X0Og?pwd=5wwy
提取码:5wwy
概述
CW32L052内部集成了64KB嵌入式FLASH供用户使用,可用来存储应用程序和用户数据 。
芯片支持对 FLASH 存储器的读、擦除和写操作,支持 擦写保护和读保护 。
芯片内置 FLASH 编程所需的高压 BOOST 威廉希尔官方网站 , 无须额外提供编程电压 。
FLASH存储器组织
- 总容量64KB,分页管理
- 每页 512 字节
- 共 128 页
FLASH存储器保护
FLASH 存储器具有擦写保护和读保护功能。
- 擦写保护
包括锁定页擦写保护和PC 地址页擦写保护,处于保护状态的页面不能被擦写,可避免 FLASH 内容被意外改写。
- 读保护
以整片FLASH为保护对象,不支持单页保护,可避免用户代码被非法读取。
FLASH存储器操作
FLASH 存储器操作包括:读操作、擦除、写(编程)操作。
页擦除
FLASH 的页擦除操作的最小单位为 1 页,即 512 字节。页擦除操作完成后,该页所有地址空间的数据内容均为 0xFF 。
如果对未解锁的 FLASH 页面进行页擦除操作,或者对*正在运行的程序[^1]*进行擦除操作,会操作失败,产生 错误中断标志 。
CW32L052 内部 FLASH 存储器被划分为 128 页,每 8 页对应擦写锁定寄存器的 1 个锁定位 。擦写锁定寄存器的各位域与 FLASH 锁定页面的对应关系如下表所示:
写操作
基于嵌入式 FLASH 的特性,写操作只能将 FLASH 存储器中位数据 由'1'改写为'0' ,不能由'0'改写为'1', 因此在写数据之前先要对对应地址所在页进行擦除操作。
基于以上陈述,总结出以下三个原则:
- 不可对数据位内容为'0'的地址写入
- 不可对锁定区域内的地址写入
- 不可对 PC(程序指针)所在的页的地址写入
读操作
CW32L052 对 FLASH 的读操作支持 3 种不同位宽,可采用直接访问绝对地址方式读取,读取的数据位宽必 须和对应地址边界对齐。
核心代码
//单片机头文件
#include "main.h"
//硬件驱动
#include "gpio.h"
#include "delay.h"
//子程序
void LCD_Configuration(void); //段式LCD配置函数
void LCD_Display(uint16_t dispdata); //段式LCD显示函数
uint8_t FLASH_Erase(void); //FLASH页擦除函数
uint8_t FLASH_Write(uint8_t *ByteData,uint16_t amount); //FLASH写操作函数
int main(void)
{
int i;
int temp8;
uint8_t cnt=0;
uint8_t WriteBuf[256];
LED_Init(); //初始化程序运行情况指示灯
LCD_Configuration(); //配置LCD液晶显示屏
FLASH_Erase(); //页擦除操作
for(i=0;i< 256;i++) //验证是否擦除成功
{
temp8=*((volatile uint8_t*)(512*127+i));
if(temp8!=0xff)
{
while(1)
{
LED2_ON(); //LED2闪烁
Delay_ms(300);
LED2_OFF();
Delay_ms(300);
}
}
}
for(i=0;i< 256;i++) //准备写入FLASH存储器的数据
{
WriteBuf[i]=i;
}
FLASH_Write(WriteBuf,256); //写操作
for(i=0;i< 255;i++) //验证是否写入正确
{
temp8=*((volatile uint8_t*)(512*127+i));
if(temp8!=i)
{
while(1)
{
LED1_ON(); //LED1、LED2同时闪烁指示写入失败
LED2_ON();
Delay_ms(300);
LED1_OFF();
LED2_OFF();
Delay_ms(300);
}
}
}
LED1_ON(); //指示擦除、读、写均成功
LED2_ON();
while(1)
{
LCD_Display(*((volatile uint8_t*)(512*127+cnt))); //LCD上依次显示写入的数据
Delay_ms(500);
cnt++;
}
}
uint8_t FLASH_Erase(void) //页擦除
{
int flag=1;
FLASH_UnlockPages(512*127,512*127);
flag=FLASH_ErasePages(512*127,512*127);
FLASH_LockAllPages();
if(flag!=0)
{
while(1)
{
LED1_ON();
Delay_ms(300);
LED1_OFF();
Delay_ms(300);
}
}
return 0;
}
uint8_t FLASH_Write(uint8_t *ByteData,uint16_t amount) //写操作
{
int flag=1;
FLASH_UnlockPages(512*127,512*127);
flag=FLASH_WriteBytes(512*127,ByteData,amount);
FLASH_LockAllPages();
if(flag!=0)
{
while(1)
{
LED2_ON();
Delay_ms(300);
LED2_OFF();
Delay_ms(300);
}
}
return 0;
}
void LCD_Configuration(void) //段式LCD配置
{
__RCC_LCD_CLK_ENABLE();
RCC_LSI_Enable();
LCD_InitTypeDef LCD_InitStruct = {0};
LCD_InitStruct.LCD_Bias = LCD_Bias_1_3;
LCD_InitStruct.LCD_ClockSource = LCD_CLOCK_SOURCE_LSI;
LCD_InitStruct.LCD_Duty = LCD_Duty_1_4;
LCD_InitStruct.LCD_ScanFreq = LCD_SCAN_FREQ_256HZ;
LCD_InitStruct.LCD_VoltageSource = LCD_VoltageSource_Internal;
LCD_Init(&LCD_InitStruct);
LCD_COMConfig(LCD_COM0 | LCD_COM1 | LCD_COM2 | LCD_COM3, ENABLE);
LCD_SEG0to23Config(LCD_SEG0|LCD_SEG1|LCD_SEG2|LCD_SEG3|LCD_SEG4|LCD_SEG5|LCD_SEG6|LCD_SEG7, ENABLE);
LCD_Cmd(ENABLE);
}
void LCD_Display(uint16_t dispdata) //LCD显示
{
uint16_t DisBuf[10]={NUM0,NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};
LCD_Write(LCD_RAMRegister_0,0x00000000);
LCD_Write(LCD_RAMRegister_1,0x00000000);
if(dispdata< 10)
LCD_Write(LCD_RAMRegister_0,DisBuf[dispdata]);
else if(dispdata< 100)
LCD_Write(LCD_RAMRegister_0,DisBuf[dispdata/10]|DisBuf[dispdata%10]< < 16);
else if(dispdata< 1000)
{
LCD_Write(LCD_RAMRegister_0,DisBuf[dispdata/100]|DisBuf[dispdata/10%10]< < 16);
LCD_Write(LCD_RAMRegister_1,DisBuf[dispdata%10]);
}
else
{
LCD_Write(LCD_RAMRegister_0,0xffffffff);
LCD_Write(LCD_RAMRegister_1,0xffffffff);
}
}
视频演示
补充
FLASH存储器和EEPROM存储器对比
一般性的总结:
使用场景侧重:
审核编辑 黄宇
-
芯片
+关注
关注
455文章
50792浏览量
423495 -
FlaSh
+关注
关注
10文章
1634浏览量
148007 -
存储器
+关注
关注
38文章
7490浏览量
163818 -
CW32
+关注
关注
1文章
203浏览量
636
发布评论请先 登录
相关推荐
评论