C# 控制CH341進行SPI,I2C讀寫


之前看了別人是C++ MFC開發的CH341 I2C,SPI讀寫flash的軟件代碼,看上去有點頭暈,感覺還是使用C# winform開發更人性化些

C#控制需要調用CH341提供的DLL庫,網上多數是ch341.dll,我這里使用的是USBIOX.DLL(內容基本上是相同的),有需要的可以到下面網盤地址下載

鏈接: https://pan.baidu.com/s/1-PafH2pX1A9DvEprGciXRw 提取碼: uqdh 

調用類函數:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.Runtime.InteropServices;
  5 
  6 
  7 namespace Burner
  8 {
  9     /* mUSB_SETUP_PKT結構體C++定義如下
 10         typedef    struct    _USB_SETUP_PKT {                // USB控制傳輸的建立階段的數據請求包結構
 11         UCHAR            mUspReqType;                // 00H 請求類型
 12         UCHAR            mUspRequest;                // 01H 請求代碼
 13         union    {
 14             struct    {
 15                 UCHAR    mUspValueLow;                // 02H 值參數低字節
 16                 UCHAR    mUspValueHigh;                // 03H 值參數高字節
 17             };
 18             USHORT        mUspValue;                    // 02H-03H 值參數
 19         };
 20         union    {
 21             struct    {
 22                 UCHAR    mUspIndexLow;                // 04H 索引參數低字節
 23                 UCHAR    mUspIndexHigh;                // 05H 索引參數高字節
 24             };
 25             USHORT        mUspIndex;                    // 04H-05H 索引參數
 26         };
 27         USHORT            mLength;                    // 06H-07H 數據階段的數據長度
 28     } mUSB_SETUP_PKT, *mPUSB_SETUP_PKT;
 29     */
 30 
 31     [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Size = 8)]
 32     public struct mUSB_SETUP_PKT
 33     {               // USB控制傳輸的建立階段的數據請求包結構
 34         [FieldOffset(0)]
 35         public byte mUspReqType;                // 00H 請求類型
 36         [FieldOffset(1)]
 37         public byte mUspRequest;                // 01H 請求代碼
 38 
 39         [FieldOffset(2)]
 40         public byte mUspValueLow;               // 02H 值參數低字節
 41         [FieldOffset(3)]
 42         public byte mUspValueHigh;              // 03H 值參數高字節
 43         [FieldOffset(2)]
 44         public UInt16 mUspValue;                    // 02H-03H 值參數
 45 
 46         [FieldOffset(4)]
 47         public byte mUspIndexLow;               // 04H 索引參數低字節
 48         [FieldOffset(5)]
 49         public byte mUspIndexHigh;              // 05H 索引參數高字節
 50         [FieldOffset(4)]
 51         public UInt16 mUspIndex;                    // 04H-05H 索引參數
 52         [FieldOffset(6)]
 53         public UInt16 mLength;                  // 06H-07H 數據階段的數據長度
 54     }
 55 
 56 
 57     /*
 58     mWIN32_COMMAND結構體C++定義如下
 59 
 60     typedef    struct    _WIN32_COMMAND {                // 定義WIN32命令接口結構
 61         union    {
 62             ULONG        mFunction;                    // 輸入時指定功能代碼或者管道號
 63             NTSTATUS    mStatus;                    // 輸出時返回操作狀態
 64         };
 65         ULONG            mLength;                    // 存取長度,返回后續數據的長度
 66         union    {
 67             mUSB_SETUP_PKT    mSetupPkt;                // USB控制傳輸的建立階段的數據請求
 68             UCHAR            mBuffer[ mCH341_PACKET_LENGTH ];    // 數據緩沖區,長度為0至255B
 69         };
 70     } mWIN32_COMMAND, *mPWIN32_COMMAND;
 71 
 72    C#中union功能由FieldOffset()代替
 73 
 74    由於上述結構體中最后一個union可能引起錯誤“對象字段由一個非對象字段不正確地對齊或重疊”
 75    因此將上述結構體拆分成2個結構體mWIN32_COMMAND_USB_SETUP_PKT與mWIN32_COMMAND_mBuffer,選其一即可。
 76    CH341DriverCommand函數將重載
 77    */
 78 
 79     [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
 80     public struct mWIN32_COMMAND_USB_SETUP_PKT
 81     {               // 定義WIN32命令接口結構
 82         [FieldOffset(0)]
 83         public UInt32 mFunction;                    // 輸入時指定功能代碼或者管道號
 84         [FieldOffset(0)]
 85         public Int32 mStatus;                   // 輸出時返回操作狀態
 86         [FieldOffset(4)]
 87         public UInt32 mLength;                  // 存取長度,返回后續數據的長度
 88         [FieldOffset(8)]
 89         public mUSB_SETUP_PKT mSetupPkt;                // USB控制傳輸的建立階段的數據請求
 90     }
 91 
 92     [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
 93     public struct mWIN32_COMMAND_mBuffer
 94     {               // 定義WIN32命令接口結構
 95         [FieldOffset(0)]
 96         public UInt32 mFunction;                    // 輸入時指定功能代碼或者管道號
 97         [FieldOffset(0)]
 98         public Int32 mStatus;                   // 輸出時返回操作狀態
 99         [FieldOffset(4)]
100         public UInt32 mLength;                  // 存取長度,返回后續數據的長度
101 
102         [MarshalAs(UnmanagedType.ByValArray, SizeConst = USBIOXdll.mCH341_PACKET_LENGTH), FieldOffset(8)]
103         public byte[] mBuffer;  // 數據緩沖區,長度為0至255B
104 
105     }
106 
107 
108     class USBIOXdll
109     {
110         public const int mCH341_PACKET_LENGTH = 32;// CH341支持的數據包的長度
111         public const int mCH341_PKT_LEN_SHORT = 8;//CH341支持的短數據包的長度
112 
113         // WIN32應用層接口命令
114         //public  const int        IOCTL_CH341_COMMAND    =    ( FILE_DEVICE_UNKNOWN << 16 | FILE_ANY_ACCESS << 14 | 0x0f34 << 2 | METHOD_BUFFERED )    // 專用接口
115 
116         // public  const int        mWIN32_COMMAND_HEAD    =    mOFFSET( mWIN32_COMMAND, mBuffer );    // WIN32命令接口的頭長度
117 
118         public const int mCH341_MAX_NUMBER = 16;            // 最多同時連接的CH341數
119 
120         public const int mMAX_BUFFER_LENGTH = 0x1000;       // 數據緩沖區最大長度4096
121 
122         //  public  const int        mMAX_COMMAND_LENGTH    =    ( mWIN32_COMMAND_HEAD + mMAX_BUFFER_LENGTH );    // 最大數據長度加上命令結構頭的長度
123 
124         public const int mDEFAULT_BUFFER_LEN = 0x0400;      // 數據緩沖區默認長度1024
125 
126         //   public  const int        mDEFAULT_COMMAND_LEN=    ( mWIN32_COMMAND_HEAD + mDEFAULT_BUFFER_LEN );    // 默認數據長度加上命令結構頭的長度
127 
128         // CH341端點地址
129         public const int mCH341_ENDP_INTER_UP = 0x81;        // CH341的中斷數據上傳端點的地址
130         public const int mCH341_ENDP_INTER_DOWN = 0x01;        // CH341的中斷數據下傳端點的地址
131         public const int mCH341_ENDP_DATA_UP = 0x82;        // CH341的數據塊上傳端點的地址
132         public const int mCH341_ENDP_DATA_DOWN = 0x02;        // CH341的數據塊下傳端點的地址
133 
134 
135         // 設備層接口提供的管道操作命令
136         public const int mPipeDeviceCtrl = 0x00000004;    // CH341的綜合控制管道
137         public const int mPipeInterUp = 0x00000005;    // CH341的中斷數據上傳管道
138         public const int mPipeDataUp = 0x00000006;    // CH341的數據塊上傳管道
139         public const int mPipeDataDown = 0x00000007;    // CH341的數據塊下傳管道
140 
141         // 應用層接口的功能代碼
142         public const int mFuncNoOperation = 0x00000000;    // 無操作
143         public const int mFuncGetVersion = 0x00000001;    // 獲取驅動程序版本號
144         public const int mFuncGetConfig = 0x00000002;    // 獲取USB設備配置描述符
145         public const int mFuncSetTimeout = 0x00000009;    // 設置USB通訊超時
146         public const int mFuncSetExclusive = 0x0000000b;    // 設置獨占使用
147         public const int mFuncResetDevice = 0x0000000c;    // 復位USB設備
148         public const int mFuncResetPipe = 0x0000000d;    // 復位USB管道
149         public const int mFuncAbortPipe = 0x0000000e;    // 取消USB管道的數據請求
150 
151         // CH341並口專用的功能代碼
152         public const int mFuncSetParaMode = 0x0000000f;    // 設置並口模式
153         public const int mFuncReadData0 = 0x00000010;    // 從並口讀取數據塊0
154         public const int mFuncReadData1 = 0x00000011;    // 從並口讀取數據塊1
155         public const int mFuncWriteData0 = 0x00000012;    // 向並口寫入數據塊0
156         public const int mFuncWriteData1 = 0x00000013;    // 向並口寫入數據塊1
157         public const int mFuncWriteRead = 0x00000014;    // 先輸出再輸入
158         public const int mFuncBufferMode = 0x00000020;    // 設定緩沖上傳模式及查詢緩沖區中的數據長度
159         public const int FuncBufferModeDn = 0x00000021;    // 設定緩沖下傳模式及查詢緩沖區中的數據長度
160 
161 
162         // USB設備標准請求代碼
163         public const int mUSB_CLR_FEATURE = 0x01;
164         public const int mUSB_SET_FEATURE = 0x03;
165         public const int mUSB_GET_STATUS = 0x00;
166         public const int mUSB_SET_ADDRESS = 0x05;
167         public const int mUSB_GET_DESCR = 0x06;
168         public const int mUSB_SET_DESCR = 0x07;
169         public const int mUSB_GET_CONFIG = 0x08;
170         public const int mUSB_SET_CONFIG = 0x09;
171         public const int mUSB_GET_INTERF = 0x0a;
172         public const int mUSB_SET_INTERF = 0x0b;
173         public const int mUSB_SYNC_FRAME = 0x0c;
174 
175         // CH341控制傳輸的廠商專用請求類型
176         public const int mCH341_VENDOR_READ = 0xC0;        // 通過控制傳輸實現的CH341廠商專用讀操作
177         public const int mCH341_VENDOR_WRITE = 0x40;        // 通過控制傳輸實現的CH341廠商專用寫操作
178 
179         // CH341控制傳輸的廠商專用請求代碼
180         public const int mCH341_PARA_INIT = 0xB1;    // 初始化並口
181         public const int mCH341_I2C_STATUS = 0x52;        // 獲取I2C接口的狀態
182         public const int mCH341_I2C_COMMAND = 0x53;        // 發出I2C接口的命令
183 
184         // CH341並口操作命令代碼
185         public const int mCH341_PARA_CMD_R0 = 0xAC;        // 從並口讀數據0,次字節為長度
186         public const int mCH341_PARA_CMD_R1 = 0xAD;        // 從並口讀數據1,次字節為長度
187         public const int mCH341_PARA_CMD_W0 = 0xA6;        // 向並口寫數據0,從次字節開始為數據流
188         public const int mCH341_PARA_CMD_W1 = 0xA7;        // 向並口寫數據1,從次字節開始為數據流
189         public const int mCH341_PARA_CMD_STS = 0xA0;        // 獲取並口狀態
190 
191         // CH341A並口操作命令代碼
192         public const int mCH341A_CMD_SET_OUTPUT = 0xA1;        // 設置並口輸出
193         public const int mCH341A_CMD_IO_ADDR = 0xA2;    // MEM帶地址讀寫/輸入輸出,從次字節開始為命令流
194         public const int mCH341A_CMD_PRINT_OUT = 0xA3;        // PRINT兼容打印方式輸出,從次字節開始為數據流
195         public const int mCH341A_CMD_PWM_OUT = 0xA4;        // PWM數據輸出的命令包,從次字節開始為數據流
196         public const int mCH341A_CMD_SHORT_PKT = 0xA5;        // 短包,次字節是該命令包的真正長度,再次字節及之后的字節是原命令包
197         public const int mCH341A_CMD_SPI_STREAM = 0xA8;        // SPI接口的命令包,從次字節開始為數據流
198         //public  const int        mCH341A_CMD_SIO_STREAM    0xA9        // SIO接口的命令包,從次字節開始為數據流
199         public const int mCH341A_CMD_I2C_STREAM = 0xAA;        // I2C接口的命令包,從次字節開始為I2C命令流
200         public const int mCH341A_CMD_UIO_STREAM = 0xAB;        // UIO接口的命令包,從次字節開始為命令流
201         public const int mCH341A_CMD_PIO_STREAM = 0xAE;        // PIO接口的命令包,從次字節開始為數據流
202 
203         // CH341A控制傳輸的廠商專用請求代碼
204         public const int mCH341A_BUF_CLEAR = 0xB2;        // 清除未完成的數據
205         public const int mCH341A_I2C_CMD_X = 0x54;        // 發出I2C接口的命令,立即執行
206         public const int mCH341A_DELAY_MS = 0x5E;        // 以亳秒為單位延時指定時間
207         public const int mCH341A_GET_VER = 0x5F;        // 獲取芯片版本
208 
209         public const int mCH341_EPP_IO_MAX = (mCH341_PACKET_LENGTH - 1);    // CH341在EPP/MEM方式下單次讀寫數據塊的最大長度
210         public const int mCH341A_EPP_IO_MAX = 0xFF;        // CH341A在EPP/MEM方式下單次讀寫數據塊的最大長度
211 
212         public const int mCH341A_CMD_IO_ADDR_W = 0x00;        // MEM帶地址讀寫/輸入輸出的命令流:寫數據,位6-位0為地址,下一個字節為待寫數據
213         public const int mCH341A_CMD_IO_ADDR_R = 0x80;        // MEM帶地址讀寫/輸入輸出的命令流:讀數據,位6-位0為地址,讀出數據一起返回
214 
215         public const int mCH341A_CMD_I2C_STM_STA = 0x74;        // I2C接口的命令流:產生起始位
216         public const int mCH341A_CMD_I2C_STM_STO = 0x75;        // I2C接口的命令流:產生停止位
217         public const int mCH341A_CMD_I2C_STM_OUT = 0x80;        // I2C接口的命令流:輸出數據,位5-位0為長度,后續字節為數據,0長度則只發送一個字節並返回應答
218         public const int mCH341A_CMD_I2C_STM_IN = 0xC0;        // I2C接口的命令流:輸入數據,位5-位0為長度,0長度則只接收一個字節並發送無應答
219         public const int mCH341A_CMD_I2C_STM_MAX = ((0x3F < mCH341_PACKET_LENGTH) ? 0x3F : mCH341_PACKET_LENGTH);    // I2C接口的命令流單個命令輸入輸出數據的最大長度
220         public const int mCH341A_CMD_I2C_STM_SET = 0x60;        // I2C接口的命令流:設置參數,位2=SPI的I/O數(0=單入單出,1=雙入雙出),位1位0=I2C速度(00=低速,01=標准,10=快速,11=高速)
221         public const int mCH341A_CMD_I2C_STM_US = 0x40;        // I2C接口的命令流:以微秒為單位延時,位3-位0為延時值
222         public const int mCH341A_CMD_I2C_STM_MS = 0x50;        // I2C接口的命令流:以亳秒為單位延時,位3-位0為延時值
223         public const int mCH341A_CMD_I2C_STM_DLY = 0x0F;        // I2C接口的命令流單個命令延時的最大值
224         public const int mCH341A_CMD_I2C_STM_END = 0x00;        // I2C接口的命令流:命令包提前結束
225 
226         public const int mCH341A_CMD_UIO_STM_IN = 0x00;        // UIO接口的命令流:輸入數據D7-D0
227         public const int mCH341A_CMD_UIO_STM_DIR = 0x40;        // UIO接口的命令流:設定I/O方向D5-D0,位5-位0為方向數據
228         public const int mCH341A_CMD_UIO_STM_OUT = 0x80;    // UIO接口的命令流:輸出數據D5-D0,位5-位0為數據
229         public const int mCH341A_CMD_UIO_STM_US = 0xC0;        // UIO接口的命令流:以微秒為單位延時,位5-位0為延時值
230         public const int mCH341A_CMD_UIO_STM_END = 0x20;        // UIO接口的命令流:命令包提前結束
231 
232 
233         // CH341並口工作模式
234         public const int mCH341_PARA_MODE_EPP = 0x00;        // CH341並口工作模式為EPP方式
235         public const int mCH341_PARA_MODE_EPP17 = 0x00;        // CH341A並口工作模式為EPP方式V1.7
236         public const int mCH341_PARA_MODE_EPP19 = 0x01;        // CH341A並口工作模式為EPP方式V1.9
237         public const int mCH341_PARA_MODE_MEM = 0x02;        // CH341並口工作模式為MEM方式
238         public const int mCH341_PARA_MODE_ECP = 0x03;        // CH341A並口工作模式為ECP方式
239 
240 
241         // I/O方向設置位定義,直接輸入的狀態信號的位定義,直接輸出的位數據定義
242         public const int mStateBitERR = 0x00000100;    // 只讀可寫,ERR#引腳輸入狀態,1:高電平,0:低電平
243         public const int mStateBitPEMP = 0x00000200;    // 只讀可寫,PEMP引腳輸入狀態,1:高電平,0:低電平
244         public const int mStateBitINT = 0x00000400;    // 只讀可寫,INT#引腳輸入狀態,1:高電平,0:低電平
245         public const int mStateBitSLCT = 0x00000800;    // 只讀可寫,SLCT引腳輸入狀態,1:高電平,0:低電平
246         public const int mStateBitWAIT = 0x00002000;    // 只讀可寫,WAIT#引腳輸入狀態,1:高電平,0:低電平
247         public const int mStateBitDATAS = 0x00004000;    // 只寫可讀,DATAS#/READ#引腳輸入狀態,1:高電平,0:低電平
248         public const int mStateBitADDRS = 0x00008000;    // 只寫可讀,ADDRS#/ADDR/ALE引腳輸入狀態,1:高電平,0:低電平
249         public const int mStateBitRESET = 0x00010000;    // 只寫,RESET#引腳輸入狀態,1:高電平,0:低電平
250         public const int mStateBitWRITE = 0x00020000;    // 只寫,WRITE#引腳輸入狀態,1:高電平,0:低電平
251         public const int mStateBitSCL = 0x00400000;    // 只讀,SCL引腳輸入狀態,1:高電平,0:低電平
252         public const int mStateBitSDA = 0x00800000;    // 只讀,SDA引腳輸入狀態,1:高電平,0:低電平
253 
254 
255         public const int MAX_DEVICE_PATH_SIZE = 128;            // 設備名稱的最大字符數
256         public const int MAX_DEVICE_ID_SIZE = 64;            // 設備ID的最大字符數
257 
258         /*
259          typedef        VOID    ( CALLBACK    * mPCH341_INT_ROUTINE ) (  // 中斷服務程序
260          ULONG            iStatus );  // 中斷狀態數據,參考下面的位說明
261         // 位7-位0對應CH341的D7-D0引腳
262         // 位8對應CH341的ERR#引腳, 位9對應CH341的PEMP引腳, 位10對應CH341的INT#引腳, 位11對應CH341的SLCT引腳
263         */
264         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
265         public delegate void mPCH341_INT_ROUTINE(// 中斷服務程序
266                                                 UInt32 iStatus);// 中斷狀態數據,參考下面的位說明
267         // 位7-位0對應CH341的D7-D0引腳
268         // 位8對應CH341的ERR#引腳, 位9對應CH341的PEMP引腳, 位10對應CH341的INT#引腳, 位11對應CH341的SLCT引腳
269 
270         public const int USBIO_DEVICE_ARRIVAL = 3;  // 設備插入事件,已經插入
271         public const int USBIO_DEVICE_REMOVE_PEND = 1;      // 設備將要拔出
272         public const int USBIO_DEVICE_REMOVE = 0;   // 設備拔出事件,已經拔出
273 
274         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_OpenDevice")]
275         public static extern IntPtr USBIO_OpenDevice(  // 打開CH341設備,返回句柄,出錯則無效
276                                      UInt32 iIndex);  // 指定CH341設備序號,0對應第一個設備
277 
278         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_CloseDevice")]
279         public static extern void USBIO_CloseDevice(  // 關閉CH341設備
280                                       UInt32 iIndex);  // 指定CH341設備序號
281 
282         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetVersion")]
283         public static extern UInt32 USBIO_GetVersion();  // 獲得DLL版本號,返回版本號
284 
285         //函數重載
286         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_DriverCommand")]
287         public static extern UInt32 USBIO_DriverCommand(  // 直接傳遞命令給驅動程序,出錯則返回0,否則返回數據長度
288                                 UInt32 iIndex,  // 指定CH341設備序號,V1.6以上DLL也可以是設備打開后的句柄
289                                  ref mWIN32_COMMAND_mBuffer ioCommand);  // 命令結構的指針
290 
291 
292 
293         [DllImport("USBIOX.DLL", EntryPoint= "USBIO_DriverCommand")]
294         public static extern UInt32 USBIO_DriverCommand(  // 直接傳遞命令給驅動程序,出錯則返回0,否則返回數據長度
295                                 UInt32 iIndex,  // 指定CH341設備序號,V1.6以上DLL也可以是設備打開后的句柄
296                                  ref mWIN32_COMMAND_USB_SETUP_PKT ioCommand);  // 命令結構的指針
297         // 該程序在調用后返回數據長度,並且仍然返回命令結構,如果是讀操作,則數據返回在命令結構中,
298         // 返回的數據長度在操作失敗時為0,操作成功時為整個命令結構的長度,例如讀一個字節,則返回mWIN32_COMMAND_HEAD+1,
299         // 命令結構在調用前,分別提供:管道號或者命令功能代碼,存取數據的長度(可選),數據(可選)
300         // 命令結構在調用后,分別返回:操作狀態代碼,后續數據的長度(可選),
301         //   操作狀態代碼是由WINDOWS定義的代碼,可以參考NTSTATUS.H,
302         //   后續數據的長度是指讀操作返回的數據長度,數據存放在隨后的緩沖區中,對於寫操作一般為0
303 
304         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetDrvVersion")]
305         public static extern UInt32 USBIO_GetDrvVersion();  // 獲得驅動程序版本號,返回版本號,出錯則返回0
306 
307         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ResetDevice")]
308         public static extern bool USBIO_ResetDevice(  // 復位USB設備
309                              UInt32 iIndex);  // 指定CH341設備序號
310 
311         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetDeviceDescr")]
312         public static extern bool USBIO_GetDeviceDescr(  // 讀取設備描述符
313             UInt32 iIndex,  // 指定CH341設備序號
314             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存描述符
315             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
316 
317         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetConfigDescr")]
318         public static extern bool USBIO_GetConfigDescr(  // 讀取配置描述符
319             UInt32 iIndex,  // 指定CH341設備序號
320             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存描述符
321             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
322 
323         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetIntRoutine")]
324         public static extern bool USBIO_SetIntRoutine(  // 設定中斷服務程序
325             UInt32 iIndex,  // 指定CH341設備序號
326             mPCH341_INT_ROUTINE iIntRoutine);  // 指定中斷服務程序,為NULL則取消中斷服務,否則在中斷時調用該程序
327 
328         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ReadInter")]
329         public static extern bool USBIO_ReadInter(  // 讀取中斷數據
330             UInt32 iIndex,  // 指定CH341設備序號
331             ref UInt32 iStatus);  // 指向一個雙字單元,用於保存讀取的中斷狀態數據,見下行
332         // 位7-位0對應CH341的D7-D0引腳
333         // 位8對應CH341的ERR#引腳, 位9對應CH341的PEMP引腳, 位10對應CH341的INT#引腳, 位11對應CH341的SLCT引腳
334 
335 
336         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_AbortInter")]
337         public static extern bool USBIO_AbortInter(  // 放棄中斷數據讀操作
338             UInt32 iIndex);  // 指定CH341設備序號
339 
340         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetParaMode")]
341         public static extern bool USBIO_SetParaMode(  // 設置並口模式
342             UInt32 iIndex,  // 指定CH341設備序號
343             UInt32 iMode);  // 指定並口模式: 0為EPP模式/EPP模式V1.7, 1為EPP模式V1.9, 2為MEM模式
344 
345         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_InitParallel")]
346         public static extern bool USBIO_InitParallel(  // 復位並初始化並口,RST#輸出低電平脈沖
347             UInt32 iIndex,  // 指定CH341設備序號
348             UInt32 iMode);  // 指定並口模式: 0為EPP模式/EPP模式V1.7, 1為EPP模式V1.9, 2為MEM模式, >= 0x00000100 保持當前模式
349 
350         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ReadData0")]
351         public static extern bool USBIO_ReadData0(  // 從0#端口讀取數據塊
352             UInt32 iIndex,  // 指定CH341設備序號
353             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存讀取的數據
354             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
355 
356         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ReadData1")]
357         public static extern bool USBIO_ReadData1(  // 從1#端口讀取數據塊
358             UInt32 iIndex,  // 指定CH341設備序號
359             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存讀取的數據
360             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
361 
362         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_AbortRead")]
363         public static extern bool USBIO_AbortRead(  // 放棄數據塊讀操作
364             UInt32 iIndex);  // 指定CH341設備序號
365 
366         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_WriteData0")]
367         public static extern bool USBIO_WriteData0(  // 向0#端口寫出數據塊
368             UInt32 iIndex,  // 指定CH341設備序號
369             byte[] iBuffer,  // 指向一個緩沖區,放置准備寫出的數據
370             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
371 
372         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_WriteData1")]
373         public static extern bool USBIO_WriteData1(  // 向1#端口寫出數據塊
374             UInt32 iIndex,  // 指定CH341設備序號
375             byte[] iBuffer,  // 指向一個緩沖區,放置准備寫出的數據
376             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
377 
378         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_AbortWrite")]
379         public static extern bool USBIO_AbortWrite(  // 放棄數據塊寫操作
380             UInt32 iIndex);  // 指定CH341設備序號
381 
382         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetStatus")]
383         public static extern bool USBIO_GetStatus(  // 通過CH341直接輸入數據和狀態
384             UInt32 iIndex,  // 指定CH341設備序號
385             ref UInt32 iStatus);  // 指向一個雙字單元,用於保存狀態數據,參考下面的位說明
386         // 位7-位0對應CH341的D7-D0引腳
387         // 位8對應CH341的ERR#引腳, 位9對應CH341的PEMP引腳, 位10對應CH341的INT#引腳, 位11對應CH341的SLCT引腳, 位23對應CH341的SDA引腳
388         // 位13對應CH341的BUSY/WAIT#引腳, 位14對應CH341的AUTOFD#/DATAS#引腳,位15對應CH341的SLCTIN#/ADDRS#引腳
389 
390         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ReadI2C")]
391         public static extern bool USBIO_ReadI2C(  // 從I2C接口讀取一個字節數據
392             UInt32 iIndex,  // 指定CH341設備序號
393             byte iDevice,  // 低7位指定I2C設備地址
394             byte iAddr,  // 指定數據單元的地址
395             ref byte oByte);  // 指向一個字節單元,用於保存讀取的字節數據
396 
397         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_WriteI2C")]
398         public static extern bool USBIO_WriteI2C(  // 向I2C接口寫入一個字節數據
399             UInt32 iIndex,  // 指定CH341設備序號
400             byte iDevice,  // 低7位指定I2C設備地址
401             byte iAddr,  // 指定數據單元的地址
402             byte iByte);  // 待寫入的字節數據
403 
404         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_EppReadData")]
405         public static extern bool USBIO_EppReadData(  // EPP方式讀數據: WR#=1, DS#=0, AS#=1, D0-D7=input
406             UInt32 iIndex,  // 指定CH341設備序號
407             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存讀取的數據
408             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
409 
410         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_EppReadAddr")]
411         public static extern bool USBIO_EppReadAddr(  // EPP方式讀地址: WR#=1, DS#=1, AS#=0, D0-D7=input
412             UInt32 iIndex,  // 指定CH341設備序號
413             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存讀取的地址數據
414             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
415 
416         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_EppWriteData")]
417         public static extern bool USBIO_EppWriteData(  // EPP方式寫數據: WR#=0, DS#=0, AS#=1, D0-D7=output
418             UInt32 iIndex,  // 指定CH341設備序號
419             byte[] iBuffer,  // 指向一個緩沖區,放置准備寫出的數據
420             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
421 
422         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_EppWriteAddr")]
423         public static extern bool USBIO_EppWriteAddr(  // EPP方式寫地址: WR#=0, DS#=1, AS#=0, D0-D7=output
424             UInt32 iIndex,  // 指定CH341設備序號
425             byte[] iBuffer,  // 指向一個緩沖區,放置准備寫出的地址數據
426             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
427 
428         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_EppSetAddr")]
429         public static extern bool USBIO_EppSetAddr(  // EPP方式設置地址: WR#=0, DS#=1, AS#=0, D0-D7=output
430             UInt32 iIndex,  // 指定CH341設備序號
431             byte iAddr);  // 指定EPP地址
432 
433         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_MemReadAddr0")]
434         public static extern bool USBIO_MemReadAddr0(  // MEM方式讀地址0: WR#=1, DS#/RD#=0, AS#/ADDR=0, D0-D7=input
435             UInt32 iIndex,  // 指定CH341設備序號
436             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存從地址0讀取的數據
437             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
438 
439         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_MemReadAddr1")]
440         public static extern bool USBIO_MemReadAddr1(  // MEM方式讀地址1: WR#=1, DS#/RD#=0, AS#/ADDR=1, D0-D7=input
441             UInt32 iIndex,  // 指定CH341設備序號
442             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存從地址1讀取的數據
443             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
444 
445         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_MemWriteAddr0")]
446         public static extern bool USBIO_MemWriteAddr0(  // MEM方式寫地址0: WR#=0, DS#/RD#=1, AS#/ADDR=0, D0-D7=output
447             UInt32 iIndex,  // 指定CH341設備序號
448             byte[] iBuffer,  // 指向一個緩沖區,放置准備向地址0寫出的數據
449             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
450 
451         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_MemWriteAddr1")]
452         public static extern bool USBIO_MemWriteAddr1(  // MEM方式寫地址1: WR#=0, DS#/RD#=1, AS#/ADDR=1, D0-D7=output
453             UInt32 iIndex,  // 指定CH341設備序號
454             byte[] iBuffer,  // 指向一個緩沖區,放置准備向地址1寫出的數據
455             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
456 
457         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetExclusive")]
458         public static extern bool USBIO_SetExclusive(  // 設置獨占使用當前CH341設備
459             UInt32 iIndex,  // 指定CH341設備序號
460             UInt32 iExclusive);  // 為0則設備可以共享使用,非0則獨占使用
461 
462         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetTimeout")]
463         public static extern bool USBIO_SetTimeout(  // 設置USB數據讀寫的超時
464             UInt32 iIndex,  // 指定CH341設備序號
465             UInt32 iWriteTimeout,  // 指定USB寫出數據塊的超時時間,以毫秒mS為單位,0xFFFFFFFF指定不超時(默認值)
466             UInt32 iReadTimeout);  // 指定USB讀取數據塊的超時時間,以毫秒mS為單位,0xFFFFFFFF指定不超時(默認值)
467 
468         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ReadData")]
469         public static extern bool USBIO_ReadData(  // 讀取數據塊
470             UInt32 iIndex,  // 指定CH341設備序號
471             byte[] oBuffer,  // 指向一個足夠大的緩沖區,用於保存讀取的數據
472             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備讀取的長度,返回后為實際讀取的長度
473 
474         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_WriteData")]
475         public static extern bool USBIO_WriteData(  // 寫出數據塊
476             UInt32 iIndex,  // 指定CH341設備序號
477             byte[] iBuffer,  // 指向一個緩沖區,放置准備寫出的數據
478             ref UInt32 ioLength);  // 指向長度單元,輸入時為准備寫出的長度,返回后為實際寫出的長度
479 
480         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetDeviceName")]
481         public static extern IntPtr USBIO_GetDeviceName(  // 返回指向CH341設備名稱的緩沖區,出錯則返回NULL
482             UInt32 iIndex);  // 指定CH341設備序號,0對應第一個設備
483 
484         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetVerIC")]
485         public static extern UInt32 USBIO_GetVerIC(  // 獲取CH341芯片的版本,返回:0=設備無效,0x10=CH341,0x20=CH341A
486             UInt32 iIndex);  // 指定CH341設備序號
487 
488         public const int IC_VER_CH341A = 0x20;
489         public const int IC_VER_CH341A3 = 0x30;
490 
491         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_FlushBuffer")]
492         public static extern bool USBIO_FlushBuffer(  // 清空CH341的緩沖區
493             UInt32 iIndex);  // 指定CH341設備序號
494 
495         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_WriteRead")]
496         public static extern bool USBIO_WriteRead(  // 執行數據流命令,先輸出再輸入
497             UInt32 iIndex,  // 指定CH341設備序號
498             UInt32 iWriteLength,  // 寫長度,准備寫出的長度
499             byte[] iWriteBuffer,  // 指向一個緩沖區,放置准備寫出的數據
500             UInt32 iReadStep,  // 准備讀取的單個塊的長度, 准備讀取的總長度為(iReadStep*iReadTimes)
501             UInt32 iReadTimes,  // 准備讀取的次數
502             ref UInt32 oReadLength,  // 指向長度單元,返回后為實際讀取的長度
503             byte[] oReadBuffer);  // 指向一個足夠大的緩沖區,用於保存讀取的數據
504 
505         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetStream")]
506         public static extern bool USBIO_SetStream(  // 設置串口流模式
507             UInt32 iIndex,  // 指定CH341設備序號
508             UInt32 iMode);  // 指定模式,見下行
509         // 位1-位0: I2C接口速度/SCL頻率, 00=低速/20KHz,01=標准/100KHz(默認值),10=快速/400KHz,11=高速/750KHz
510         // 位2:     SPI的I/O數/IO引腳, 0=單入單出(D3時鍾/D5出/D7入)(默認值),1=雙入雙出(D3時鍾/D5出D4出/D7入D6入)
511         // 位7:     SPI字節中的位順序, 0=低位在前, 1=高位在前
512         // 其它保留,必須為0
513 
514         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetDelaymS")]
515         public static extern bool USBIO_SetDelaymS(  // 設置硬件異步延時,調用后很快返回,而在下一個流操作之前延時指定毫秒數
516             UInt32 iIndex,  // 指定CH341設備序號
517             UInt32 iDelay);  // 指定延時的毫秒數
518 
519         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_StreamI2C")]
520         public static extern bool USBIO_StreamI2C(  // 處理I2C數據流,2線接口,時鍾線為SCL引腳,數據線為SDA引腳(准雙向I/O),速度約56K字節
521             UInt32 iIndex,  // 指定CH341設備序號
522             UInt32 iWriteLength,  // 准備寫出的數據字節數
523             byte[] iWriteBuffer,  // 指向一個緩沖區,放置准備寫出的數據,首字節通常是I2C設備地址及讀寫方向位
524             UInt32 iReadLength,  // 准備讀取的數據字節數
525             byte[] oReadBuffer);  // 指向一個緩沖區,返回后是讀入的數據
526 
527         public enum EEPROM_TYPE         // EEPROM型號
528         {
529             ID_24C01,
530             ID_24C02,
531             ID_24C04,
532             ID_24C08,
533             ID_24C16,
534             ID_24C32,
535             ID_24C64,
536             ID_24C128,
537             ID_24C256,
538             ID_24C512,
539             ID_24C1024,
540             ID_24C2048,
541             ID_24C4096
542 
543         };
544 
545         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ReadEEPROM")]
546         public static extern bool USBIO_ReadEEPROM(  // 從EEPROM中讀取數據塊,速度約56K字節
547             UInt32 iIndex,  // 指定CH341設備序號
548             EEPROM_TYPE iEepromID,  // 指定EEPROM型號
549             UInt32 iAddr,  // 指定數據單元的地址
550             UInt32 iLength,  // 准備讀取的數據字節數
551             byte[] oBuffer);  // 指向一個緩沖區,返回后是讀入的數據
552 
553         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_WriteEEPROM")]
554         public static extern bool USBIO_WriteEEPROM(  // 向EEPROM中寫入數據塊
555             UInt32 iIndex,  // 指定CH341設備序號
556             EEPROM_TYPE iEepromID,  // 指定EEPROM型號
557             UInt32 iAddr,  // 指定數據單元的地址
558             UInt32 iLength,  // 准備寫出的數據字節數
559             byte[] iBuffer);  // 指向一個緩沖區,放置准備寫出的數據
560 
561         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetInput")]
562         public static extern bool USBIO_GetInput(  // 通過CH341直接輸入數據和狀態,效率比CH341GetStatus更高
563             UInt32 iIndex,  // 指定CH341設備序號
564             ref UInt32 iStatus);  // 指向一個雙字單元,用於保存狀態數據,參考下面的位說明
565         // 位7-位0對應CH341的D7-D0引腳
566         // 位8對應CH341的ERR#引腳, 位9對應CH341的PEMP引腳, 位10對應CH341的INT#引腳, 位11對應CH341的SLCT引腳, 位23對應CH341的SDA引腳
567         // 位13對應CH341的BUSY/WAIT#引腳, 位14對應CH341的AUTOFD#/DATAS#引腳,位15對應CH341的SLCTIN#/ADDRS#引腳
568 
569         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetOutput")]
570         public static extern bool USBIO_SetOutput(  // 設置CH341的I/O方向,並通過CH341直接輸出數據
571                                                    /* ***** 謹慎使用該API, 防止修改I/O方向使輸入引腳變為輸出引腳導致與其它輸出引腳之間短路而損壞芯片 ***** */
572             UInt32 iIndex,  // 指定CH341設備序號
573             UInt32 iEnable,  // 數據有效標志,參考下面的位說明
574                              // 位0為1說明iSetDataOut的位15-位8有效,否則忽略
575                              // 位1為1說明iSetDirOut的位15-位8有效,否則忽略
576                              // 位2為1說明iSetDataOut的7-位0有效,否則忽略
577                              // 位3為1說明iSetDirOut的位7-位0有效,否則忽略
578                              // 位4為1說明iSetDataOut的位23-位16有效,否則忽略
579             UInt32 iSetDirOut,  // 設置I/O方向,某位清0則對應引腳為輸入,某位置1則對應引腳為輸出,並口方式下默認值為0x000FC000,參考下面的位說明
580             UInt32 iSetDataOut);  // 輸出數據,如果I/O方向為輸出,那么某位清0時對應引腳輸出低電平,某位置1時對應引腳輸出高電平,參考下面的位說明
581         // 位7-位0對應CH341的D7-D0引腳
582         // 位8對應CH341的ERR#引腳, 位9對應CH341的PEMP引腳, 位10對應CH341的INT#引腳, 位11對應CH341的SLCT引腳
583         // 位13對應CH341的WAIT#引腳, 位14對應CH341的DATAS#/READ#引腳,位15對應CH341的ADDRS#/ADDR/ALE引腳
584         // 以下引腳只能輸出,不考慮I/O方向: 位16對應CH341的RESET#引腳, 位17對應CH341的WRITE#引腳, 位18對應CH341的SCL引腳, 位29對應CH341的SDA引腳
585 
586         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_Set_D5_D0")]
587         public static extern bool USBIO_Set_D5_D0(  // 設置CH341的D5-D0引腳的I/O方向,並通過CH341的D5-D0引腳直接輸出數據,效率比CH341SetOutput更高
588                                                    /* ***** 謹慎使用該API, 防止修改I/O方向使輸入引腳變為輸出引腳導致與其它輸出引腳之間短路而損壞芯片 ***** */
589             UInt32 iIndex,  // 指定CH341設備序號
590             UInt32 iSetDirOut,  // 設置D5-D0各引腳的I/O方向,某位清0則對應引腳為輸入,某位置1則對應引腳為輸出,並口方式下默認值為0x00全部輸入
591             UInt32 iSetDataOut);  // 設置D5-D0各引腳的輸出數據,如果I/O方向為輸出,那么某位清0時對應引腳輸出低電平,某位置1時對應引腳輸出高電平
592         // 以上數據的位5-位0分別對應CH341的D5-D0引腳
593 
594         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_StreamSPI3")]
595         public static extern bool USBIO_StreamSPI3(  // 該API已失效,請勿使用
596             UInt32 iIndex,
597             UInt32 iChipSelect,
598             UInt32 iLength,
599             byte[] ioBuffer);
600 
601         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_StreamSPI4")]
602         public static extern bool USBIO_StreamSPI4(  // 處理SPI數據流,4線接口,時鍾線為DCK/D3引腳,輸出數據線為DOUT/D5引腳,輸入數據線為DIN/D7引腳,片選線為D0/D1/D2,速度約68K字節
603                                                     /* SPI時序: DCK/D3引腳為時鍾輸出, 默認為低電平, DOUT/D5引腳在時鍾上升沿之前的低電平期間輸出, DIN/D7引腳在時鍾下降沿之前的高電平期間輸入 */
604             UInt32 iIndex,  // 指定CH341設備序號
605             UInt32 iChipSelect,  // 片選控制, 位7為0則忽略片選控制, 位7為1則參數有效: 位1位0為00/01/10分別選擇D0/D1/D2引腳作為低電平有效片選
606             UInt32 iLength,  // 准備傳輸的數據字節數
607             byte[] ioBuffer);  // 指向一個緩沖區,放置准備從DOUT寫出的數據,返回后是從DIN讀入的數據
608 
609         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_StreamSPI5")]
610         public static extern bool USBIO_StreamSPI5(  // 處理SPI數據流,5線接口,時鍾線為DCK/D3引腳,輸出數據線為DOUT/D5和DOUT2/D4引腳,輸入數據線為DIN/D7和DIN2/D6引腳,片選線為D0/D1/D2,速度約30K字節*2
611                                                     /* SPI時序: DCK/D3引腳為時鍾輸出, 默認為低電平, DOUT/D5和DOUT2/D4引腳在時鍾上升沿之前的低電平期間輸出, DIN/D7和DIN2/D6引腳在時鍾下降沿之前的高電平期間輸入 */
612             UInt32 iIndex,  // 指定CH341設備序號
613             UInt32 iChipSelect,  // 片選控制, 位7為0則忽略片選控制, 位7為1則參數有效: 位1位0為00/01/10分別選擇D0/D1/D2引腳作為低電平有效片選
614             UInt32 iLength,  // 准備傳輸的數據字節數
615             byte[] ioBuffer,  // 指向一個緩沖區,放置准備從DOUT寫出的數據,返回后是從DIN讀入的數據
616             byte[] ioBuffer2);  // 指向第二個緩沖區,放置准備從DOUT2寫出的數據,返回后是從DIN2讀入的數據
617 
618         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_BitStreamSPI")]
619         public static extern bool USBIO_BitStreamSPI(  // 處理SPI位數據流,4線/5線接口,時鍾線為DCK/D3引腳,輸出數據線為DOUT/DOUT2引腳,輸入數據線為DIN/DIN2引腳,片選線為D0/D1/D2,速度約8K位*2
620             UInt32 iIndex,  // 指定CH341設備序號
621             UInt32 iLength,  // 准備傳輸的數據位數,一次最多896,建議不超過256
622             byte[] ioBuffer);  // 指向一個緩沖區,放置准備從DOUT/DOUT2/D2-D0寫出的數據,返回后是從DIN/DIN2讀入的數據
623         /* SPI時序: DCK/D3引腳為時鍾輸出, 默認為低電平, DOUT/D5和DOUT2/D4引腳在時鍾上升沿之前的低電平期間輸出, DIN/D7和DIN2/D6引腳在時鍾下降沿之前的高電平期間輸入 */
624         /* ioBuffer中的一個字節共8位分別對應D7-D0引腳, 位5輸出到DOUT, 位4輸出到DOUT2, 位2-位0輸出到D2-D0, 位7從DIN輸入, 位6從DIN2輸入, 位3數據忽略 */
625         /* 在調用該API之前,應該先調用CH341Set_D5_D0設置CH341的D5-D0引腳的I/O方向,並設置引腳的默認電平 */
626 
627         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetBufUpload")]
628         public static extern bool USBIO_SetBufUpload(  // 設定內部緩沖上傳模式
629             UInt32 iIndex,  // 指定CH341設備序號,0對應第一個設備
630             UInt32 iEnableOrClear);  // 為0則禁止內部緩沖上傳模式,使用直接上傳,非0則啟用內部緩沖上傳模式並清除緩沖區中的已有數據
631         // 如果啟用內部緩沖上傳模式,那么CH341驅動程序創建線程自動接收USB上傳數據到內部緩沖區,同時清除緩沖區中的已有數據,當應用程序調用CH341ReadData后將立即返回緩沖區中的已有數據
632 
633         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_QueryBufUpload")]
634         public static extern Int32 USBIO_QueryBufUpload(  // 查詢內部上傳緩沖區中的已有數據包個數,成功返回數據包個數,出錯返回-1
635             UInt32 iIndex);  // 指定CH341設備序號,0對應第一個設備
636 
637         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetBufDownload")]
638         public static extern bool USBIO_SetBufDownload(  // 設定內部緩沖下傳模式
639             UInt32 iIndex,  // 指定CH341設備序號,0對應第一個設備
640             UInt32 iEnableOrClear);  // 為0則禁止內部緩沖下傳模式,使用直接下傳,非0則啟用內部緩沖下傳模式並清除緩沖區中的已有數據
641         // 如果啟用內部緩沖下傳模式,那么當應用程序調用CH341WriteData后將僅僅是將USB下傳數據放到內部緩沖區並立即返回,而由CH341驅動程序創建的線程自動發送直到完畢
642 
643         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_QueryBufDownload")]
644         public static extern Int32 USBIO_QueryBufDownload(  // 查詢內部下傳緩沖區中的剩余數據包個數(尚未發送),成功返回數據包個數,出錯返回-1
645             UInt32 iIndex);  // 指定CH341設備序號,0對應第一個設備
646 
647         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ResetInter")]
648         public static extern bool USBIO_ResetInter(  // 復位中斷數據讀操作
649             UInt32 iIndex);  // 指定CH341設備序號
650 
651         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ResetRead")]
652         public static extern bool USBIO_ResetRead(  // 復位數據塊讀操作
653             UInt32 iIndex);  // 指定CH341設備序號
654 
655         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_ResetWrite")]
656         public static extern bool USBIO_ResetWrite(  // 復位數據塊寫操作
657             UInt32 iIndex);  // 指定CH341設備序號
658 
659         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
660 
661         public delegate void mPCH341_NOTIFY_ROUTINE(  // 設備事件通知回調程序
662                     UInt32 iEventStatus);  // 設備事件和當前狀態(在下行定義): 0=設備拔出事件, 3=設備插入事件
663 
664 
665         public const int CH341_DEVICE_ARRIVA = 3;    // 設備插入事件,已經插入
666         public const int CH341_DEVICE_REMOVE_PEND = 1;        // 設備將要拔出
667         public const int CH341_DEVICE_REMOVE = 0;        // 設備拔出事件,已經拔出
668 
669         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetDeviceNotify")]
670         public static extern bool USBIO_SetDeviceNotify(  // 設定設備事件通知程序
671             UInt32 iIndex,  // 指定CH341設備序號,0對應第一個設備
672             string iDeviceID,  // 可選參數,指向字符串,指定被監控的設備的ID,字符串以\0終止
673             mPCH341_NOTIFY_ROUTINE iNotifyRoutine);  // 指定設備事件回調程序,為NULL則取消事件通知,否則在檢測到事件時調用該程序
674 
675         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetupSerial")]
676         public static extern bool USBIO_SetupSerial(  // 設定CH341的串口特性,該API只能用於工作於串口方式的CH341芯片
677             UInt32 iIndex,  // 指定CH341設備序號,0對應第一個設備
678             UInt32 iParityMode,  // 指定CH341串口的數據校驗模式: NOPARITY/ODDPARITY/EVENPARITY/MARKPARITY/SPACEPARITY
679             UInt32 iBaudRate);  // 指定CH341串口的通訊波特率值,可以是50至3000000之間的任意值
680 
681         /*  以下API可以用於工作於串口方式的CH341芯片,除此之外的API一般只能用於並口方式的CH341芯片
682             CH341OpenDevice
683             CH341CloseDevice
684             CH341SetupSerial
685             CH341ReadData
686             CH341WriteData
687             CH341SetBufUpload
688             CH341QueryBufUpload
689             CH341SetBufDownload
690             CH341QueryBufDownload
691             CH341SetDeviceNotify
692             CH341GetStatus
693         //  以上是主要API,以下是次要API
694             CH341GetVersion
695             CH341DriverCommand
696             CH341GetDrvVersion
697             CH341ResetDevice
698             CH341GetDeviceDescr
699             CH341GetConfigDescr
700             CH341SetIntRoutine
701             CH341ReadInter
702             CH341AbortInter
703             CH341AbortRead
704             CH341AbortWrite
705             CH341ReadI2C
706             CH341WriteI2C
707             CH341SetExclusive
708             CH341SetTimeout
709             CH341GetDeviceName
710             CH341GetVerIC
711             CH341FlushBuffer
712             CH341WriteRead
713             CH341ResetInter
714             CH341ResetRead
715             CH341ResetWrite
716         */
717         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_OpenDeviceEx")]
718         public static extern IntPtr USBIO_OpenDeviceEx(   // 打開CH341設備,返回句柄,出錯則無效
719             UInt32 iIndex);        // 指定CH341設備序號,0對應插入的第一個設備,1對應插入的第二個設備,為節約設備設備序號資源,用完后要關閉設備
720 
721         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_CloseDeviceEx")]
722         public static extern void USBIO_CloseDeviceEx(  // 關閉CH341設備
723             UInt32 iIndex);        // 指定CH341設備序號
724 
725         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_GetDeviceNameEx")]
726         public static extern IntPtr USBIO_GetDeviceNameEx(   // 返回指向CH341設備名稱的緩沖區,出錯則返回NULL
727             UInt32 iIndex);           // 指定CH341設備序號,0對應第一個設備
728 
729         [DllImport("USBIOX.DLL", EntryPoint = "USBIO_SetDeviceNotifyEx")]
730         public static extern bool USBIO_SetDeviceNotifyEx(       // 設定設備事件通知程序
731             UInt32 iIndex,           // 指定CH341設備序號,0對應第一個設備
732             string iDeviceID,        // 可選參數,指向字符串,指定被監控的設備的ID,字符串以\0終止
733             mPCH341_NOTIFY_ROUTINE iNotifyRoutine); // 指定設備事件回調程序,為NULL則取消事件通知,否則在檢測到事件時調用該程序
734 
735     }
736 }
USBIOXdll.cs

主要I2C和SPI 操作代碼:

  1 //FLASH 配置狀態寄存器地址
  2         public static byte WRITE_ENABLE = 0X06; //寫使能
  3         public static byte WRITE_DISABLE = 0X04;    //寫禁止
  4         public static byte READ_STATUS_REG1 = 0X05; //讀狀態寄存器
  5         public static byte READ_STATUS_REG2 = 0X35; //讀狀態寄存器
  6         public static byte READ_DATA = 0X03;    //讀字節
  7         public static byte EWSR = 0X50;    //使能寫狀態寄存器
  8         public static byte FAST_READ = 0X0B;    //快讀指令
  9         public static byte PAGE_PROGRAM = 0X02; //Byte Prog Mode
 10         public static byte SECTOR_ERASE_4K = 0X20;  //Erase 4 KByte of memory array
 11         public static byte BLOCK_ERASE_32K = 0X52; //Erase 32 KByte block of memory array
 12         public static byte BLOCK_ERASE_64K = 0XD8;  //Erase 64 KByte block of memory array
 13         public static byte CHIP_ERASE = 0XC7;   //擦除整個FLASH芯片
 14 
 15 public static void memset(byte[] buf, byte val, int size)
 16         {
 17             int i;
 18             for (i = 0; i < size; i++)
 19                 buf[i] = val;
 20         }
 21 
 22         public static void memcpy(byte[] dst, int dst_offst, byte[] src, int src_offst, uint len)
 23         {
 24             for (int i = 0; i < len; i++)
 25             {
 26                 dst[dst_offst++] = src[src_offst++];
 27             }
 28 
 29         }
 30 
 31         public static bool ReadI2C(uint mIndex, byte SlaveAddr, byte DataAddr, byte readData)    //連讀模式
 32         {
 33             UInt32 writeLen = 0, readLen = 1;
 34             byte[] writeData = new byte[4], rData = new byte[1];
 35             memset(writeData, 0xFF, 4);
 36             writeData[0] = SlaveAddr;
 37             writeData[1] = DataAddr;
 38             writeLen = 2;
 39             bool bRet = USBIOXdll.USBIO_StreamI2C(mIndex, writeLen, writeData, readLen, rData);
 40             readData = rData[0];
 41             return bRet;
 42         }
 43         public static bool ReadI2C(uint mIndex, byte SlaveAddr, byte DataAddr, byte[] readData, UInt32 readLen)    //連讀模式
 44         {
 45             UInt32 writeLen = 0;
 46             byte[] writeData = new byte[4];
 47             memset(writeData, 0xFF, 4);
 48             writeData[0] = SlaveAddr;
 49             writeData[1] = DataAddr;
 50             writeLen = 2;
 51             bool bRet = USBIOXdll.USBIO_StreamI2C(mIndex, writeLen, writeData, readLen, readData);
 52             return bRet;
 53         }
 54 
 55         public static bool WriteI2C(uint mIndex, byte SlaveAddr, byte DataAddr, byte data)     //單寫模式
 56         {
 57             UInt32 writeLen = 3;
 58             UInt32 readLen = 0;
 59             byte[] writeData = new byte[4];
 60             byte[] readData = new byte[256];
 61             memset(writeData, 0xFF, 4);
 62             memset(readData, 0x00, 256);
 63             writeData[0] = SlaveAddr;
 64             writeData[1] = DataAddr;
 65             writeData[2] = data;
 66             bool bRet = USBIOXdll.USBIO_StreamI2C(mIndex, writeLen, writeData, readLen, readData);
 67             return bRet;
 68         }
 69 
 70         public static bool WriteI2C(uint mIndex, byte SlaveAddr, byte DataAddr, byte[] data, UInt32 len)     //多寫模式
 71         {
 72             UInt32 writeLen = len + 2;
 73             UInt32 readLen = 0;
 74             byte[] writeData = new byte[writeLen];
 75             byte[] readData = new byte[256];
 76             //memset(writeData, 0xFF, 4);
 77             memset(readData, 0x00, 256);
 78 
 79             writeData[0] = SlaveAddr;
 80             writeData[1] = DataAddr;
 81             memcpy(writeData, 2, data, 0, len);
 82             bool bRet = USBIOXdll.USBIO_StreamI2C(mIndex, writeLen, writeData, readLen, readData);
 83             return bRet;
 84         }
 85         /// <summary>
 86         /// SPI擦除flash操作
 87         /// </summary>
 88         /// <param name="mIndex">指定CH341設備序號</param>
 89         /// <param name="m_iChipSelect">片選控制, 位7為0則忽略片選控制, 位7為1則參數有效: 位1位0為00/01/10分別選擇D0/D1/D2引腳作為低電平有效片選</param>
 90         /// <param name="Erase_Select">擦除類型</param>
 91         /// <param name="sAdd">地址</param>
 92         public static void SPIErase(uint mIndex,uint m_iChipSelect,byte Erase_Select,uint sAdd)
 93         {
 94             byte[] data = new byte[4];
 95             USBIOXdll.USBIO_SetStream(mIndex, 0x80);
 96             memset(data, 0xFF, 4);
 97             data[0] = WRITE_ENABLE;
 98             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 1, data);
 99 
100             data[0] = Erase_Select;
101             data[1] = (byte)((sAdd & 0xFF0000) >> 16);
102             data[2] = (byte)((sAdd & 0x00FF00) >> 8);
103             data[3] = (byte)(sAdd & 0x0000FF);
104             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 4, data);
105 
106             data[0] = WRITE_DISABLE;
107             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 1, data);
108 
109         }
110         /// <summary>
111         /// SPI寫入flash數據
112         /// </summary>
113         /// <param name="mIndex">設備號</param>
114         /// <param name="m_iChipSelect">片選</param>
115         /// <param name="sAdd">起始地址</param>
116         /// <param name="WriteData">數據</param>
117         public static void WriteSPI(uint mIndex, uint m_iChipSelect,uint sAdd,byte[] WriteData)
118         {
119             byte[] status = new byte[1];
120             byte[] data = new byte[260];
121             int len = WriteData.Length;
122             int nPage = 0;
123             USBIOXdll.USBIO_SetStream(mIndex, 0x80);
124             while (len >256)
125             {
126                 
127                 status[0] = WRITE_ENABLE;
128                 USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 1, status);
129                 data[0] = PAGE_PROGRAM;
130                 data[1] = (byte)((sAdd & 0xFF0000) >> 16);
131                 data[2] = (byte)((sAdd & 0x00FF00) >> 8);
132                 data[3] = (byte)(sAdd & 0x0000FF);
133                 memcpy(data, 4, WriteData, nPage * 256, 256);
134                 USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 260, data);
135                 status[0] = WRITE_DISABLE;
136                 USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 1, status);
137                 USBIOXdll.USBIO_SetDelaymS(mIndex, 2);
138                 len -= 256;
139                 nPage++;
140                 sAdd += 256;
141             }
142 
143             status[0] = WRITE_ENABLE;
144             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 1, status);
145             data[0] = PAGE_PROGRAM;
146             data[1] = (byte)((sAdd & 0xFF0000) >> 16);
147             data[2] = (byte)((sAdd & 0x00FF00) >> 8);
148             data[3] = (byte)(sAdd & 0x0000FF);
149             memcpy(data, 4, WriteData, nPage * 256, (uint)len);
150             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, (uint)(len+4), data);
151             status[0] = WRITE_DISABLE;
152             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 1, status);
153         }
154         /// <summary>
155         /// SPI讀取flash數據
156         /// </summary>
157         /// <param name="mIndex">設備號</param>
158         /// <param name="m_iChipSelect">片選</param>
159         /// <param name="sAdd">起始地址</param>
160         /// <param name="ReadData">讀取數據返回數組</param>
161         /// <param name="ReadLen">讀取長度</param>
162         public static void ReadSPI(uint mIndex, uint m_iChipSelect, uint sAdd, byte[] ReadData,uint ReadLen)
163         {
164             byte[] status = new byte[2564];
165             int i = 0;
166             
167             USBIOXdll.USBIO_SetStream(mIndex, 0x80);
168             //USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 4, status);
169             while(ReadLen>2560)
170             {
171                 status[0] = READ_DATA;
172                 status[1] = (byte)((sAdd & 0xFF0000) >> 16);
173                 status[2] = (byte)((sAdd & 0x00FF00) >> 8);
174                 status[3] = (byte)(sAdd & 0x0000FF);
175                 USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, 2564, status);
176                 memcpy(ReadData, i * 2560, status, 4, 2560);
177                 ReadLen -= 2560;
178                 i++;
179                 sAdd += 2560;
180             }
181             status[0] = READ_DATA;
182             status[1] = (byte)((sAdd & 0xFF0000) >> 16);
183             status[2] = (byte)((sAdd & 0x00FF00) >> 8);
184             status[3] = (byte)(sAdd & 0x0000FF);
185             USBIOXdll.USBIO_StreamSPI4(mIndex, m_iChipSelect, ReadLen+4, status);
186             memcpy(ReadData, i * 2560, status, 4, ReadLen);
187         }
View Code

 

 

 

鏈接:C# SPI 讀寫SD卡


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM