在软件开发的过程中不必免出现需要设计到调试参数和保存参数的情况,保存的参数要么是保存到外部的FLASH中或者内部的FLASH芯片中。

        大多数情况下外挂一个Flash会比较占地方。目前我使用的芯片是STM32H743。原本是使用的STM32F407的芯片,后面因为芯片性能的问题,被迫升级了至STM32H743系列。

        注意的是使用STM32H743去读写内部的Flash是不需要STM32CubeMx支持的,一般生成的工程里面会自带stm32h7xx_hal_flash.h文件里面会自带相关的函数。

        从Keil5上面看,芯片的Flash大小应该是2M。目前通过测试发现我只能写FLASH_BANK_1(1M),不能写FLASH_BANK_2(1M)。

#include "bsp_flash.h"

uint32_t FlashWrData[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint32_t FlashRdData[16];

uint8_t STMFLASH_ReadByte(uint32_t Address)
{
	return *((__IO uint8_t *)(Address));
}

uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
	return *(__IO uint32_t *)faddr; 
}

void STMFLASH_Read(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t Len)   	
{
	uint32_t i;
	uint32_t Lenth = Len / sizeof(uint32_t);
	for( i=0; i < Lenth ; i++)
	{
		pBuffer[i] = STMFLASH_ReadWord(ReadAddr);//读取4个字节.
		ReadAddr += 4;//偏移4个字节.	
	}
}

uint8_t STMFLASH_GetFlashSector(uint32_t addr)
{
    if (addr < BANK1_FLASH_SECTOR_1)return 0;
    else if (addr < BANK1_FLASH_SECTOR_2)return 1;
    else if (addr < BANK1_FLASH_SECTOR_3)return 2;
    else if (addr < BANK1_FLASH_SECTOR_4)return 3;
    else if (addr < BANK1_FLASH_SECTOR_5)return 4;
    else if (addr < BANK1_FLASH_SECTOR_6)return 5;
    else if (addr < BANK1_FLASH_SECTOR_7)return 6;
    else if (addr < BANK2_FLASH_SECTOR_0)return 7;
    else if (addr < BANK2_FLASH_SECTOR_1)return 8;
    else if (addr < BANK2_FLASH_SECTOR_2)return 9;
    else if (addr < BANK2_FLASH_SECTOR_3)return 10;
    else if (addr < BANK2_FLASH_SECTOR_4)return 11;
    else if (addr < BANK2_FLASH_SECTOR_5)return 12;
    else if (addr < BANK2_FLASH_SECTOR_6)return 13;
    else if (addr < BANK2_FLASH_SECTOR_7)return 14;
    return 15;
}

bool STMFLASH_Write(uint32_t waddr,uint32_t *pbuf, uint32_t length)
{
  FLASH_EraseInitTypeDef FlashEraseInit;
  HAL_StatusTypeDef FlashStatus = HAL_OK;
	uint32_t SectorError = 0;
  uint32_t  addrx = 0;
  uint32_t  endaddr = 0;
	uint32_t *data_u32 = (uint32_t *)pbuf;
	
	if(waddr < FLASH_BASE || waddr % 4)
	{
		return false;
	}
	
  HAL_FLASH_Unlock();    			/* 解锁 */
  addrx = waddr;           		/* 写入的起始地址 */
  endaddr = waddr + length;		/* 写入的结束地址 */
	if (addrx < 0X1FF00000)
  {
		while (addrx < endaddr)		/* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */
		{
			if (STMFLASH_ReadWord(addrx) != 0XFFFFFFFF)            						/* 有非0XFFFFFFFF的地方,要擦除这个扇区 */
			{
				FlashEraseInit.Banks = FLASH_BANK;															/* STM32H743有Bank0和Bank1*/
				FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;             /* 擦除类型,扇区擦除 */
				FlashEraseInit.Sector = STMFLASH_GetFlashSector(addrx);       	/* 要擦除的扇区 */
				FlashEraseInit.NbSectors = 1;                                   /* 一次只擦除一个扇区 */
				FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;            /* 电压范围,VCC=2.7~3.6V之间!! */
				if (HAL_FLASHEx_Erase(&FlashEraseInit, &SectorError) != HAL_OK)
				{
						return false;						/* 发生错误了 */
				}
			}
			else
			{
				addrx = addrx + 4;
			}
			FLASH_WaitForLastOperation(FLASH_WAITETIME, FLASH_BANK);  
		}
	}
	FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME, FLASH_BANK);   /* 等待上次操作完成 */
	
  if (FlashStatus == HAL_OK)
  {
		while (waddr < endaddr)	  /* 写数据 */
		{
				if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, waddr, (uint64_t)data_u32) != HAL_OK)    /* 写入数据 */
				{
						return false;					  /* 写入异常 */
				}
				waddr += 32;
				data_u32 += 8;
		}
	}
  HAL_FLASH_Lock();				/* 上锁 */

	return true;
}

void Flash_Test(void)
{
	STMFLASH_Write(FLASH_FALG,FlashWrData,sizeof(FlashWrData));
	STMFLASH_Read(FLASH_FALG,FlashRdData,sizeof(FlashWrData));
}
#ifndef __BSP_FLASH_H
#define __BSP_FLASH_H
#include "stdbool.h"
#include "main.h"

#define FLASH_FALG      0x080E0000
#define FLASH_BANK 			FLASH_BANK_1

#define FLASH_BASE_ADDR		(uint32_t)(FLASH_BASE)
#define FLASH_END_ADDR		(uint32_t)(FLASH_END)

#define FLASH_WAITETIME         50000                       /* FLASH等待超时时间 */

/* BANK1 */
#define BANK1_FLASH_SECTOR_0    ((uint32_t)0x08000000)      /* Bank1扇区0起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_1    ((uint32_t)0x08020000)      /* Bank1扇区1起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_2    ((uint32_t)0x08040000)      /* Bank1扇区2起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_3    ((uint32_t)0x08060000)      /* Bank1扇区3起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_4    ((uint32_t)0x08080000)      /* Bank1扇区4起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_5    ((uint32_t)0x080A0000)      /* Bank1扇区5起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_6    ((uint32_t)0x080C0000)      /* Bank1扇区6起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_7    ((uint32_t)0x080E0000)      /* Bank1扇区7起始地址, 128 Kbytes */

/* BNAK2 */
#define BANK2_FLASH_SECTOR_0    ((uint32_t)0x08100000)      /* Bank2扇区0起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_1    ((uint32_t)0x08120000)      /* Bank2扇区1起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_2    ((uint32_t)0x08140000)      /* Bank2扇区2起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_3    ((uint32_t)0x08160000)      /* Bank2扇区3起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_4    ((uint32_t)0x08180000)      /* Bank2扇区4起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_5    ((uint32_t)0x081A0000)      /* Bank2扇区5起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_6    ((uint32_t)0x081C0000)      /* Bank2扇区6起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_7    ((uint32_t)0x081E0000)      /* Bank2扇区7起始地址, 128 Kbytes */

bool STMFLASH_Write(uint32_t waddr,uint32_t *pbuf, uint32_t length);
void STMFLASH_Read(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t Len);

#endif

        测试结果:写入内部Flash的数据和读取出来的数据是一致的。大概率是没有问题!目前这个工程可能是适用STM32H743的芯片。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐