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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1779|回復(fù): 13
收起左側(cè)

C語言算法求助,關(guān)于保留最新的N次數(shù)據(jù)

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

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

使用道具 舉報(bào)

ID:1104941 發(fā)表于 2024-6-17 16:45 | 顯示全部樓層
之前簡單的排序可以在數(shù)組實(shí)現(xiàn),但是這個(gè)邏輯感覺不適合在FLASH中操作,因?yàn)橛忠x,擦寫,既花時(shí)間,又要一直擦除會(huì)影響壽命。
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

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

使用道具 舉報(bào)

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

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

使用道具 舉報(bào)

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

目前計(jì)劃是打算使用索引表,索引保存FLASH的偏移地址,每次刪除或者增加數(shù)據(jù),舊偏移索引里面的地址,這樣可以實(shí)現(xiàn)吧
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

單片機(jī)本身工作電流并不大,超級電容可以串聯(lián)一個(gè)100歐的電阻或者是另外加一個(gè)LDO給超級電容充電
充電的電壓不要超過超級電容的耐壓
回復(fù)

使用道具 舉報(bào)

ID:688692 發(fā)表于 2024-6-19 19:31 | 顯示全部樓層
每次存儲(chǔ)扇區(qū)往后移動(dòng),用到最后一個(gè)扇區(qū)再擦除前面的扇區(qū),可以節(jié)約FLASH壽命。循環(huán)滾動(dòng),只要記得上次是從哪里存起的就行了。
回復(fù)

使用道具 舉報(bào)

ID:384109 發(fā)表于 2024-6-19 21:05 | 顯示全部樓層
應(yīng)該不是數(shù)據(jù)存儲(chǔ)區(qū)的操作問題吧,單獨(dú)加個(gè)EEPROM用來存儲(chǔ)指針或鏈表什么的都可以
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: av天天澡天天爽天天av | 国产午夜精品理论片a大结局 | sese视频在线观看 | 日韩综合一区 | 国产精品视频在线观看 | 激情91| 日韩男人天堂 | 国产精品久久久久久久久大全 | 国产欧美一区二区三区久久人妖 | 国产一区二区在线观看视频 | 黄色片在线看 | 色噜噜狠狠色综合中国 | 欧美精品中文字幕久久二区 | 成人福利片 | 欧美群妇大交群中文字幕 | 精品国产欧美 | 高清黄色 | 日韩一区二区av | 亚洲综合一区二区三区 | 亚洲综合在线播放 | 欧美国产亚洲一区二区 | 毛片免费观看 | 国内精品一区二区 | av天天澡天天爽天天av | 精品欧美一区二区三区精品久久 | 亚洲视频一区二区三区 | 国产精品久久在线 | 久久精品国产一区 | 情侣黄网站免费看 | 91精品国产色综合久久 | 精品国产黄色片 | 日韩午夜网站 | 国产精品亚洲一区二区三区在线观看 | 亚洲精品久久久一区二区三区 | 黄色一级特级片 | 黄色在线免费观看 | 欧美日韩精品在线免费观看 | 黄色日本视频 | 九色av| 免费视频二区 | 一级片在线观看 |