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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1058|回復: 9
收起左側

25Q32怎么跟二分法查找結合起來用?

[復制鏈接]
回帖獎勵 30 黑幣 回復本帖可獲得 3 黑幣獎勵! 每人限 1 次
ID:777254 發表于 2024-8-15 18:23 | 顯示全部樓層 |閱讀模式
1.25Q32中保留N條記錄,每條記錄包含時間加數據,時間是順序保存的。(數據量很大,Mbyte級別,不能讀到RAM中操作)
2.上位機發送指定時間加次數M,要求上報指定時間后的M次記錄。

想到的是二分法查找,不知道怎么結合用?大佬們還有更好的方法嗎?
回復

使用道具 舉報

ID:309610 發表于 2024-8-16 10:34 | 顯示全部樓層
我提交GPT給的方案可以參考一下
你提到的需求是在一個大數據文件中查找指定時間后的N條記錄,由于數據量較大,無法將整個文件加載到內存中,直接在磁盤上進行操作。二分法結合順序讀取是一個合理的解決方案,以下是具體步驟:1. 二分查找定位指定時間由于時間是按順序保存的,二分查找可以幫助我們快速定位到接近目標時間的記錄。讀取文件頭和尾部的記錄,通過它們的時間值計算中間位置(假設你可以通過文件指針直接跳到中間的位置)。二分查找:將中間位置的時間與目標時間進行比較。如果目標時間大于當前時間,繼續在后半部分查找;反之在前半部分查找。重復這個過程,直到找到目標時間或最接近目標時間的位置。2. 順序讀取N條記錄一旦找到了目標時間的位置,接下來需要順序讀取指定數量的記錄。將文件指針移到二分查找到的位置,順序讀取接下來的N條記錄。由于時間是順序排列的,所以直接讀取M次就可以獲得所需數據。

總結使用二分查找快速定位到目標時間的記錄。順序讀取目標時間之后的N條記錄。這種方法的優勢在于只需要在磁盤上進行有限的讀取操作,避免了全量讀取數據到內存中,可以有效處理大規模數據文件。

在STM32平臺上使用C語言進行二分查找并讀取指定時間后的記錄,結合存儲器25Q32,可以參考以下方案:1. 環境準備Flash類型: 25Q32是一種SPI Flash存儲器。你需要在STM32上配置SPI接口,確保可以通過SPI協議訪問25Q32存儲器。文件系統或裸操作: 如果數據是按照某種結構直接存儲在Flash中的,你可能需要裸操作Flash存儲器,即通過特定的SPI指令讀取數據。2. 數據組織假設每條記錄的格式如下:struct Record {
    uint32_t timestamp; // 時間戳,假設是4字節
    uint8_t data[DATA_LENGTH]; // 數據部分
};假設每條記錄長度固定為RECORD_SIZE。3. 二分查找算法實現為了從大文件中高效找到指定時間點后的數據,可以通過二分查找確定目標時間的起始位置。以下是步驟:3.1 計算記錄總數你可以通過Flash的總容量除以每條記錄的大小來計算出記錄總數。#define FLASH_SIZE (4 * 1024 * 1024)  // 25Q32容量 4MB
#define RECORD_SIZE sizeof(struct Record)

uint32_t total_records = FLASH_SIZE / RECORD_SIZE;3.2 實現二分查找二分查找用于找到指定時間戳的位置。uint32_t binary_search(uint32_t target_time) {
    uint32_t low = 0;
    uint32_t high = total_records - 1;
   
    while (low <= high) {
        uint32_t mid = (low + high) / 2;
        struct Record record;
        read_record(mid, &record); // 從flash讀取第mid條記錄
        
        if (record.timestamp < target_time) {
            low = mid + 1;
        } else if (record.timestamp > target_time) {
            high = mid - 1;
        } else {
            return mid; // 找到精確時間
        }
    }
   
    return low; // 沒有精確匹配,返回最接近的記錄位置
}3.3 從指定位置讀取M條記錄找到目標位置后,可以順序讀取接下來的M條記錄。void read_next_n_records(uint32_t start_index, uint32_t n) {
    for (uint32_t i = 0; i < n; ++i) {
        struct Record record;
        read_record(start_index + i, &record); // 讀取并處理記錄
        // process_record(&record);
    }
}4. SPI Flash讀操作實現在STM32上實現SPI讀取25Q32 Flash中的數據,需要使用STM32的HAL庫或直接操作寄存器。4.1 SPI Flash讀記錄的實現void read_record(uint32_t index, struct Record *record) {
    uint32_t address = index * RECORD_SIZE;
   
    // 使用SPI讀取數據
    uint8_t cmd[4];
    cmd[0] = READ_COMMAND;           // 讀取命令(通常為0x03)
    cmd[1] = (address >> 16) & 0xFF; // 地址高字節
    cmd[2] = (address >> 8) & 0xFF;  // 地址中字節
    cmd[3] = address & 0xFF;         // 地址低字節
   
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET); // 拉低片選(CS)
    HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);       // 發送讀命令和地址
    HAL_SPI_Receive(&hspi1, (uint8_t*)record, RECORD_SIZE, HAL_MAX_DELAY); // 讀取數據
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);   // 拉高片選(CS)
}5. 總結使用二分查找算法在SPI Flash中查找指定時間戳的位置。從該位置開始順序讀取指定數量的記錄。在STM32上通過SPI接口實現對25Q32的讀操作。這個方案在STM32平臺上效率較高,能夠處理大規模數據存儲器中的查找和讀取操作。
回復

使用道具 舉報

ID:910662 發表于 2024-8-16 11:07 | 顯示全部樓層
如果時間是均勻的,計算即可;如果是隨機的,除了二分法,還有黃金分割法更優,你不妨試試。不過Mbyte也不是很大,二分法也不錯。
回復

使用道具 舉報

ID:777254 發表于 2024-8-16 11:53 | 顯示全部樓層
dhjmw 發表于 2024-8-16 11:07
如果時間是均勻的,計算即可;如果是隨機的,除了二分法,還有黃金分割法更優,你不妨試試。不過Mbyte也不 ...

時間不是規律增加的,因為外部可以設置這個時間間隔,間隔在1-99內。
回復

使用道具 舉報

ID:844772 發表于 2024-8-19 15:12 | 顯示全部樓層
1、我覺得二分法就不錯的;
2、但更建議使用插值法,因為雖然時間間隔可調但估計不會頻繁調整所以時間隨機性不那么大適合插值法;
3、前邊提的黃金分割法是不是需要構建斐波那契數列啊,這在單片機上需要消耗不少內存啊;
4、如果插值法不能滿足要求,還可以試試先用分塊法粗篩,再用插值法。
回復

使用道具 舉報

ID:777254 發表于 2024-8-19 20:36 | 顯示全部樓層
glinfei 發表于 2024-8-19 15:12
1、我覺得二分法就不錯的;
2、但更建議使用插值法,因為雖然時間間隔可調但估計不會頻繁調整所以時間隨機 ...

目前遇到個難題,就是在FLASH空間內,如果存儲到盡頭,會從起始地址開始覆蓋回滾覆蓋存,這樣就會出現整個存儲空間,地址從小到大的數據,其記錄的時間并不是按先后順序的,總不能把所有記錄數據讀出來排序吧
回復

使用道具 舉報

ID:1034262 發表于 2024-8-20 15:42 | 顯示全部樓層
二分法用于間隔恒定的單調參數有效,時間順序雖然單調,但是間隔不恒定,效果欠佳,但還是可以用。
更好的辦法是時間和數據分開存放(類似電腦文件系統的目錄項、鏈表、數據),特別是數據比較大時特別有效,讀出時間查找,然后讀出對應的數據、
回復

使用道具 舉報

ID:844772 發表于 2024-8-21 08:56 | 顯示全部樓層
li1069136863 發表于 2024-8-19 20:36
目前遇到個難題,就是在FLASH空間內,如果存儲到盡頭,會從起始地址開始覆蓋回滾覆蓋存,這樣就會出現整 ...

運行一段時間,必然一直按你說的這種情況存儲,可以理解順序是 CDAB ,A<B<C<D,而且C=B+1;如果沒有做數據索引,那就先看在AB段還是在CD段 即(X>C還是X<B),然后再二分法去找,當然分后的新中點要先對分段,比如X在AB段,二分后的新點E如果大于B,那就丟棄再找。這里有很多可以優化的地方,比如利用一次是刪除多少等條件,迅速發現DA點,及其X是否在記錄中;或者刪除舊數據時直接記錄一下,可以省不少時間。
回復

使用道具 舉報

ID:777254 發表于 2024-8-21 14:19 | 顯示全部樓層
glinfei 發表于 2024-8-21 08:56
運行一段時間,必然一直按你說的這種情況存儲,可以理解順序是 CDAB ,A

是做了索引,索引保存的是記錄的總次數,還有最新的一條記錄跟基地址的偏移量,主要是這兩個變量。我先按照你的思路捋一下
回復

使用道具 舉報

ID:844772 發表于 2024-8-21 15:51 | 顯示全部樓層
li1069136863 發表于 2024-8-21 14:19
是做了索引,索引保存的是記錄的總次數,還有最新的一條記錄跟基地址的偏移量,主要是這兩個變量。我先按 ...

那就相當于分兩個塊,分別搜索啊,但有個問題,查找A的偏移要注意,因為刪除是按頁面刪的,所以會有空白區,可以理解DA之間有空白區,
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表