之前看了别人是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 }
主要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 }
链接:C# SPI 读写SD卡