📄 ch365dll.c
字号:
{
PVOID mAddress;
ULONG mLength;
mWIN32_COMMAND mCommand;
if ( iAddr >= (PVOID)dllMemBaseAddr[ iIndex ] ) mAddress = iAddr; // 直接指定地址
else mAddress = (PUCHAR)dllMemBaseAddr[ iIndex ] + (ULONG)iAddr; // 只是指定偏移地址,要加上基址
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncWriteMemByte; // 以字节为单位写入存储器
mCommand.mAddress = mAddress;
mCommand.mLength = 1;
mCommand.mBuffer[0] = iByte; // 待写入的字节数据
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
return( TRUE );
else return( FALSE );
}
BOOL WINAPI CH365mWriteMemDword( // 向存储器写入一个双字
ULONG iIndex, // 指定CH365设备序号
PVOID iAddr, // 指定存储器的地址,虚拟地址
ULONG iDword ) // 待写入的双字数据
{
PVOID mAddress;
ULONG mLength;
mWIN32_COMMAND mCommand;
if ( iAddr >= (PVOID)dllMemBaseAddr[ iIndex ] ) mAddress = iAddr; // 直接指定地址
else mAddress = (PUCHAR)dllMemBaseAddr[ iIndex ] + (ULONG)iAddr; // 只是指定偏移地址,要加上基址
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncWriteMemDword; // 以双字为单位写入存储器
mCommand.mAddress = mAddress;
mCommand.mLength = 4;
*(PULONG) & mCommand.mBuffer[0] = iDword; // 待写入的双字数据
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
return( TRUE );
else return( FALSE );
}
BOOL WINAPI CH365mReadConfig( // 从配置空间读取一个字节数据
ULONG iIndex, // 指定CH365设备序号
PVOID iOffset, // 指定偏移地址
PUCHAR oByte ) // 指向一个字节单元,用于保存读取的字节数据
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncReadConfig; // 以字节为单位读取配置空间
mCommand.mAddress = iOffset;
mCommand.mLength = 1;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
*oByte = mCommand.mBuffer[0]; // 返回读取的字节数据
return( TRUE );
}
else return( FALSE );
}
BOOL WINAPI CH365mWriteConfig( // 向配置空间写入一个字节数据
ULONG iIndex, // 指定CH365设备序号
PVOID iOffset, // 指定偏移地址
UCHAR iByte ) // 待写入的字节数据
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncWriteConfig; // 以字节为单位写入配置空间
mCommand.mAddress = iOffset;
mCommand.mLength = 1;
mCommand.mBuffer[0] = iByte; // 待写入的字节数据
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
return( TRUE );
else return( FALSE );
}
BOOL WINAPI CH365mSetA15_A8( // 设置高地址,即设置A15-A8的输出
ULONG iIndex, // 指定CH365设备序号
UCHAR iA15_A8 ) // 位7-位0对应A15-A8的输出,1为高电平,0为低电平
{
PVOID mAddress;
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncWriteIoByte; // 以字节为单位写入I/O端口
mCommand.mAddress = & dllIoBaseAddr[ iIndex ] -> mCh365MemAddrH; // A15-A8地址设定寄存器
mCommand.mLength = 1;
mCommand.mBuffer[0] = iA15_A8; // 改变A15-A8
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) )
return( TRUE );
return( FALSE );
}
BOOL WINAPI CH365mReadI2C( // 从I2C接口读取一个字节数据
ULONG iIndex, // 指定CH365设备序号
UCHAR iDevice, // 低7位指定I2C设备地址
UCHAR iAddr, // 指定数据单元的地址
PUCHAR oByte ) // 指向一个字节单元,用于保存读取的字节数据
{
UCHAR mByte;
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cDev, (UCHAR) ( iDevice << 1 | 0x01 ) ) ) { // 设备地址和命令
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cAddr, iAddr ) ) { // 设定地址
if ( CH365mReadIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cCtrl, &mByte ) ) { // 读取控制和状态
mByte |= 0x01; // 位0置1则启动操作
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cCtrl, mByte ) ) { // 开始读操作
while ( mByte & 0x01 ) CH365mReadIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cCtrl, &mByte ); // 等待读操作完成
if ( CH365mReadIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cData, oByte ) ) { // 返回读取的数据
CH365DelayUS( 4 ); // 延时4uS作为两次I2C操作的间隔
return( TRUE );
}
}
}
}
}
return( FALSE );
}
BOOL WINAPI CH365mWriteI2C( // 向I2C接口写入一个字节数据
ULONG iIndex, // 指定CH365设备序号
UCHAR iDevice, // 低7位指定I2C设备地址
UCHAR iAddr, // 指定数据单元的地址
UCHAR iByte ) // 待写入的字节数据
{
UCHAR mByte;
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cDev, (UCHAR) ( iDevice << 1 | 0x00 ) ) ) { // 设备地址和命令
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cAddr, iAddr ) ) { // 设定地址
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cData, iByte ) ) { // 待写入的数据
if ( CH365mReadIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cCtrl, &mByte ) ) { // 读取控制和状态
mByte |= 0x01; // 位0置1则启动操作
if ( CH365mWriteIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cCtrl, mByte ) ) { // 开始写操作
while ( mByte & 0x01 ) CH365mReadIoByte( iIndex, & dllIoBaseAddr[ iIndex ] -> mCh365I2cCtrl, &mByte ); // 等待写操作完成
CH365DelayUS( 4 ); // 延时4uS作为两次I2C操作的间隔
return( TRUE );
}
}
}
}
}
return( FALSE );
}
BOOL WINAPI CH365DelayUS( // 延时指定微秒
ULONG iDelay ) // 指定要延时的微秒数,如果延时小于10则误差较大
{
UCHAR mByte;
UCHAR mTime;
ULONG ms, us;
ULONG mIndex;
for ( mIndex = 0; mIndex < mCH365_MAX_NUMBER; ++mIndex ) if ( dllHandle[ mIndex ] != INVALID_HANDLE_VALUE ) break; // 搜索一个有效句柄
if ( mIndex >= mCH365_MAX_NUMBER ) return( FALSE ); // 设备句柄无效
ms = iDelay / 983; // 计算硬件计时周期, 983.04uS, 近似1毫秒
us = iDelay % 983; // 计算剩余微秒数
while ( ms -- ) { // CH365硬件循环计数周期
CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 读取硬件循环计数寄存器 */
mTime = mByte;
while ( mByte == mTime ) CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 等待计数开始 */
while ( mByte != mTime ) CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 等待一个计数周期 */
}
if ( us > 10 ) { /* 剩余微秒数大于10 */
mTime = (UCHAR)( ( 50 * us ) / (ULONG)( 50 * 3.84 ) ); /* 计算硬件计时数, 3.84uS */
CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 读取硬件循环计数寄存器 */
mTime += mByte; /* 加上起始值为计数终值 */
while ( mByte != mTime ) CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 等待计数结束 */
}
else { /* 剩余微秒数小于10 */
while ( us -- ) { /* 每个周期近似1uS */
CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 读取硬件循环计数寄存器 */
CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 读取硬件循环计数寄存器 */
CH365mReadIoByte( mIndex, & dllIoBaseAddr[ mIndex ] -> mCh365IoTime, &mByte ); /* 读取硬件循环计数寄存器 */
}
}
}
BOOL WINAPI CH365mAccessBlock( // 读取或者写入数据块
ULONG iIndex, // 指定CH365设备序号
ULONG iAccessMode, // 参考下面的说明
PVOID iAddr, // 指定I/O端口或者存储器的地址
PVOID ioBuffer, // 指向输入或者输出的缓冲区,存放读出的数据或者准备写出的数据
ULONG iLength ) // 数据块长度,也就是读取或者写入的字节数,长度不超过32KB
// iAccessMode 定义如下
// #define mFuncReadIoByte 0x00000010 // 读取输入输出端口,在同一个端口地址以字节为单位连续读取,最大长度32KB
// #define mFuncReadIoWord 0x00000011 // 读取输入输出端口,在同一个端口地址以字为单位连续读取,最大长度32KB
// #define mFuncReadIoDword 0x00000012 // 读取输入输出端口,在同一个端口地址以双字为单位连续读取,最大长度32KB
// #define mFuncReadIoBlock 0x00000013 // 读取输入输出端口,每读取一个字节,端口地址加一,最大长度240B(从偏移地址00H读到EFH)
// #define mFuncWriteIoByte 0x00000014 // 写入输入输出端口,在同一个端口地址以字节为单位连续写入,最大长度32KB
// #define mFuncWriteIoWord 0x00000015 // 写入输入输出端口,在同一个端口地址以字为单位连续写入,最大长度32KB
// #define mFuncWriteIoDword 0x00000016 // 写入输入输出端口,在同一个端口地址以双字为单位连续写入,最大长度32KB
// #define mFuncWriteIoBlock 0x00000017 // 写入输入输出端口,每写入一个字节,端口地址加一,最大长度240B(从偏移地址00H写到EFH)
// #define mFuncReadMemByte 0x00000018 // 读取存储器/寄存器,以字节为单位连续读,每读取一个字节,地址加一,最大长度32KB(从偏移地址0000H读到7FFFH)
// #define mFuncReadMemWord 0x00000019 // 读取存储器/寄存器,以字为单位连续读,每读取一个字,地址加二,最大长度32KB(从偏移地址0000H读到7FFFH)
// #define mFuncReadMemDword 0x0000001a // 读取存储器/寄存器,以双字为单位连续读,每读取一个字节,地址加四,最大长度32KB(从偏移地址0000H读到7FFFH)
// #define mFuncWriteMemByte 0x0000001c // 写入存储器/寄存器,以字节为单位连续写,每读取一个字节,地址加一,最大长度32KB(从偏移地址0000H写到7FFFH)
// #define mFuncWriteMemWord 0x0000001d // 写入存储器/寄存器,以字为单位连续写,每读取一个字,地址加二,最大长度32KB(从偏移地址0000H写到7FFFH)
// #define mFuncWriteMemDword 0x0000001e // 写入存储器/寄存器,以双字为单位连续写,每读取一个双字,地址加四,最大长度32KB(从偏移地址0000H写到7FFFH)
// 其它方式不支持,上述定义在文件CH365DLL.H中
{
BOOL mRead;
PVOID mAddress;
ULONG mLength;
UCHAR mBuffer[ mWIN32_COMMAND_HEAD + 1024 ];
mPWIN32_COMMAND mpCommand;
mRead = FALSE;
switch ( iAccessMode ) {
case mFuncReadIoByte:
case mFuncReadIoWord:
case mFuncReadIoDword:
mRead = TRUE;
case mFuncWriteIoByte:
case mFuncWriteIoWord:
case mFuncWriteIoDword:
// if ( iAddr >= (PVOID)dllIoBaseAddr[ iIndex ] ) mAddress = iAddr; // 直接指定地址
if ( iAddr >= (PVOID)0x0100 ) mAddress = iAddr; // 本址定址功能的ISA兼容地址
else mAddress = (PUCHAR)dllIoBaseAddr[ iIndex ] + (ULONG)iAddr; // 只是指定偏移地址,要加上基址
break;
case mFuncReadIoBlock:
mRead = TRUE;
case mFuncWriteIoBlock:
// if ( iAddr >= (PVOID)dllIoBaseAddr[ iIndex ] ) mAddress = iAddr; // 直接指定地址
if ( iAddr >= (PVOID)0x0100 ) mAddress = iAddr; // 本址定址功能的ISA兼容地址
else mAddress = (PUCHAR)dllIoBaseAddr[ iIndex ] + (ULONG)iAddr; // 只是指定偏移地址,要加上基址
if ( ( (ULONG)mAddress & 0x00ff ) + iLength >= mOFFSET( mCH365_IO_REG, mCh365MemAddr ) ) return( FALSE ); /* 超出I/O连续地址范围 */
break;
case mFuncReadMemByte:
case mFuncReadMemWord:
case mFuncReadMemDword:
mRead = TRUE;
case mFuncWriteMemByte:
case mFuncWriteMemWord:
case mFuncWriteMemDword:
if ( iAddr >= (PVOID)dllMemBaseAddr[ iIndex ] ) mAddress = iAddr; // 直接指定地址
else mAddress = (PUCHAR)dllMemBaseAddr[ iIndex ] + (ULONG)iAddr; // 只是指定偏移地址,要加上基址
break;
default:
return( FALSE );
break;
}
mLength = mWIN32_COMMAND_HEAD + iLength; // 缓冲区长度为命令结构头的长度加上数据长度
if ( iLength == 0 ) return( TRUE );
else if ( iLength <= 1024 ) mpCommand = (PVOID)mBuffer; // 不超过默认缓冲区长度
else if ( iLength > mMAX_BUFFER_LENGTH ) return( FALSE ); // 非正常长度
else { // 需要另外分配内存
mpCommand = (mPWIN32_COMMAND)LocalAlloc( LMEM_FIXED, mLength ); // 分配内存
if ( mpCommand == NULL ) return( FALSE ); // 分配内存失败
}
mpCommand -> mFunction = iAccessMode; // 存取I/O端口或者存储器
mpCommand -> mAddress = mAddress;
mpCommand -> mLength = iLength;
if ( mRead == FALSE ) CopyMemory( & mpCommand -> mBuffer[0], ioBuffer, iLength ); // 复制准备写入的数据
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, mpCommand, mLength, mpCommand, mLength, &mLength, NULL ) ) {
if ( mRead == TRUE ) CopyMemory( ioBuffer, & mpCommand -> mBuffer[0], iLength ); // 返回读取的数据
if ( (PUCHAR)mpCommand != mBuffer ) LocalFree( mpCommand ); // 如果是分配的内存则释放
return( TRUE );
}
else { // 出错
if ( (PUCHAR)mpCommand != mBuffer ) LocalFree( mpCommand ); // 如果是分配的内存则释放
return( FALSE );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -