STM32读写内部FLASH&读取芯片id

文章目录

  • 读写内部Flash
  • 接线
  • 程序编写
  • 测试效果
  • 补充
  • 读取芯片id
  • 代码编写

  • 读写内部Flash

    接线

    程序编写

    首先使用ThisFlash.c来写入flash的基本操作,写入、读取、擦除,然后使用Store.c配合数组来进行主存与flash的交互
    ThisFlash.c

    #include "stm32f10x.h"                  // Device header
    /**
      * @brief  读取此地址一个字的数据
      * @param 	Address,页地址
      * @retval 此地址的一个字的数据
      */
    uint32_t ThisFlash_ReadWord(uint32_t Address){
    	return *((__IO uint32_t *)(Address));
    }
    /**
      * @brief  读取此地址的半字数据
      * @param 	Address,页地址
      * @retval 此地址的半字数据
      */
    uint16_t ThisFlash_ReadHalfWord(uint32_t Address){
    	return *((__IO uint16_t *)(Address));
    }
    /**
      * @brief  读取此地址一个字节的数据
      * @param 	Address,页地址
      * @retval 此地址的一个字节的数据
      */
    uint8_t ThisFlash_ReadByte(uint32_t Address){
    	return *((__IO uint8_t *)(Address));
    }
    /**
      * @brief  擦除整页数据
      * @param 	无
      * @retval 无
      */
    void ThisFlash_EraseAllPages(void){
    	FLASH_Unlock();	// 解锁
    	FLASH_EraseAllPages();	// 擦除所有页
    	FLASH_Lock();		// 重新上锁
    }
    /**
      * @brief  擦除指定页数据
      * @param 	无
      * @retval 无
      */
    void ThisFlash_ErasePage(uint32_t PageAddress){
    	FLASH_Unlock();	// 解锁
    	FLASH_ErasePage(PageAddress);	// 擦除指定页
    	FLASH_Lock();		// 重新上锁
    }
    /**
      * @brief  指定地址写入一个字的数据
      * @param 	Address,页地址		Data,数据
      * @retval 无
      */
    void ThisFlash_PragramWord(uint32_t Address,uint32_t Data){
    	FLASH_Unlock();	// 解锁
    	FLASH_ProgramWord(Address,Data);	// 指定地址写入一个字的数据
    	FLASH_Lock();		// 重新上锁
    }
    /**
      * @brief  指定地址写入半字数据
      * @param 	Address,页地址		Data,数据
      * @retval 无
      */
    void ThisFlash_PragramHalfWord(uint32_t Address,uint16_t Data){
    	FLASH_Unlock();	// 解锁
    	FLASH_ProgramHalfWord(Address,Data);	// 指定地址写入一个字的数据
    	FLASH_Lock();		// 重新上锁
    }
    
    

    ThisFlash.h

    #ifndef __THISFLASH_H
    #define __THISFLASH_H
    uint32_t ThisFlash_ReadWord(uint32_t Address);
    uint16_t ThisFlash_ReadHalfWord(uint32_t Address);
    uint8_t ThisFlash_ReadByte(uint32_t Address);
    void ThisFlash_EraseAllPages(void);
    void ThisFlash_ErasePage(uint32_t PageAddress);
    void ThisFlash_PragramWord(uint32_t Address,uint32_t Data);
    void ThisFlash_PragramHalfWord(uint32_t Address,uint16_t Data);
    
    #endif
    
    

    store.c

    #include "stm32f10x.h"                  // Device header
    #include "ThisFlash.h"
    
    // 用于与flash交互的数组,存储与ram中
    uint16_t Store_Data[512];
    
    
    /**
      * @brief  初始化最后一页
      * @param 	无
      * @retval 无
      */
    void Store_Init(void){
    	// 使用最后一页第一个半字作为是否为第一次写入的标志位
    	if(ThisFlash_ReadHalfWord(0x0800fc00) != 0xa5a5){
    		ThisFlash_ErasePage(0x0800fc00); 	// 第一次写入,擦掉此页数据
    		ThisFlash_PragramHalfWord(0x0800fc00,0xa5a5);		// 写入标志位
    		for(uint16_t i=1;i<512;i++){
    			ThisFlash_PragramHalfWord(0x0800fc00+i*2,0x0000);		
    		}
    	}
    	
    	for(uint16_t i=0;i<512;i++){
    		Store_Data[i] = ThisFlash_ReadHalfWord(0x0800fc00+i*2);		// 写入标志位
    	}
    }
    /**
      * @brief  备份Store_Data到flash
      * @param 	无
      * @retval 无
      */
    void Store_Backup(void){
    	ThisFlash_ErasePage(0x0800fc00);
    	for(uint16_t i=0;i<512;i++){
    		ThisFlash_PragramHalfWord(0x0800fc00+i*2,Store_Data[i]);		// 写入标志位
    	}
    }
    /**
      * @brief  擦除Store_Data并备份到flash
      * @param 	无
      * @retval 无
      */
    void Store_Clear(void){
    	for(uint16_t i=0;i<512;i++){
    		Store_Data[i] = 0x0000;		// 写入标志位
    	}
    	Store_Backup();		// flash同步清空
    }
    
    

    store.h

    #ifndef __STORE_H
    #define	__STORE_H
    extern uint16_t Store_Data[512];
    void Store_Init(void);
    void Store_Backup(void);
    void Store_Clear(void);
    
    #endif
    
    

    button.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    
    /**
      * @brief  初始化Button相关端口
      * @param 	无
      * @retval 无
      */
    void Button_Init(void){
    	// 初始化时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
    	GPIO_Init(GPIOB, &GPIO_InitStructure);
    }
    /**
      * @brief  返回所按按键值
      * @param 	无
      * @retval KeyNum 按键值
      */
    uint8_t Key_Num(void){
    	uint8_t KeyNum = 0;
    	if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0){
    		Delay_ms(20);
    		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0);
    		Delay_ms(20);
    		KeyNum = 1;
    	}
    	if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0){
    		Delay_ms(20);
    		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0);
    		Delay_ms(20);
    		KeyNum = 11;
    	}
    	return KeyNum;
    }
    
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "OLED.h"
    #include "Store.h"
    #include "button.h"
    
    uint8_t KeyNum;
    
    int main(void)
    {
    	OLED_Init();
    	Button_Init();
    	Store_Init();
    
    	
    	// 为了不影响芯片的其他功能,在flash最后一页写入数据来测试
    
    	while (1)
    	{
    		KeyNum = Key_Num();
    		if(KeyNum == 1){
    			Store_Data[1] = 0x1314;
    			Store_Data[3] = 0X3344;
    			Store_Backup();
    		}
    		if(KeyNum == 11){
    			Store_Clear();
    		}
    		OLED_ShowHexNum(1,1,Store_Data[1],4);
    		OLED_ShowHexNum(2,1,Store_Data[3],4);	
    		OLED_ShowString(3,1,"Flag:");
    		OLED_ShowHexNum(3,7,Store_Data[0],4);
    	}
    }
    
    

    测试效果

    下载程序后按下b11的按键最后一页数据清零,使用ST-LINK Utility查看

    然后按下复位键,初始化函数执行,标志位置a5a5(为小端对齐反式)

    然后按下b1按键,写入数据到数组并备份到flash,并且掉电不丢失

    补充

    还可以根据所需要的闪存空间来设置留给程序的闪存大小

    读取芯片id

    代码编写

    根据手册给出的器件id地址一一使用指针读取

  • 显示闪存大小

  • 显示uid

    main.c内容如下:

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "OLED.h"
    
    int main(void)
    {
    	OLED_Init();
    	
    	OLED_ShowString(1,1,"F_Size:");
    	OLED_ShowHexNum(1,8,*((__IO uint16_t *)(0x1FFFF7E0)),4);
    	
    	OLED_ShowString(2,1,"U_ID:");
    	OLED_ShowHexNum(2,8,*((__IO uint16_t *)(0x1FFFF7E8)),4);
    	OLED_ShowHexNum(2,11,*((__IO uint16_t *)(0x1FFFF7E8+0x02)),4);
    	
    	OLED_ShowHexNum(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x04)),8);
    	
    	OLED_ShowHexNum(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x08)),8);
    	while (1)
    	{
    		
    	}
    }
    
    


    作者:CC Cian

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32读写内部FLASH&读取芯片id

    发表回复