把 PLC 數值存成 CSV,再讀回指定紀錄
這次我們先用 SP.FWRITE 把 16 個數值存成 1.CSV 的一列紀錄,再用 SP.FREAD 讀回。你會依序完成資料區設定、檔尾追加、列欄設定,以及讀回比對。
CSV 用逗號分隔欄位、用換行分隔紀錄,存好後可以直接用文字編輯器查看。先做好單次寫入,確認每列都有 16 欄,再加入連續記錄。
| 本次練習 | 設定與目標 |
|---|---|
| 設備與工具 | FX5U、適用的 SD 卡、GX Works3 |
| 寫入 | 將 D101~D116 追加到 1.CSV,每次新增一列 |
| 讀取 | 指定檔名、起始列、欄數與要求數量 |
| 比對方式 | 檢查實際讀取數,再比對時鐘與 108~116 的辨識值 |
圖片可點開查看原尺寸。藍色矩形是 GX Works3 的編輯選取範圍,不代表接點導通。
1 CSV 的列欄與資料型態
例如一列文字 100,200,300 代表三個欄位,不是三個字元。CSV 的檔案大小會隨數字位數、負號、逗號及換行而變動,因此寫入 16 字數值,不代表 CSV 檔案只有 32 bytes。
| 設定 | 形成的資料 |
|---|---|
| D0=H100 | CSV 十進位帶符號 16 位數值寫入,數值解讀範圍為 -32768~32767。 |
| D7=K0 | 來源以字為單位;此專案每掃描重設 D7。 |
| D100=K16 | 本次轉換並寫出 D101~D116,共 16 個數值欄位。 |
| D6=K0 | 不指定分欄數,本次資料寫成單列,即 16 欄一列。 |
| D4:D5=FFFFFFFFH | 寫到檔案尾端。 |
| D3=H0 | 保留正常追加方式;與檔尾設定搭配時,新增下一列。 |
前 7 欄使用 TRD 取得:年、月、日、時、分、秒、星期。後 9 欄 D108~D116 在這段梯形圖未被賦值,會把當時的裝置內容一起寫出;先把這九字填入 108~116,方便稍後比對。
使用文字編輯器確認原始 CSV 再用試算表開啟。試算表可能自動轉換日期、長數字或前導零;畫面看似相同,不代表存回後的文字仍符合 PLC 格式。數值讀取練習不要加入標題列、公式或千分位逗號。
2 操作準備與控制資料表
準備適用的 FX5U、SD 卡、GX Works3 與讀卡機,先備份專案和卡上檔案。請在獨立教學設備確認 CPU 型號與卡片格式;依硬體手冊停止卡片存取後再取卡。
| 裝置 | CSV 寫入設定與用途 |
|---|---|
| D0 | H100:十進位帶符號 16 位轉 CSV |
| D1 | 初始 H0;指令完成後回報狀態碼 |
| D2 | 初始 K0;指令完成後回報實際寫入數 |
| D3 | H0:正常追加,不把最後換行改成逗號 |
| D4、D5 | DMOV H0FFFFFFFF D4;32 位元內容為 FFFFFFFFH |
| D6 | K0:本次 16 個數值寫成一列 |
| D7 | K0:字單位,SM400 每掃描重設 |
| D100 | K16:要求寫入 16 字 |
| D101~D107 | TRD 寫入年、月、日、時、分、秒、星期 |
| D108~D116 | 另 9 字,練習前須明確指定內容 |
D4:D5 是兩字組成的檔案位置,不可只看低字 D4。原指令顯示 H0FFFFFFFF,前導 0 不改變這個 32 位元全 1 的值;以有號十進位監看時會看到 -1。
本篇指令表採 GX Works3 梯形圖的操作數順序。若改用 ST,參數排列必須重新對照 ST 語法,不能直接照抄梯形圖文字順序。
3 設定 CSV 格式與初始狀態
圖 1 CSV 寫入程式第 1~4 列
先在 SM402 分支下把 D0 設為 H100,選擇 CSV 十進位帶符號 16 位模式,再把 D1、D2、D3 清為 0。這些設定會在 RUN 後第一次掃描執行。要切換儲存格式,必須設定 D0,不能只修改副檔名。
D2 為完成後的實際寫入數,不是要求數量。要求寫出多少個數值,要看後面的 D100。每次執行完成應同時核對 D1 與 D2。
4 設定檔尾追加,每次寫一列
圖 2 CSV 寫入程式第 5~8 列
DMOV 將 D4:D5 設為 FFFFFFFFH,選擇檔尾追加;D3=0 表示正常新增下一列。D6=0 代表本次資料只形成一列,不是「沒有資料欄位」。
D100=16 表示來源為 D101~D116。D7 在 SM400 下每掃描設為 0。若把 D4:D5 改成其他值,CSV 寫入會改走從開頭重寫的行為,原檔內容會被清除後重建,不能當成任意列的插入位置。
5 確認啟動條件,執行 FWRITE
圖 3 CSV 寫入程式第 9~12 列,步號 40 與 52 起
M1 上升沿且 SM753=OFF 時,執行 RST M0、RST M100、SET M101。這是取消/重置用的實際邏輯,不能把它當成一次寫入啟動。M3 週期段才會 SET M0。
M0=ON 且 SM606=OFF 時,執行 SP.FWRITE U1 K2 D0 "1" D100 M100。K2 指 SD 卡;"1" 自動成為 1.CSV。完成位是 M100,異常完成位是其下一點 M101。
6 保存完成結果,檢查實際寫入數
圖 4 CSV 寫入程式第 12~15 列,包含完成處理
正常完成時 M100=ON、M101=OFF,程式 SET M150;異常完成時 M100、M101 一起 ON,SET M151。完成分支同時 RST M0,結束這一次執行保持。
M150、M151 沒有自動清除,可能保留不同次的結果。練習前先清除兩位,完成後再核對 D1=0、D2=16。卡片空間不足可能只寫入部分資料,不能只看檔案存在。
7 加入時鐘資料與每秒觸發
圖 5 以 TRD 更新時鐘,透過 M3 與 SM412 觸發寫入
SM400 讓 TRD D101 持續更新七個時鐘欄位。M3=ON 時,SM412 的每次上升沿 SET M0,下一掃描由前段 FWRITE 執行。CSV 已使用檔尾追加,所以這裡沒有 BIN 範例的 DADDP 位置遞增。
M3 週期分支沒有串接 SM753;資料來源又每掃描刷新。開始先做單次測試,正式記錄功能再加入忙碌互鎖與資料快照,確保一次存取完成前不變更正在使用的內容。
8 實作一 建立並檢查 CSV 紀錄
先在教學設備寫一筆資料,再寫第二筆,確認檔尾追加確實保留了第一筆紀錄。
先讓 M3、M1、M0 為 OFF,確認 SM753=OFF、SM606=OFF,並備份既有 1.CSV。
確認 RUN 初始化完成,D0=H100、D3=0、D4:D5=FFFFFFFFH、D6=0、D7=0、D100=16。清除 M150、M151。
將 D108~D116 設為 108~116。D101~D107 由 TRD 提供,不要在這七字設定固定值期待保留。
將 M0 設為 ON 一次,等待本次完成,確認 D1=0、D2=16、M0 已解除,並記錄結果。單次練習不使用 M1,也不開啟 M3。
再做一次同樣的單次觸發。如果原檔已存在,兩次操作應增加兩列,不是取代前一列。
依 CPU 手冊完成停止卡片存取後,使用讀卡機與文字編輯器檢查 1.CSV。每列應有 16 個數值欄位;前七欄為保存時的時鐘,後九欄應為 108~116。
一列的示意內容如下,這只是格式示例,實際日期與時間由 CPU 決定:
2026,9,8,14,30,5,2,108,109,110,111,112,113,114,115,116
不要用「16 字 = 32 bytes」判斷 CSV 大小。數字轉成文字後,還包含逗號、可能的負號及換行;應改用欄數與數值內容檢查。
9 建立讀取程式,改用 SP.FREAD
要把檔案內容讀回 PLC,先在教學副本建立讀取程式,將檔案指令改為 SP.FREAD,並重新設定讀取控制資料。只改專案名稱不會改變程式功能。
圖 6 寫入指令與完成處理;建立讀取程式時須改用 SP.FREAD
上圖雖然以「讀取」命名,實際指令仍是 SP.FWRITE。請先核對指令名稱,再下載讀取程式,避免本來要讀檔卻又追加一筆資料。
接下來先用每列 5 欄的 sample.csv 練習指定列讀取,弄清楚列號與要求數量的關係,再把設定換成剛才寫出的 16 欄 1.CSV。sample.csv 的指令圖取自三菱官方手冊。
10 設定從第 2 列讀取 20 個數值
圖 7 三菱官方手冊 JY997D55801AB 印刷頁 510 的 SP.FREAD 指令局部圖
把讀取起點設為 sample.csv 的第 2 列,每列選取 5 欄,要求讀取 20 個 16 位數值。預留 D101~D120 放結果,並用 D100 查看實際讀取數。依下表設定控制資料,再接上圖中的指令。
| 裝置或參數 | 官方範例值 | 讀取時的意義 |
|---|---|---|
| U、驅動器 | U1、K2 | 虛擬指定與 SD 卡驅動器 |
| D0 | H100 | CSV 十進位 16 位轉換讀取 |
| D1 | 初始 H0 | 完成後的狀態碼 |
| D2 | K20 | 要求讀取 20 個數值 |
| D3 | K0 | 非 ASCII 字串模式固定為 0;實作時應明確確保為 0 |
| D4、D5 | K2 | 從 CSV 第 2 列開始,這裡不是 byte 偏移 |
| D6、D7 | K5、K2 | 每列 5 欄;採用 D0 對應資料單位 |
| 檔名 | "sample.csv" | 指定實際讀取的 CSV 檔 |
| D100、D101 起 | 實際數量、資料 | D100 由指令更新;資料從下一字開始 |
| M100、M101 | 完成、異常完成 | 以 M150、M151 保存結果,再解除 M0 |
11 準備五列資料,執行一次讀取
用 X0 上升沿作為啟動條件,串接 SM753 常閉接點,避免在檔案存取中重複啟動。啟動時 SET M0,RST M100、M101;接著以 M0 與 SM606 常閉接點執行 SP.FREAD。完成時依 M101 區分正常與異常,保存到 M150 或 M151,最後 RST M0。
在獨立測試檔 sample.csv 中準備以下五列,每列五個數值。這份練習檔只用數值,不加入欄位標題。
| 列 | 第 1 欄 | 第 2 欄 | 第 3 欄 | 第 4 欄 | 第 5 欄 |
|---|---|---|---|---|---|
| 1 | 101 | 102 | 103 | 104 | 105 |
| 2 | 201 | 202 | 203 | 204 | 205 |
| 3 | 301 | 302 | 303 | 304 | 305 |
| 4 | 401 | 402 | 403 | 404 | 405 |
| 5 | 501 | 502 | 503 | 504 | 505 |
在教學副本加入 SP.FREAD,依上一節設定 D0~D7,並將檔名設為 "sample.csv"。下載前確認 CPU 型號、指令名稱與 X0 的用途。
先清除 M150、M151 舊結果,確認沒有其他檔案存取,給 X0 一次受控上升沿。
完成後檢查 D1=0、D100=20。D101~D105 應為 201~205,D106~D110 為 301~305。
D111~D115 應為 401~405,D116~D120 為 501~505。第 1 列 101~105 不應出現在此次結果。
用這四組數值核對讀取結果。若 D100 不足 20,先核對剩餘列數、欄數及檔案內容;若某欄成為 0,還要檢查是否轉換失敗。
12 讀回剛才寫出的 1.CSV
現在把讀取對象換成剛才寫出的 1.CSV。它每列有 16 欄,因此要一起修改檔名、要求數量、起始列與欄數。依下表設定完成後,再觸發一次讀取。
| 讀取項目 | 匹配原寫入格式的設定 |
|---|---|
| 指令 | SP.FREAD U1 K2 D0 "1.CSV" D100 M100 |
| D0 | H100:CSV 十進位 16 位 |
| D1、D3 | 初始化為 0;D1 完成後由系統更新 |
| D2 | K16:讀一筆 16 欄的紀錄 |
| D4、D5 | 0:從檔案開頭;或指定第 n 列來讀某筆紀錄 |
| D6 | K16:以原寫入的 16 欄為一列 |
| D7 | K0:本例使用字單位 |
| D100 | 完成後應為實際讀入的數量,完整一列為 16 |
| D101~D116 | 前七字為時鐘,後九字為練習時指定的 108~116 |
若 D6 設為 0,SP.FREAD 會忽略換行,將資料當成連續數值讀取;這不代表自動只讀一列。這次把 D6 設為 16,讓每列的欄數與寫入格式一致。
FREAD 的 FFFFFFFFH 表示從上次讀取結束位置接續,不是「讀最後一列」。接續讀取必須維持同一檔案及相容的格式設定;第一次練習應使用明確列號,較容易核對結果。
13 CSV 問題排查與改良方向
| 現象 | 判斷方式 |
|---|---|
| 開啟讀取檔卻一直新增資料 | 先看實際指令。若仍是 SP.FWRITE,先改為 SP.FREAD,並重新設定讀取控制資料。 |
| 只寫第一列或舊資料消失 | 確認 D4:D5 是否仍為 FFFFFFFFH。CSV 非檔尾設定會重寫原檔。 |
| 新資料接在最後一列後面 | 檢查 D3.b0;設 1 會把最後換行轉成逗號接續最後一列,本範例使用 0。 |
| 每列欄位數不是預期 | FWRITE 的 D6=0 是本次資料只寫一列;要求 16 字,所以每列 16 欄。 |
| D100=16 但讀回不是 16 欄 | 讀取要求數應設在 D2;D100 是系統回報。再核對欄數、列號及是否為初始化舊值。 |
| 某些欄位讀入後變成 0 | 可能包含標題、無法轉換字元或超出範圍的數值。這些欄位仍可能計入實際數量,必須核對內容。 |
| M150、M151 都亮 | 兩位保留舊結果,練習前清除,再依本次完成與 D1、實際數量判斷。 |
| 資料時間不一致或漏筆 | TRD 每掃描刷新,M3 又沒有忙碌互鎖。正式記錄應先複製資料快照,等存取完成後才送下一筆。 |
若要改成 BIN32、無符號數、ASCII 或浮點數,不只是改副檔名。需一併核對 D0、D7、資料區大小與允許範圍;本篇先固定使用原範例的 16 位數值,避免混用。
連續記錄的驗收應包含檔案大小、每列欄數、紀錄總數、時間順序與錯誤情境。卡片未就緒、空間不足及部分寫入都應保留狀態碼與實際完成數量。
14 完成後做最後確認
用文字編輯器檢查 1.CSV:每次寫入增加一列,每列 16 欄,後九欄是 108~116。回到 GX Works3,確認讀取完成後 D1=0、D100=16,再逐項比對 D101~D116。
若要每秒保存紀錄,先加入 SM753 忙碌互鎖,並在觸發時複製一份資料快照。等上一筆完成再送下一筆,同時保存錯誤碼與實際寫入數,才能追查漏筆或部分寫入。
參考資料
程式圖片來源:《SD卡 CSV檔案讀寫教學》;圖 7 為三菱官方 SP.FREAD 指令圖。
MELSEC iQ-F FX5 Programming Manual (Instructions, Standard Functions/Function Blocks),JY997D55801AB。SP.FREAD 核對印刷頁 488~513;官方 CSV 範例與原指令局部圖為印刷頁 509~512。SP.FWRITE 核對印刷頁 514~535;TRD 核對印刷頁 894~895。
上機時請完成編譯與 CPU/SD 卡相容性確認,並依上述步驟驗證實際讀寫結果。本文未進行實機測試。





