📄 ch365dll.c
字号:
BOOL WINAPI CH365ReadMemByte( // 从存储器读取一个字节
PVOID iAddr, // 指定存储器的地址,虚拟地址
PUCHAR oByte ) // 指向一个字节单元,用于保存读取的字节数据
{
return( CH365mReadMemByte( 0, iAddr, oByte ) );
}
BOOL WINAPI CH365ReadMemDword( // 从存储器读取一个双字
PVOID iAddr, // 指定存储器的地址,虚拟地址
PULONG oDword ) // 指向一个双字单元,用于保存读取的双字数据
{
return( CH365mReadMemDword( 0, iAddr, oDword ) );
}
BOOL WINAPI CH365WriteMemByte( // 向存储器写入一个字节
PVOID iAddr, // 指定存储器的地址,虚拟地址
UCHAR iByte ) // 待写入的字节数据
{
return( CH365mWriteMemByte( 0, iAddr, iByte ) );
}
BOOL WINAPI CH365WriteMemDword( // 向存储器写入一个双字
PVOID iAddr, // 指定存储器的地址,虚拟地址
ULONG iDword ) // 待写入的双字数据
{
return( CH365mWriteMemDword( 0, iAddr, iDword ) );
}
BOOL WINAPI CH365ReadConfig( // 从配置空间读取一个字节数据
PVOID iOffset, // 指定偏移地址
PUCHAR oByte ) // 指向一个字节单元,用于保存读取的字节数据
{
return( CH365mReadConfig( 0, iOffset, oByte ) );
}
BOOL WINAPI CH365WriteConfig( // 向配置空间写入一个字节数据
PVOID iOffset, // 指定偏移地址
UCHAR iByte ) // 待写入的字节数据
{
return( CH365mWriteConfig( 0, iOffset, iByte ) );
}
BOOL WINAPI CH365SetA15_A8( // 设置高地址,即设置A15-A8的输出
UCHAR iA15_A8 ) // 位7-位0对应A15-A8的输出,1为高电平,0为低电平
{
return( CH365mSetA15_A8( 0, iA15_A8 ) );
}
BOOL WINAPI CH365ReadI2C( // 从I2C接口读取一个字节数据
UCHAR iDevice, // 低7位指定I2C设备地址
UCHAR iAddr, // 指定数据单元的地址
PUCHAR oByte ) // 指向一个字节单元,用于保存读取的字节数据
{
return( CH365mReadI2C( 0, iDevice, iAddr, oByte ) );
}
BOOL WINAPI CH365WriteI2C( // 向I2C接口写入一个字节数据
UCHAR iDevice, // 低7位指定I2C设备地址
UCHAR iAddr, // 指定数据单元的地址
UCHAR iByte ) // 待写入的字节数据
{
return( CH365mWriteI2C( 0, iDevice, iAddr, iByte ) );
}
HANDLE WINAPI CH365mOpenDevice( // 打开CH365设备,返回句柄,出错则无效
ULONG iIndex, // 指定CH365设备序号,0对应第一个设备
BOOL iEnableMemory, // 是否需要支持存储器
BOOL iEnableInterrupt ) // 是否需要支持中断
{
UCHAR mBuffer[1024];
LPGUID mClassGuid;
HDEVINFO mDevInfo;
SP_INTERFACE_DEVICE_DATA mDevIfData;
PSP_INTERFACE_DEVICE_DETAIL_DATA mDevIfDetail;
if ( iIndex >= mCH365_MAX_NUMBER ) return( INVALID_HANDLE_VALUE ); // 太多设备,不支持
mClassGuid = ( LPGUID )&CH365Guid; // 设备类
mDevInfo = SetupDiGetClassDevs( mClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); // 获得指定设备类
if ( mDevInfo == INVALID_HANDLE_VALUE ) return( INVALID_HANDLE_VALUE );
mDevIfData.cbSize = sizeof( mDevIfData );
if ( !SetupDiEnumDeviceInterfaces( mDevInfo, NULL, mClassGuid, iIndex, &mDevIfData ) ) { // 枚举指定序号的设备
SetupDiDestroyDeviceInfoList( mDevInfo );
return( INVALID_HANDLE_VALUE );
}
mDevIfDetail = ( PSP_INTERFACE_DEVICE_DETAIL_DATA ) mBuffer;
mDevIfDetail -> cbSize = sizeof( SP_INTERFACE_DEVICE_DETAIL_DATA );
if ( !SetupDiGetDeviceInterfaceDetail( mDevInfo, &mDevIfData, mDevIfDetail, 1020, NULL, NULL ) ) { // 获得设备详细信息
SetupDiDestroyDeviceInfoList( mDevInfo );
return( INVALID_HANDLE_VALUE );
}
lstrcpy( dllDeviceName[ iIndex ], mDevIfDetail -> DevicePath ); // 设备名称
dllHandle[ iIndex ] = CreateFile( mDevIfDetail -> DevicePath, GENERIC_READ | GENERIC_WRITE, // 打开设备,不支持重叠操作
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
SetupDiDestroyDeviceInfoList( mDevInfo );
if ( dllHandle[ iIndex ] == INVALID_HANDLE_VALUE ) return( INVALID_HANDLE_VALUE ); // 没有打开CH365设备的权限
CH365mGetIoBaseAddr( iIndex, & dllIoBaseAddr[ iIndex ] ); // 获取CH365的I/O基址
CH365mGetMemBaseAddr( iIndex, & dllMemBaseAddr[ iIndex ] ); // 获取CH365的存储器基址
if ( iEnableMemory && dllMemBaseAddr[ iIndex ] == NULL ) // 如果需要支持存储器并且存储器基址尚未设定
CH365mSetMemBaseAddr( iIndex, mCH365_MEM_BASE_AUTO ); // 自动设定存储器基址
CH365mGetIntLine( iIndex, & dllIntLine[ iIndex ] ); // 获得CH365的中断号
if ( iEnableInterrupt && dllIntLine[ iIndex ] == 0 ) // 如果需要支持中断并且中断号尚未检测
CH365mSetIntLine( iIndex, mCH365_INT_LINE_AUTO ); // 自动检测中断号
return( dllHandle[ iIndex ] );
}
VOID WINAPI CH365mCloseDevice( // 关闭CH365设备
ULONG iIndex ) // 指定CH365设备序号
{
dllIntRoutine[ iIndex ] = NULL; // 取消中断服务程序
while ( dllIntThreadId[ iIndex ] ) CH365mAbortWaitInt( iIndex ); // 等待线程结束
CloseHandle( dllHandle[ iIndex ] ); // 关闭句柄
dllHandle[ iIndex ] = INVALID_HANDLE_VALUE;
}
ULONG WINAPI CH365mDriverCommand( // 直接传递命令给驱动程序,出错则返回0,否则返回数据长度
ULONG iIndex, // 指定CH365设备序号
mPWIN32_COMMAND ioCommand ) // 命令结构的指针
// 该程序在调用后返回数据长度,并且仍然返回命令结构,如果是读操作,则数据返回在命令结构中,
// 返回的数据长度在操作失败时为0,操作成功时为整个命令结构的长度,例如读一个字节,则返回mWIN32_COMMAND_HEAD+1,
// 命令结构在调用前,分别提供:命令功能代码,起始地址(可选),存取数据的长度(可选),
// 命令结构在调用后,分别返回:操作状态代码,返回的基址(可选),后续数据的长度(可选),
// 操作状态代码是由WINDOWS定义的代码,可以参考NTSTATUS.H,
// 返回的基址只适用于下列命令:获取I/O基址,获取存储器基址,获取中断号,对于其它命令则保持输入时的起始地址
// 后续数据的长度是指读操作返回的数据长度,数据存放在随后的缓冲区中,对于写操作一般为0
{
ULONG mLength;
mLength = ioCommand -> mLength + mWIN32_COMMAND_HEAD; // 数据缓冲区长度加上命令结构头的长度
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, ioCommand, mLength, ioCommand, mLength, &mLength, NULL ) )
return( mLength ); // 返回数据长度
else return( 0 ); // 出错
}
BOOL WINAPI CH365mGetIoBaseAddr( // 获取I/O端口的基址
ULONG iIndex, // 指定CH365设备序号
mPCH365_IO_REG *oIoBaseAddr ) // 保存I/O端口基址的单元地址
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncGetIoBaseAddr;
mCommand.mAddress = NULL;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
dllIoBaseAddr[ iIndex ] = mCommand.mAddress; // 返回的I/O端口的基址
*oIoBaseAddr = dllIoBaseAddr[ iIndex ]; // 返回
return( TRUE );
}
else return( FALSE ); // 出错
}
BOOL WINAPI CH365mSetIoBaseAddr( // 设定I/O端口的基址
ULONG iIndex, // 指定CH365设备序号
mPCH365_IO_REG iIoBaseAddr ) // 指定I/O端口基址
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncSetIoBaseAddr;
mCommand.mAddress = iIoBaseAddr;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
CH365mGetIoBaseAddr( iIndex, & dllIoBaseAddr[ iIndex ] ); // 重新获取I/O端口的基址
return( TRUE );
}
else { // 出错
CH365mGetIoBaseAddr( iIndex, & dllIoBaseAddr[ iIndex ] ); // 重新获取I/O端口的基址
return( FALSE );
}
}
BOOL WINAPI CH365mGetMemBaseAddr( // 获取存储器的基址
ULONG iIndex, // 指定CH365设备序号
mPCH365_MEM_REG *oMemBaseAddr ) // 保存存储器基址的单元地址
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncGetMemBaseAddr;
mCommand.mAddress = NULL;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
dllMemBaseAddr[ iIndex ] = mCommand.mAddress; // 返回的存储器的基址
*oMemBaseAddr = dllMemBaseAddr[ iIndex ]; // 返回
return( TRUE );
}
else return( FALSE ); // 出错
}
BOOL WINAPI CH365mSetMemBaseAddr( // 设定存储器的基址
ULONG iIndex, // 指定CH365设备序号
mPCH365_MEM_REG iMemBaseAddr ) // 指定存储器基址,为0则关闭存储器,为-1则自动设定
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncSetMemBaseAddr;
mCommand.mAddress = iMemBaseAddr;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
CH365mGetMemBaseAddr( iIndex, & dllMemBaseAddr[ iIndex ] ); // 重新获取存储器的基址
return( TRUE );
}
else { // 出错
CH365mGetMemBaseAddr( iIndex, & dllMemBaseAddr[ iIndex ] ); // 重新获取存储器的基地
return( FALSE );
}
}
BOOL WINAPI CH365mGetIntLine( // 获取中断号
ULONG iIndex, // 指定CH365设备序号
PULONG oIntLine ) // 保存中断号的单元地址
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncGetInterLine;
mCommand.mAddress = NULL;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
dllIntLine[ iIndex ] = (ULONG) mCommand.mAddress; // 返回的中断号
*oIntLine = dllIntLine[ iIndex ]; // 返回
return( TRUE );
}
else return( FALSE ); // 出错
}
BOOL WINAPI CH365mSetIntLine( // 设定中断号
ULONG iIndex, // 指定CH365设备序号
ULONG iIntLine ) // 指定中断号,为0则关闭中断,为-1则自动检测并设定
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncSetInterLine;
mCommand.mAddress = (PVOID)iIntLine;
mCommand.mLength = 0;
if ( DeviceIoControl( dllHandle[ iIndex ], IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, NULL ) ) {
CH365mGetIntLine( iIndex, & dllIntLine[ iIndex ] ); // 重新获取中断号
return( TRUE );
}
else { // 出错
CH365mGetIntLine( iIndex, & dllIntLine[ iIndex ] ); // 重新获取中断号
return( FALSE );
}
}
BOOL WINAPI CH365mWaitInterrupt( // 等待中断事件
ULONG iIndex ) // 指定CH365设备序号
{
ULONG mLength;
mWIN32_COMMAND mCommand;
mLength = sizeof( mWIN32_COMMAND );
mCommand.mFunction = mFuncWaitInterrupt; // 等待中断事件,如果暂时没有中断事件则一直等待,直到发生中断或者放弃等待中断
mCommand.mAddress = NULL;
mCommand.mLength = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -