00. 目录
文章目录
- 00. 目录
- 01. FLASH概述
- 02. 读写内部FLASH接线图
- 03. 读写内部FLASH相关API
- 04. 读写内部FLASH程序示例
- 05. 读写芯片ID接线图
- 06. 读写芯片ID程序示例
- 07. 程序示例下载
- 08. 附录
01. FLASH概述
STM32F10xxx内嵌的闪存存储器可以用于在线编程(ICP)或在程序中编程(IAP)烧写。
在线编程(In-Circuit Programming – ICP)方式用于更新闪存存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载用户应用程序到微控制器中。ICP是一种快速有效的编程方法,消除了封装和管座的困扰。
与ICP方式对应,在程序中编程(In-Application Programming – IAP)可以使用微控制器支持的任一种通信接口(如I/O端口、USB、CAN、UART、I 2 C、SPI等)下载程序或数据到存储器中。IAP允许用户在程序运行时重新烧写闪存存储器中的内容。然而,IAP要求至少有一部分程序已经使用ICP烧到闪存存储器中。
闪存接口是在AHB协议上实现了对指令和数据的访问,它通过对存储器的预取缓存,加快了存储器的访问;闪存接口还实现了在所有工作电压下对闪存编程和擦除所需的逻辑电路,这里还包括访问和写入保护以及选择字节的控制。
02. 读写内部FLASH接线图
03. 读写内部FLASH相关API
/*------------ Functions used for all STM32F10x devices -----*/
void FLASH_SetLatency(uint32_t FLASH_Latency);
void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess);
void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer);
void FLASH_Unlock(void);
void FLASH_Lock(void);
FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
FLASH_Status FLASH_EraseAllPages(void);
FLASH_Status FLASH_EraseOptionBytes(void);
FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);
FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY);
uint32_t FLASH_GetUserOptionByte(void);
uint32_t FLASH_GetWriteProtectionOptionByte(void);
FlagStatus FLASH_GetReadOutProtectionStatus(void);
FlagStatus FLASH_GetPrefetchBufferStatus(void);
void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState);
FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG);
void FLASH_ClearFlag(uint32_t FLASH_FLAG);
FLASH_Status FLASH_GetStatus(void);
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
04. 读写内部FLASH程序示例
测试程序1
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "flash.h"
int main(void)
{
//初始化
OLED_Init();
//显示一个字符
OLED_ShowChar(1, 1, 'A');
#if 0
//显示字符串
OLED_ShowString(1, 3, "HelloWorld!");
//显示十进制数字
OLED_ShowNum(2, 1, 12345, 5);
//显示有符号十进制数
OLED_ShowSignedNum(2, 7, -66, 2);
//显示十六进制
OLED_ShowHexNum(3, 1, 0xAA55, 4);
//显示二进制数字
OLED_ShowBinNum(4, 1, 0xAA55, 16);
#endif
OLED_ShowHexNum(1, 1, flash_read_word(0x08000000), 8);
OLED_ShowHexNum(2, 1, flash_read_half_word(0x08000000), 4);
OLED_ShowHexNum(3, 1, flash_read_byte(0x08000000), 2);
while(1)
{
}
return 0;
}
测试程序2
flash.h
#ifndef __FLASH_H__
#define __FLASH_H__
#include "stm32f10x.h" // Device header
//存储的开始地址
#define STORE_START_ADDR 0x0800FC00
//存储数据的个数
#define STORE_SIZE 512
extern uint16_t store_data[STORE_SIZE];
uint32_t flash_read_word(uint32_t addr);
uint16_t flash_read_half_word(uint32_t addr);
uint8_t flash_read_byte(uint32_t addr);
//擦除所有的页
void flash_erase_all_pages(void);
//页擦除
void flash_erase_pages(uint32_t page_addr);
//存储初始化
void store_init(void);
//将数据保存到闪存
void store_save(void);
//数据清零
void store_clear(void);
#endif
flash.c
#include "flash.h"
uint16_t store_data[STORE_SIZE];
uint32_t flash_read_word(uint32_t addr)
{
return *((__IO uint32_t *)(addr));;
}
uint16_t flash_read_half_word(uint32_t addr)
{
return *((__IO uint16_t *)(addr));
}
uint8_t flash_read_byte(uint32_t addr)
{
return *((__IO uint8_t *)(addr));
}
//擦除所有的页
void flash_erase_all_pages(void)
{
FLASH_Unlock();
FLASH_EraseAllPages();
FLASH_Lock();
}
//页擦除
void flash_erase_pages(uint32_t page_addr)
{
FLASH_Unlock();
FLASH_ErasePage(page_addr);
FLASH_Lock();
}
//flash编程字
void flash_program_word(uint32_t addr, uint32_t data)
{
FLASH_Unlock();
FLASH_ProgramWord(addr, data);
FLASH_Lock();
}
//flash编程半字
void flash_program_half_word(uint32_t addr, uint16_t data)
{
FLASH_Unlock();
FLASH_ProgramHalfWord(addr, data);
FLASH_Lock();
}
//存储初始化
void store_init(void)
{
uint16_t i;
//判断是不是第一次使用
if (flash_read_half_word(STORE_START_ADDR) != 0xA5A5)
{
flash_erase_pages(STORE_START_ADDR);
flash_program_half_word(STORE_START_ADDR, 0xA5A5);
//清空数据
for (i = 1; i < STORE_SIZE; i++)
{
flash_program_half_word(STORE_START_ADDR + i * 2, 0x0000);
}
}
//上电时候将数据拷贝到数组中
for (i = 0; i < STORE_SIZE; i++)
{
store_data[i] = flash_read_half_word(STORE_START_ADDR + i * 2);
}
}
//将数据保存到闪存
void store_save(void)
{
uint16_t i;
flash_erase_pages(STORE_START_ADDR);
for (i = 0; i < STORE_SIZE; i++)
{
flash_program_half_word(STORE_START_ADDR + i * 2, store_data[i]);
}
}
//数据清零
void store_clear(void)
{
uint16_t i;
for (i = 1; i < STORE_SIZE; i++)
{
store_data[i] = 0x0000;
}
store_save();
}
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "key.h"
#include "flash.h"
int main(void)
{
uint8_t key = 0;
//初始化
OLED_Init();
//按键初始化
key_init();
//显示一个字符
OLED_ShowChar(1, 1, 'A');
#if 0
//显示字符串
OLED_ShowString(1, 3, "HelloWorld!");
//显示十进制数字
OLED_ShowNum(2, 1, 12345, 5);
//显示有符号十进制数
OLED_ShowSignedNum(2, 7, -66, 2);
//显示十六进制
OLED_ShowHexNum(3, 1, 0xAA55, 4);
//显示二进制数字
OLED_ShowBinNum(4, 1, 0xAA55, 16);
#endif
store_init();
//显示字符串
OLED_ShowString(1, 1, "Flag: ");
OLED_ShowString(2,1, "Data: ");
while(1)
{
key = key_scan();
if (1 == key)
{
store_data[1]++;
store_data[2] += 2;
store_data[3] += 3;
store_data[4] += 4;
store_save();
}
if (2 == key)
{
store_clear();
}
OLED_ShowHexNum(1, 6, store_data[0], 4);
OLED_ShowHexNum(3, 1, store_data[1], 4);
OLED_ShowHexNum(3, 6, store_data[2], 4);
OLED_ShowHexNum(4, 1, store_data[3], 4);
OLED_ShowHexNum(4, 6, store_data[4], 4);
}
return 0;
}
05. 读写芯片ID接线图
06. 读写芯片ID程序示例
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
int main(void)
{
//初始化
OLED_Init();
#if 0
//显示一个字符
OLED_ShowChar(1, 1, 'A');
//显示字符串
OLED_ShowString(1, 3, "HelloWorld!");
//显示十进制数字
OLED_ShowNum(2, 1, 12345, 5);
//显示有符号十进制数
OLED_ShowSignedNum(2, 7, -66, 2);
//显示十六进制
OLED_ShowHexNum(3, 1, 0xAA55, 4);
//显示二进制数字
OLED_ShowBinNum(4, 1, 0xAA55, 16);
#endif
OLED_ShowString(1, 1, "F_SIZE");
OLED_ShowHexNum(1, 8, *((__IO uint16_t *)(0x1FFFF7E0)), 4);
OLED_ShowString(2, 1, "U_ID:");
OLED_ShowHexNum(2, 6, *((__IO uint16_t *)(0x1FFFF7E8)), 4);
OLED_ShowHexNum(2, 11, *((__IO uint16_t *)(0x1FFFF7E8 + 0x2)), 4);
OLED_ShowHexNum(3, 1, *((__IO uint16_t *)(0x1FFFF7E8 + 0x4)), 8);
OLED_ShowHexNum(4, 1, *((__IO uint16_t *)(0x1FFFF7E8 + 0x8)), 8);
while(1)
{
}
return 0;
}
07. 程序示例下载
40-读写FLASH.rar
41-读写芯片ID.rar
08. 附录
参考: 【STM32】江科大STM32学习笔记汇总