<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/單片機知識點總結/directory.html" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
說明
因為用到了STM32F407系列的單片機的flash存儲數據,所以寫了這套程序.
目的是為了在便於存儲.
關於407的Flash
1.F407xxx系列的flash都是這個樣子
STM32F405xx/407xx and STM32F415xx/417xx 也是這樣子
主存儲區總共12個扇區,Sector0 - Sector11;
Sector0 - Sector3 每個扇區是16KB = 16*1024 = 16384字節; 總共4個扇區 = 16384*4=65536字節
Sector4 扇區是64KB = 64*1024 = 65536字節;
Sector5 - Sector11 每個扇區是128KB = 128*1024 = 131072字節; 總共7個扇區 = 131072*7=917504字節
這些扇區加起來總共是1M字節
2.關於flash的擦除
2.1
F407的flash擦除的時候要求每次只能擦除某個扇區;
擦除函數是: FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange)
函數的第一個參數是扇區編號,第二個參數填寫自己芯片的供電電壓范圍.一般都是填寫 VoltageRange_3
2.2 關於怎么獲取這個編號
所以擦除一般都寫成: FLASH_EraseSector(/*獲取地址對應的扇區編號*/STMFLASH_GetFlashSector(要擦除的地址), VoltageRange_3)
2.3 提供給用戶的擦除函數
2.關於flash的寫入
用戶只需要記住,寫入的時候寫的地址必須是4的倍數,最少寫入一個字(4字節)
提供給用戶的寫入函數:(一般的數據咱不直接使用這個函數存儲數據,具體接着往下看)
3.關於flash的讀取
關於本節封裝的Flash寫讀函數思路
1.使用其中一個扇區存儲數據,假設使用11扇區,准備一個固定大小(假設是512)的u32類型的數組用來存儲數據
記住一句話:只要擦除過了的地方,不需要再次擦除就可以寫入數據
在下載程序的時候.默認所有的flash都是已經擦除過的.
2.第一次存儲
把整個數組全部寫到扇區的最前面
3.第二次存儲(不需要擦除,直接寫入就可以,因為后面都已經擦除過了)
把整個數組緊接着寫到后面
4.第三次存儲(不需要擦除,直接寫入就可以,因為后面都已經擦除過了)
把整個數組緊接着寫到后面
5.假設寫到最后了
我后面空了一點是因為定義的數組大小不一樣,不一定正好占滿.
6.接着再寫
檢測不夠了以后,擦除下這個扇區,把數據從頭開始存儲.
源碼使用
1.打開這節的程序
2.使用下面兩個文件
3.提示:存儲數據的時候是把數據放到這個數組里面,然后調用一下刷新函數.
4.存儲數據
flash_helper_init(ADDR_FLASH_SECTOR_11); flash_helper_struct.FlashHelperData[0]=12345; flash_helper_struct.FlashHelperData[1]=6666; flash_helper_update();
5.讀取存儲的數據(直接從數組獲取) 推薦
因為數組里面的值就是存儲在flash里面的,所以直接從數組里面獲取即可
flash_helper_struct.FlashHelperData[0] flash_helper_struct.FlashHelperData[1]
6.讀取存儲的數據(從flash里面獲取),一般用於查看下存儲的對不對
例如,獲取數組的第一位存儲在flash里面的值
u32 data; flash_helper_get(0,&data,1); printf("get0=%d\r\n",data);
例如,獲取數組的第二位存儲在flash里面的值
flash_helper_get(1,&data,1); printf("get1=%d\r\n",data);
例如,獲取多個數據
u32 data_temp[200]; flash_helper_get(0,data_temp,200); for(i=0;i<200;i++){ printf("%d ",data_temp[i]); }
提示:前面兩個是存儲的正常的數據,后面全是0.因為數組除了最后一位是0x55555555,其它位置默認是0
7.單片機一上電,獲取先前存儲的數據
flash_helper_init 函數會把以前的數據緩存到 flash_helper_struct.FlashHelperData 數組.
所以獲取以前存儲的數據只需要從數組里面獲取即可.
推薦使用方式(新建一個falsh_data文件)
1.假設使用數組其中一個位置記錄數據
2.再來一個這種的
3.假設使用數組的其中一個位置記錄四個單字節數據
數組是4字節的,如果當做一個使用就有點浪費了.
為了4字節和單字節快速分離出來,我直接使用了共用體
如果不使用共用體,就要寫什么右移24位,16位,8位啥的轉換為單字節.太麻煩.
關於轉換的詳細使用看下面鏈接文章
單片機模塊化程序: IEEE754規約,浮點數和16進制之間的轉換
用數組的其中一位記錄水位,濕度,XXX,XXXX
//ÉèÖÃˮλ0,ʪ¶È1,xxxÖµ2,xxxxÖµ3 void flash_data_set_water_humidity_xxx_xxxx(char type,char data) { /*ÏȰÑÀïÃæµÄÊý¾ÝÈ«²¿»ñÈ¡³öÀ´*/ union_resolve_value.u32_data = flash_helper_struct.FlashHelperData[2]; if(type==0){//ÉèÖÃˮλ union_resolve_value.char_table[0] = data;/*ÖØÐÂÐÞ¸ÄÏÂˮλ*/ } else if(type==1){//ÉèÖÃʪ¶È union_resolve_value.char_table[1] = data;/*ÖØÐÂÐÞ¸ÄÏÂʪ¶È*/ } else if(type==2){//ÉèÖÃxxxÖµ union_resolve_value.char_table[2] = data;/*ÖØÐÂÐÞ¸ÄÏÂxxxÖµ*/ } else if(type==3){//ÉèÖÃxxxxÖµ union_resolve_value.char_table[3] = data;/*ÖØÐÂÐÞ¸ÄÏÂxxxxÖµ*/ } /*ÖØÐÂÉèÖÃÏÂÈ«²¿Êý¾Ý*/ flash_helper_struct.FlashHelperData[2] = union_resolve_value.u32_data; } //»ñȡˮλ0,ʪ¶È1,xxxÖµ2,xxxxÖµ3 //·µ»Ø255,˵Ã÷´íÎó char flash_data_get_water_humidity_xxx_xxxx(char type,char mode) { u32 value; if(mode) flash_helper_get(2,&value,1); //´ÓfalshÀïÃæ»ñÈ¡ else value = flash_helper_struct.FlashHelperData[2]; /*ת»»*/ union_resolve_value.u32_data = value; if(type==0) return union_resolve_value.char_table[0]; //ˮλ else if(type==1)return union_resolve_value.char_table[1];//ʪ¶È else if(type==2)return union_resolve_value.char_table[2];//xxxÖµ else if(type==3)return union_resolve_value.char_table[3];//xxxxÖµ else return 255; }
//ÑÓʱֻÊDZÜÃâ´òÓ¡µÄÌ«¿ì delay_ms(3000); //ÉèÖÃеÄˮλֵ flash_data_set_water_humidity_xxx_xxxx(0,50); //ÉèÖÃеÄʪ¶ÈÖµ flash_data_set_water_humidity_xxx_xxxx(1,60); /*Ë¢ÐÂÒ»ÏÂÈÃÊý¾Ý´æ´¢µ½flash*/ flash_helper_update(); //ÑÓʱֻÊDZÜÃâ´òÓ¡µÄÌ«¿ì delay_ms(1000); printf("´æ´¢µÄˮλֵ:%d\r\n",flash_data_get_water_humidity_xxx_xxxx(0,0)); printf("´æ´¢µÄʪ¶ÈÖµ:%d\r\n",flash_data_get_water_humidity_xxx_xxxx(1,0));
4.假設需要記錄最大1000個字節的數據
我加大了些緩存,2000個字節
//ÉèÖÃÒ»¸ö×²»µ½1000×Ö½ÚµÄ×Ö·û´® void flash_data_set_1000bytes(char *data,u32 data_len) { //Çå¿Õ memset(&flash_helper_struct.FlashHelperData[3],0,1000); //¸´ÖÆ memcpy(&flash_helper_struct.FlashHelperData[3],data,data_len); } //»ñȡһ¸ö×²»µ½1000×Ö½ÚµÄ×Ö·û´® //data µÄ³¤¶ÈÊÇ1000×Ö½Ú void flash_data_get_1000bytes(char *data,char mode) { if(mode) flash_helper_get(3,(u32*)data,250); //´ÓfalshÀïÃæ»ñÈ¡ else memcpy(data,&flash_helper_struct.FlashHelperData[3],1000); }
移植使用
把下面文件放到自己的工程里面,按照上面的說明使用即可.