STM32之内部FLASH例程

#include "stm32f10x.h"
#include <string.h>

/* STM32 内部 FLASH 配置 */
#define STM32_FLASH_SIZE        512	/* 所选STM32的FLASH容量大小(单位为K)  */

#if STM32_FLASH_SIZE < 256
  #define STM_SECTOR_SIZE  1024    /* < 256为1K字节页,  >=256 为2K页 */
#else 
  #define STM_SECTOR_SIZE	 2048
#endif

/* 应用程序区域 */
#define APP_REGION (0x8000000 + 0x80000 - STM_SECTOR_SIZE)

/* RCC时钟配置 */
void RCC_config()
{ 
	ErrorStatus HSEStartUpStatus;

	/* RCC寄存器设置为默认配置 */
	RCC_DeInit();
	/* 打开外部高速时钟 */
	RCC_HSEConfig(RCC_HSE_ON);
	/* 等待外部高速时钟稳定 */
	HSEStartUpStatus = RCC_WaitForHSEStartUp();
	if(HSEStartUpStatus == SUCCESS) 
	{ 
		/* 设置HCLK = SYSCLK */
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
		/* 设置PCLK2 = HCLK */
		RCC_PCLK2Config(RCC_HCLK_Div1);
		/* 设置PCLK1 = HCLK / 2 */
		RCC_PCLK1Config(RCC_HCLK_Div2);
		/* 设置FLASH代码延时 */
		FLASH_SetLatency(FLASH_Latency_2);
		/* 使能预取址缓存 */
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		/* 设置PLL时钟源为HSE倍频9 72MHz */
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
		/* 使能PLL */
		RCC_PLLCmd(ENABLE);
		/* 等待PLL稳定 */
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
		/* 设置PLL为系统时钟源 */
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		/* 等待系统时钟源切换到PLL */
		while(RCC_GetSYSCLKSource() != 0x08);
	}
}

/* 扇区缓冲区 */
static uint8_t flash_buf[STM_SECTOR_SIZE];

/* 读flash */
void read_flash(uint32_t addr, uint8_t *buf, uint16_t size)
{
	uint16_t i;

	for(i = 0; i < size; i++)
	{
		buf[i] = *(__IO uint8_t *)(addr + i);
	}  
} 

/* 写flash */
void write_flash(uint32_t addr, uint8_t *buf, uint16_t size)
{
	uint32_t addr_base;
	uint16_t len;
	uint16_t i;
	
	/* 检查地址合法性 */
	if(addr < FLASH_BASE ||(addr >= (FLASH_BASE + 1024 * STM32_FLASH_SIZE)))
		assert_param(0);

	/* 将数据循环写入flash */
	while(size)	
	{
		/* 扇区基地址 */
		addr_base = (addr / STM_SECTOR_SIZE) * STM_SECTOR_SIZE;
		/* 读出整个扇区内容 */
		read_flash(addr_base, flash_buf, STM_SECTOR_SIZE);
		/* 需要写入的长度 */
		len = ((addr + size) > (addr_base + STM_SECTOR_SIZE)) ? (addr_base + STM_SECTOR_SIZE - addr) : size;
		/* 将需要改变的内容替换掉 */
		memcpy(flash_buf + addr - addr_base, buf, len);
		
		/* 解锁 */
		FLASH_Unlock();
		/* 擦除整片扇区 */
		FLASH_ErasePage(addr_base);
		/* 写使能 */
		FLASH->CR &= FLASH_CR_OPTWRE; 
		/* 重新将内容写入扇区 */
		for(i = 0; i < STM_SECTOR_SIZE / 2; i++, addr_base += 2) /* 从头写到尾 */
			FLASH_ProgramHalfWord(addr_base, *((uint16_t *)flash_buf + i));
		/* 锁定 */
		FLASH_Lock();

		/* 将数据偏移len */
		addr += len;
		buf += len;
		size -= len;
	}
}

int main()
{
	uint8_t buf[5] = {1, 2, 3, 4, 5};
	uint8_t test[5];

	/* 时钟配置 */
	RCC_config();

	write_flash(APP_REGION, buf, 5);
	read_flash(APP_REGION, test, 5);
	
	while(1)
	{

	}
}

猜你喜欢

转载自blog.csdn.net/lushoumin/article/details/87704087