欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2771|回復(fù): 13
打印 上一主題 下一主題
收起左側(cè)

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

[復(fù)制鏈接]
回帖獎(jiǎng)勵(lì) 30 黑幣 回復(fù)本帖可獲得 3 黑幣獎(jiǎng)勵(lì)! 每人限 1 次
跳轉(zhuǎn)到指定樓層
樓主
ID:1104941 發(fā)表于 2024-6-17 16:40 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
使用場(chǎng)景:需要在外接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ī)好久沒(méi)碰過(guò)鏈表方面的知識(shí)了,還有其它方法嗎?
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1104941 發(fā)表于 2024-6-17 16:45 | 只看該作者
之前簡(jiǎn)單的排序可以在數(shù)組實(shí)現(xiàn),但是這個(gè)邏輯感覺(jué)不適合在FLASH中操作,因?yàn)橛忠x,擦寫(xiě),既花時(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è)斷電檢測(cè)或者寫(xiě)入動(dòng)作,如果沒(méi)有斷電,最新的數(shù)據(jù)是保留在單片機(jī)上的,不用寫(xiě)入FLASH
把寫(xiě)入FLASH地址的記錄單獨(dú)放到一個(gè)頁(yè)面,每次寫(xiě)入的時(shí)候,把已經(jīng)寫(xiě)入的地址寫(xiě)到這個(gè)頁(yè)面中
數(shù)據(jù)存放在其它的頁(yè)面,頁(yè)面是循環(huán)使用的,比如先寫(xiě)1頁(yè)面,然后是2頁(yè)面
這樣的話,每次寫(xiě)入就只要擦寫(xiě)地址頁(yè)面就可以了
FLASH不是普通存儲(chǔ)器,一個(gè)地址只能寫(xiě)入一次,你想再寫(xiě)入第二次就擦寫(xiě)整個(gè)頁(yè)面了
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

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

使用道具 舉報(bào)

7#
ID:1104941 發(fā)表于 2024-6-18 18:21 | 只看該作者
Y_G_G 發(fā)表于 2024-6-18 09:40
增加一個(gè)斷電檢測(cè)或者寫(xiě)入動(dòng)作,如果沒(méi)有斷電,最新的數(shù)據(jù)是保留在單片機(jī)上的,不用寫(xiě)入FLASH
把寫(xiě)入FLASH地 ...

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

使用道具 舉報(bào)

8#
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)

9#
ID:1080935 發(fā)表于 2024-6-19 08:41 | 只看該作者
是的,但是flash是按扇區(qū)操作的,一次寫(xiě)一個(gè)扇區(qū),而且讀寫(xiě)不快,影響壽命,不建議頻繁讀寫(xiě)。
回復(fù)

使用道具 舉報(bào)

10#
ID:1125920 發(fā)表于 2024-6-19 12:07 | 只看該作者
對(duì)于在外接FLASH上存儲(chǔ)最新的10次數(shù)據(jù),可以采用循環(huán)緩沖區(qū)(環(huán)形隊(duì)列)的方式,這種方法比鏈表更加簡(jiǎn)單高效,非常適合在單片機(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ù)組,通過(guò)一個(gè)指針來(lái)跟蹤最新的數(shù)據(jù)位置,并循環(huán)使用數(shù)組空間。  ### 3. 寫(xiě)入數(shù)據(jù) 每次寫(xiě)入新的數(shù)據(jù)時(shí),將指針移動(dòng)到下一個(gè)位置。如果指針超出數(shù)組范圍,則回到數(shù)組的起點(diǎn)。  ### 4. 讀取數(shù)據(jù) 讀取數(shù)據(jù)時(shí),根據(jù)指針和偏移量來(lái)獲取最新的數(shù)據(jù)。  ### 具體實(shí)現(xiàn) 下面是一個(gè)示例代碼,假設(shè)使用C語(yǔ)言來(lái)實(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;  // 寫(xiě)入數(shù)據(jù)到FLASH的函數(shù) void writeDataToFlash(unsigned int index, const char* data) {     unsigned int address = FLASH_START_ADDRESS + (index * DATA_SIZE);     // 寫(xiě)入數(shù)據(jù)到指定地址,具體的FLASH寫(xiě)入函數(shù)根據(jù)芯片手冊(cè)實(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ù)芯片手冊(cè)實(shí)現(xiàn)     Flash_Read(address, data, DATA_SIZE); }  // 存儲(chǔ)新數(shù)據(jù) void storeNewData(const char* newData) {     // 寫(xiě)入新數(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; // 無(wú)效參數(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寫(xiě)入實(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ù)寫(xiě)入FLASH的指定位置。 - `readDataFromFlash`:從FLASH的指定位置讀取數(shù)據(jù)。 - `storeNewData`:存儲(chǔ)新數(shù)據(jù)到環(huán)形緩沖區(qū),并更新索引。 - `getLatestData`:獲取最新的n次數(shù)據(jù)。  這種方法避免了復(fù)雜的鏈表操作,使用一個(gè)固定大小的數(shù)組來(lái)存儲(chǔ)數(shù)據(jù),通過(guò)簡(jiǎn)單的索引操作實(shí)現(xiàn)數(shù)據(jù)的循環(huán)存儲(chǔ)和讀取,適合單片機(jī)環(huán)境下的使用。
回復(fù)

使用道具 舉報(bào)

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

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表