久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1715|回復: 13
收起左側

C語言算法求助,關于保留最新的N次數據

[復制鏈接]
回帖獎勵 30 黑幣 回復本帖可獲得 3 黑幣獎勵! 每人限 1 次
ID:1104941 發表于 2024-6-17 16:40 | 顯示全部樓層 |閱讀模式
使用場景:需要在外接FLASH存儲最新的10次數據,每次存儲的數據有點大(4Kbyte),按照更新的時間排序,次數越小,時間越新。
比如,昨天存完10次后,今天又需要存一次數據了,昨天的次數10舍棄,全部次數往后挪一個單位,今天的次數存在次數1位置。

我能想到的是使用鏈表,但是搞單片機好久沒碰過鏈表方面的知識了,還有其它方法嗎?
回復

使用道具 舉報

ID:1104941 發表于 2024-6-17 16:45 | 顯示全部樓層
之前簡單的排序可以在數組實現,但是這個邏輯感覺不適合在FLASH中操作,因為又要讀,擦寫,既花時間,又要一直擦除會影響壽命。
回復

使用道具 舉報

ID:1080935 發表于 2024-6-18 08:25 | 顯示全部樓層
鏈表和索引表都可以,隊列也可以,控制頭尾,不在頭尾的都是空閑空間。
回復

使用道具 舉報

ID:401564 發表于 2024-6-18 09:40 | 顯示全部樓層
增加一個斷電檢測或者寫入動作,如果沒有斷電,最新的數據是保留在單片機上的,不用寫入FLASH
把寫入FLASH地址的記錄單獨放到一個頁面,每次寫入的時候,把已經寫入的地址寫到這個頁面中
數據存放在其它的頁面,頁面是循環使用的,比如先寫1頁面,然后是2頁面
這樣的話,每次寫入就只要擦寫地址頁面就可以了
FLASH不是普通存儲器,一個地址只能寫入一次,你想再寫入第二次就擦寫整個頁面了
回復

使用道具 舉報

ID:277550 發表于 2024-6-18 10:08 | 顯示全部樓層
使用這樣的方法
固定的第1個位置是保存索引,每次保存完索引+1到第10、復位。表示一下個該寫入的索引。
固定的第2個位置是保存是開始索引。表示從該索引開始讀、到第10回0、讀夠10個。
后面是數據。
這樣讀寫最少。
回復

使用道具 舉報

ID:1104941 發表于 2024-6-18 18:14 | 顯示全部樓層
devcang 發表于 2024-6-18 10:08
使用這樣的方法
固定的第1個位置是保存索引,每次保存完索引+1到第10、復位。表示一下個該寫入的索引。
...

好的,我也有這個思路,在索引里面更改FLASH的地址偏移,指向不同地址,好像指針啊
回復

使用道具 舉報

ID:1104941 發表于 2024-6-18 18:21 | 顯示全部樓層
Y_G_G 發表于 2024-6-18 09:40
增加一個斷電檢測或者寫入動作,如果沒有斷電,最新的數據是保留在單片機上的,不用寫入FLASH
把寫入FLASH地 ...

謝謝,我打算做個外部超級電容了,掉電檢測再保存FLASH,平時保存RAM。目前是舊數據的刪除和新數據的插入有點想不通,還有就是加了電容,上電緩慢又怕出問題,感覺要加復位芯片啊
回復

使用道具 舉報

ID:1104941 發表于 2024-6-18 18:23 | 顯示全部樓層
LaoYuTou 發表于 2024-6-18 08:25
鏈表和索引表都可以,隊列也可以,控制頭尾,不在頭尾的都是空閑空間。

目前計劃是打算使用索引表,索引保存FLASH的偏移地址,每次刪除或者增加數據,舊偏移索引里面的地址,這樣可以實現吧
回復

使用道具 舉報

ID:1080935 發表于 2024-6-19 08:41 | 顯示全部樓層
是的,但是flash是按扇區操作的,一次寫一個扇區,而且讀寫不快,影響壽命,不建議頻繁讀寫。
回復

使用道具 舉報

ID:1125920 發表于 2024-6-19 12:07 | 顯示全部樓層
對于在外接FLASH上存儲最新的10次數據,可以采用循環緩沖區(環形隊列)的方式,這種方法比鏈表更加簡單高效,非常適合在單片機上使用。下面是實現這一方案的步驟:  ### 1. 設計存儲結構 假設每次數據的大小為4Kbyte,需要存儲10次數據,因此需要的存儲空間為40Kbyte。  ### 2. 初始化環形緩沖區 環形緩沖區的概念是使用一個固定大小的數組,通過一個指針來跟蹤最新的數據位置,并循環使用數組空間。  ### 3. 寫入數據 每次寫入新的數據時,將指針移動到下一個位置。如果指針超出數組范圍,則回到數組的起點。  ### 4. 讀取數據 讀取數據時,根據指針和偏移量來獲取最新的數據。  ### 具體實現 下面是一個示例代碼,假設使用C語言來實現這一功能:  ```c #define DATA_SIZE 4096       // 每次數據大小為4Kbyte #define BUFFER_SIZE 10       // 環形緩沖區大小為10 #define FLASH_START_ADDRESS 0x00000000  // 外接FLASH起始地址,根據具體情況修改  // 環形緩沖區的當前索引 unsigned int currentIndex = 0;  // 寫入數據到FLASH的函數 void writeDataToFlash(unsigned int index, const char* data) {     unsigned int address = FLASH_START_ADDRESS + (index * DATA_SIZE);     // 寫入數據到指定地址,具體的FLASH寫入函數根據芯片手冊實現     Flash_Write(address, data, DATA_SIZE); }  // 讀取FLASH中的數據到內存 void readDataFromFlash(unsigned int index, char* data) {     unsigned int address = FLASH_START_ADDRESS + (index * DATA_SIZE);     // 從指定地址讀取數據,具體的FLASH讀取函數根據芯片手冊實現     Flash_Read(address, data, DATA_SIZE); }  // 存儲新數據 void storeNewData(const char* newData) {     // 寫入新數據到當前索引位置     writeDataToFlash(currentIndex, newData);          // 更新索引,循環使用緩沖區     currentIndex = (currentIndex + 1) % BUFFER_SIZE; }  // 獲取最新的n次數據,n從1到10 void getLatestData(unsigned int n, char* data) {     if (n == 0 || n > BUFFER_SIZE) {         return; // 無效參數     }          int index = (currentIndex + BUFFER_SIZE - n) % BUFFER_SIZE;     readDataFromFlash(index, data); }  void Flash_Write(unsigned int address, const char* data, unsigned int size) {     // 具體的FLASH寫入實現 }  void Flash_Read(unsigned int address, char* data, unsigned int size) {     // 具體的FLASH讀取實現 } ```  ### 代碼解釋 - `currentIndex`:記錄當前最新數據在緩沖區中的位置。 - `writeDataToFlash`:將數據寫入FLASH的指定位置。 - `readDataFromFlash`:從FLASH的指定位置讀取數據。 - `storeNewData`:存儲新數據到環形緩沖區,并更新索引。 - `getLatestData`:獲取最新的n次數據。  這種方法避免了復雜的鏈表操作,使用一個固定大小的數組來存儲數據,通過簡單的索引操作實現數據的循環存儲和讀取,適合單片機環境下的使用。
回復

使用道具 舉報

ID:401564 發表于 2024-6-19 12:41 | 顯示全部樓層
bstljq 發表于 2024-6-18 18:21
謝謝,我打算做個外部超級電容了,掉電檢測再保存FLASH,平時保存RAM。目前是舊數據的刪除和新數據的插入 ...

單片機本身工作電流并不大,超級電容可以串聯一個100歐的電阻或者是另外加一個LDO給超級電容充電
充電的電壓不要超過超級電容的耐壓
回復

使用道具 舉報

ID:688692 發表于 2024-6-19 19:31 | 顯示全部樓層
每次存儲扇區往后移動,用到最后一個扇區再擦除前面的扇區,可以節約FLASH壽命。循環滾動,只要記得上次是從哪里存起的就行了。
回復

使用道具 舉報

ID:384109 發表于 2024-6-19 21:05 | 顯示全部樓層
應該不是數據存儲區的操作問題吧,單獨加個EEPROM用來存儲指針或鏈表什么的都可以
回復

使用道具 舉報

ID:1126074 發表于 2024-6-23 22:51 | 顯示全部樓層
在單片機環境下,由于資源有限,使用鏈表可能不是最理想的解決方案,因為它需要額外的內存空間來存儲節點。考慮到數據量較大(4Kbyte)且需要頻繁操作,可以考慮以下幾種方法:  1.  **循環數組(Circular Buffer)**:          *   使用一個固定大小的數組(例如,10個元素,每個元素4Kbyte),數組的最后一個元素和第一個元素相連,形成循環。     *   當新的數據到來時,替換數組的第一個元素(次數為1),然后更新次數(例如,使用一個寄存器記錄當前次數)。     *   當需要訪問數據時,根據次數索引到數組的相應位置。 2.  **堆棧(Stack)**:          *   如果單片機支持堆棧操作,可以使用堆棧來存儲數據和次數。每次新數據到來,將數據壓入堆棧,同時更新堆棧頂部的次數(如果堆棧已滿,可能需要先彈出最舊的數據)。     *   訪問數據時,從堆棧頂部獲取。 3.  **帶計數的順序存儲**:          *   如果內存空間允許,可以將數據和次數連續存儲,每個數據塊后面緊跟著一個表示次數的字節。當新數據到來時,直接插入到數據末尾,次數加1。需要訪問時,根據次數找到對應的數據。 4.  **文件系統(如SD卡)**:          *   如果你的應用支持外部存儲,可以使用文件系統(如FatFS或YottaDB)將數據存儲為文件,每個文件代表一次數據,文件名或文件屬性可以包含次數信息。每次新數據寫入一個新文件,舊文件保持,次數遞增。  在選擇方法時,要考慮單片機的內存限制、操作速度和數據持久性等因素。循環數組和順序存儲通常更適用于資源有限的情況,而堆棧和文件系統則需要更高級的硬件支持。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 中文字幕精品视频 | 久久久精品一区二区三区 | 精久久 | 欧美日韩精品一区 | 日韩字幕一区 | 91精品国产一区二区在线观看 | 成人在线精品视频 | av手机在线| 亚洲精品中文字幕在线观看 | 精品一区二区久久久久久久网站 | 一区二区三区不卡视频 | 成在线人视频免费视频 | 日韩一区二区在线免费观看 | 国产精品久久久久国产a级 欧美日韩国产免费 | 99热精品国产| 国产欧美精品一区二区色综合朱莉 | 久久欧美精品 | 亚洲午夜精品 | 欧美成人免费在线视频 | 国产一区二区自拍 | h视频免费在线观看 | 国产成人综合在线 | 亚洲国产精品一区在线观看 | 国产剧情一区 | 亚洲h色 | 日韩中文字幕在线视频 | 亚洲欧美日韩电影 | 国产精品视频一区二区三 | 国产欧美久久一区二区三区 | 狠狠干网| 免费视频一区二区 | 成人精品福利 | 特黄色一级毛片 | 久久久91精品国产一区二区三区 | 国产精品国产a | 99久热 | 日韩视频一区二区三区 | 日韩成人在线播放 | 欧美一a一片一级一片 | 操操日| 男女羞羞视频免费 |