⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exam_api.c

📁 usb isp demo source code
💻 C
📖 第 1 页 / 共 2 页
字号:
// V1.1

#include	<windows.h>
#include	"USBIOX.H"

/* 本程序涉及到
 1、2线接口的一些自定义时序,处理I2C总线的应答位,以及了解2线接口的内部时序分析
 2、提供例子程序,操作2线接口I2C器件X76F640、PCF8574、PCA9554
 3、用EPP或者MEM并口进行多位输出或者多位输入,模拟只读或者只写的SPI时序
 4、用UIO通用I/O位流命令实现自定义的同步串行接口
 5、提供例子程序,操作类似SPI的非标准串行时序的器件TLC1549
 6、提供例子程序,通过USBIO_StreamSPI4操作4线接口SPI器件25C512、25C020
 7、提供例子程序,通过USBIO_BitStreamSPI操作类似SPI的非标准串行时序的器件ADC0831
 另外可以用USBIO_SetOutput设置USBIO_的I/O方向,并通过USBIO_的任何一个引脚直接输出数据,未提供例子,建议用USBIO_Set_D5_D0代替
*/

/* USB2ISP并口驱动及DLL的API层次,按从低向高分为
 1、USBIO_DriverCommand直接传给WDM驱动程序层
 2、USBIO_WriteData只写数据, USBIO_ReadData只读数据, USBIO_WriteRead先写数据再读数据
 3、USBIO_StreamI2C先写I2C,可选地再读I2C (内部调用USBIO_WriteData和USBIO_WriteRead)
    USBIO_StreamSPI进行SPI传输,读写都是可选的 (内部调用USBIO_WriteRead)
 4、USBIO_ReadEEPROM读EEPROM数据, USBIO_WriteEEPROM写EEPROM数据 (内部调用USBIO_StreamI2C)
 本例子中的子程序将调用USBIO_WriteData、USBIO_WriteRead、USBIO_StreamI2C等DLL中的API */

/* 实测速度
   USBIO_StreamI2C     约56K字节
   USBIO_ReadEEPROM    约56K字节
   USBIO_WriteEEPROM   约5K字节(如果是RAM而非闪存那么与USBIO_ReadEEPROM速度相同)
   USBIO_StreamSPI4    约68K字节
   USBIO_StreamSPI5    每路约30K字节  * 2路输入和2路输出
   USBIO_BitStreamSPI  每路约8K位     * 至少2路输入和2路输出(最多7路输入4路输出)
*/

/* ********************************************************************************************** */
/* 例子:兼容I2C总线的通用操作时序 */

BOOL	WINAPI	I2C_IssueStart(
	ULONG			iIndex )  // 指定USB2ISP设备序号
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_STA;  // 产生起始位
	mBuffer[ 2 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 3;
	return( USBIO_WriteData( iIndex, mBuffer, &mLength ) );  // 写出数据块
}

BOOL	WINAPI	I2C_IssueStop(
	ULONG			iIndex )  // 指定USB2ISP设备序号
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_STO;  // 产生停止位
	mBuffer[ 2 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 3;
	return( USBIO_WriteData( iIndex, mBuffer, &mLength ) );  // 写出数据块
}

BOOL	WINAPI	I2C_OutBlockSkipAck(  // 输出数据块,不检查应答
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iOutLength,  // 准备写出的数据字节数,单次必须小于29字节
	PVOID			iOutBuffer )  // 指向一个缓冲区,放置准备写出的数据
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength;
	if ( iOutLength == 0 || iOutLength > ( mUSBIO_PACKET_LENGTH - 1 - 1 - 1 ) ) return( FALSE );
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | iOutLength );  // 输出数据,位5-位0为长度
	memcpy( &mBuffer[2], iOutBuffer, iOutLength );  // 数据
	mBuffer[ 1 + 1 + iOutLength ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 1 + 1 + iOutLength + 1;
	return( USBIO_WriteData( iIndex, mBuffer, &mLength ) );  // 写出数据块
}

BOOL	WINAPI	I2C_OutByteCheckAck(  // 输出一字节数据并检查应答是否有效
	ULONG			iIndex,  // 指定USB2ISP设备序号
	UCHAR			iOutByte )  // 准备写出的数据
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength, mInLen;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_OUT;  // 输出数据,位5-位0为长度,0长度则只发送一个字节并返回应答
	mBuffer[ 2 ] = iOutByte;  // 数据
	mBuffer[ 3 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 4;
	mInLen = 0;
	if ( USBIO_WriteRead( iIndex, mLength, mBuffer, mUSBIO_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) {  // 执行数据流命令,先输出再输入
		if ( mInLen && ( mBuffer[ mInLen - 1 ] & 0x80 ) == 0 ) return( TRUE );  // 返回的数据的位7代表ACK应答位,ACK=0有效
	}
	return( FALSE );
}

BOOL	WINAPI	I2C_InBlockByAck(  // 输入数据块,每输入一个字节都产生有效应答
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iInLength,  // 准备读取的数据字节数,单次必须小于32字节
	PVOID			oInBuffer )  // 指向一个缓冲区,返回后是读入的数据
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength, mInLen;
	if ( iInLength == 0 || iInLength > mUSBIO_CMD_I2C_STM_MAX ) return( FALSE );
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = (UCHAR)( mUSBIO_CMD_I2C_STM_IN | iInLength );  // 输入数据,位5-位0为长度
	mBuffer[ 2 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 3;
	mInLen = 0;
	if ( USBIO_WriteRead( iIndex, mLength, mBuffer, mUSBIO_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) {  // 执行数据流命令,先输出再输入
		if ( mInLen == iInLength ) {
			memcpy( oInBuffer, &mBuffer[0], iInLength );  // 数据
			return( TRUE );
		}
	}
	return( FALSE );
}

BOOL	WINAPI	I2C_InByteNoAck(  // 输入一字节数据,但是不产生应答
	ULONG			iIndex,  // 指定USB2ISP设备序号
	PUCHAR			oInByte )  // 指向一个字节的缓冲区,返回后是读入的数据
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength, mInLen;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_IN;  // 输入数据,位5-位0为长度,0长度则只接收一个字节并发送无应答
	mBuffer[ 2 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 3;
	mInLen = 0;
	if ( USBIO_WriteRead( iIndex, mLength, mBuffer, mUSBIO_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) {  // 执行数据流命令,先输出再输入
		if ( mInLen ) {
			*oInByte = mBuffer[ mInLen - 1 ];  // 数据
			return( TRUE );
		}
	}
	return( FALSE );
}

/* ********************************************************************************************** */
/* 操作加密存储器X76F640 */

BOOL	WINAPI	X76F640_AckPolling(  // 查询X76F640应答 (包括:输出起始位,输出一字节命令数据,检查应答是否有效)
	ULONG			iIndex )  // 指定USB2ISP设备序号
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength, mInLen;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_STA;  // 产生起始位
	mBuffer[ 2 ] = mUSBIO_CMD_I2C_STM_OUT;  // 输出数据,位5-位0为长度,0长度则只发送一个字节并返回应答
	mBuffer[ 3 ] = 0xF0;  // 应答查询操作的命令码
	mBuffer[ 4 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 5;
	mInLen = 0;
	if ( USBIO_WriteRead( iIndex, mLength, mBuffer, mUSBIO_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) {  // 执行数据流命令,先输出再输入
		if ( mInLen && ( mBuffer[ mInLen - 1 ] & 0x80 ) == 0 ) return( TRUE );  // 返回的数据的位7代表ACK应答位,ACK=0有效
	}
	return( FALSE );
}

BOOL	WINAPI	X76F640_CheckPasswd(  // 发出操作命令并检查指定的密码 (包括:输出起始位,输出9字节数据(1命令+8密码),查询应答,输出2字节地址)
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iCommand,  // 操作命令码
	PVOID			iPasswdBuf,  // 指向一个缓冲区,提供8字节的密码数据
	ULONG			iAddress )  // 指定操作地址或者密码后的2字节数据
{
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	i, mLength;
	i = 0;
	mBuffer[ i++ ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_STA;  // 产生起始位
	mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | 9 );  // 输出数据,位5-位0为长度,9字节
	mBuffer[ i++ ] = (UCHAR)iCommand;  // 操作命令码
	memcpy( &mBuffer[ i ], iPasswdBuf, 8 );  // 8字节密码数据
	i += 8;
	mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_MS | 10 );  // 以亳秒为单位延时,位3-位0为延时值,延时10毫秒
	mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = i;
	if ( USBIO_WriteData( iIndex, mBuffer, &mLength ) ) {  // 写出数据块
		if ( X76F640_AckPolling( iIndex ) ) {  // 查询应答有效
			i = 0;
			mBuffer[ i++ ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
			mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | 2 );  // 输出数据,位5-位0为长度
			mBuffer[ i++ ] = (UCHAR)( iAddress & 0x00FF );  // 地址低8位
			mBuffer[ i++ ] = (UCHAR)( ( iAddress >> 8 ) & 0x00FF );  // 地址高8位
			mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
			mLength = i;
			return( USBIO_WriteData( iIndex, mBuffer, &mLength ) );  // 写出数据块
		}
		else I2C_IssueStop( iIndex );  // 应答无效
	}
	return( FALSE );
}

BOOL	WINAPI	X76F640_WriteWithPasswd(  // 写X76F640的块,使用指定的密码
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iWriteCommand,  // 块写命令码
	PVOID			iPasswdBuf,  // 指向一个缓冲区,放置8字节的密码数据
	ULONG			iAddress,  // 指定操作地址
	ULONG			iOutLength,  // 准备写出的数据字节数,单次必须小于32字节(1个扇区)
	PVOID			iOutBuffer )  // 指向一个缓冲区,放置准备写出的数据
{
	UCHAR	mBuffer[ mDEFAULT_BUFFER_LEN ];
	ULONG	i, mLength;
	if ( iOutLength == 0 || iOutLength > 32 ) return( FALSE );
	if ( X76F640_CheckPasswd( iIndex, iWriteCommand, iPasswdBuf, iAddress ) ) {  // 发出命令及密码检查通过
		if ( iOutLength > ( mUSBIO_PACKET_LENGTH - 1 - 1 - 1 - 1 - 1 ) ) {  // 去掉前2字节后3字节,一个包不够用
			mLength = iOutLength - ( mUSBIO_PACKET_LENGTH - 1 - 1 - 1 - 1 - 1);  // 多出的长度
			iOutLength -= mLength;  // 第1个包的数据长度
		}
		else mLength = 0;  // 1个包就够用了
		i = 0;
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
		mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | iOutLength );  // 输出数据,位5-位0为长度
		memcpy( &mBuffer[ i ], iOutBuffer, iOutLength );  // 数据
		i += iOutLength;
		if ( mLength ) {  // 第2包
			mBuffer[ i ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
			i += mUSBIO_PACKET_LENGTH - i % mUSBIO_PACKET_LENGTH;  // 跳过当前包剩余部分
			mBuffer[ i++ ] = mUSBIO_CMD_I2C_STREAM;  // 第2个包的首字节仍然是命令码
			mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | mLength );  // 输出数据,位5-位0为长度
			memcpy( &mBuffer[ i ], (PUCHAR)iOutBuffer + iOutLength, mLength );  // 剩余数据
			i += mLength;
		}
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_STO;  // 产生停止位
		mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_MS | 10 );  // 以亳秒为单位延时,位3-位0为延时值,延时10毫秒
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
		return( USBIO_WriteData( iIndex, mBuffer, &i ) );  // 写出数据块
	}
	return( FALSE );
}

BOOL	WINAPI	X76F640_ReadWithPasswd(  // 读X76F640的块,使用指定的密码 (包括:输出起始位,输出9字节数据(1命令+8密码),查询应答,输出2字节地址,读入数据块)
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iReadCommand,  // 块读命令码
	PVOID			iPasswdBuf,  // 指向一个缓冲区,放置8字节的密码数据
	ULONG			iAddress,  // 指定操作地址
	ULONG			iInLength,  // 准备读取的数据字节数,单次必须小于512字节 ( 每包32 * 16个包 = 512字节 )
	PVOID			oInBuffer )  // 指向一个缓冲区,返回后是读入的数据
{
	UCHAR	mBuffer[ mDEFAULT_BUFFER_LEN ];
	ULONG	i, mLength, mInLen;
	if ( iInLength == 0 || iInLength > ( 16 * mUSBIO_PACKET_LENGTH ) ) return( FALSE );
	if ( X76F640_CheckPasswd( iIndex, iReadCommand, iPasswdBuf, iAddress ) ) {  // 发出命令及密码检查通过
		i = 0;
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
		for ( mInLen = 1; mInLen < iInLength; ) {
			mLength = iInLength - mInLen >= mUSBIO_CMD_I2C_STM_MAX ? mUSBIO_CMD_I2C_STM_MAX : iInLength - mInLen;  // 本次输入有效数据长度
			mBuffer[ i++ ] = (UCHAR)( mUSBIO_CMD_I2C_STM_IN | mLength );  // 输入数据,位5-位0为长度
			mInLen += mLength;
			if ( mLength >= mUSBIO_CMD_I2C_STM_MAX ) {  // 当前包将满
				mBuffer[ i ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
				i += mUSBIO_PACKET_LENGTH - i % mUSBIO_PACKET_LENGTH;  // 跳过当前包剩余部分
				mBuffer[ i++ ] = mUSBIO_CMD_I2C_STREAM;  // 新包的命令码
			}
		}
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_IN;  // 输入最后一个字节数据,只接收一个字节并发送无应答
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_STO;  // 产生停止位
		mBuffer[ i++ ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
		mLength = 0;
		if ( USBIO_WriteRead( iIndex, i, mBuffer, mUSBIO_CMD_I2C_STM_MAX, ( iInLength + mUSBIO_CMD_I2C_STM_MAX - 1 ) / mUSBIO_CMD_I2C_STM_MAX, &mLength, oInBuffer ) ) {  // 执行数据流命令,先输出再输入
			if ( mLength == iInLength ) return( TRUE );
		}
	}
	return( FALSE );
}

/* ********************************************************************************************** */
/* 例子:操作准双向I/O扩展PCF8574 */

BOOL	WINAPI	PCF8574_WriteIO(  // 输出PCF8574的I/O
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iDeviceAddr,  // 设备地址,最低位为命令方向位
	ULONG			iOutByte )  // 准备写出的I/O数据
{  // 可以直接用USBIO_StreamI2C( iIndex, 2, mBuffer, 0, NULL )实现

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -