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

📄 exam_api.c

📁 usb isp demo source code
💻 C
📖 第 1 页 / 共 2 页
字号:
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_STA;  // 产生起始位
	mBuffer[ 2 ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | 2 );  // 输出数据,位5-位0为长度,2字节
	mBuffer[ 3 ] = (UCHAR)( iDeviceAddr & 0xFE );  // 设备地址,写操作
	mBuffer[ 4 ] = (UCHAR)iOutByte;  // I/O数据
	mBuffer[ 5 ] = mUSBIO_CMD_I2C_STM_STO;  // 产生停止位
	mBuffer[ 6 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 7;
	return( USBIO_WriteData( iIndex, mBuffer, &mLength ) );  // 写出数据块
}

BOOL	WINAPI	PCF8574_ReadIO(  // 输入PCF8574的I/O
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iDeviceAddr,  // 设备地址,最低位为命令方向位
	PUCHAR			oInByte )  // 指向一个字节的缓冲区,返回后是读入的I/O数据
{  // 可以直接用USBIO_StreamI2C( iIndex, 1, mBuffer, 1, oInByte )实现
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	ULONG	mLength, mInLen;
	mBuffer[ 0 ] = mUSBIO_CMD_I2C_STREAM;  // 命令码
	mBuffer[ 1 ] = mUSBIO_CMD_I2C_STM_STA;  // 产生起始位
	mBuffer[ 2 ] = (UCHAR)( mUSBIO_CMD_I2C_STM_OUT | 1 );  // 输出数据,位5-位0为长度,1字节
	mBuffer[ 3 ] = (UCHAR)( iDeviceAddr | 0x01 );  // 设备地址,读操作
	mBuffer[ 4 ] = (UCHAR)( mUSBIO_CMD_I2C_STM_IN | 1 );  // 输入数据,位5-位0为长度,1字节
	mBuffer[ 5 ] = mUSBIO_CMD_I2C_STM_STO;  // 产生停止位
	mBuffer[ 6 ] = mUSBIO_CMD_I2C_STM_END;  // 当前包提前结束
	mLength = 7;
	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 );
}

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

BOOL	WINAPI	PCA9554_SetIO(  // 设置PCA9554的I/O方向
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iDeviceAddr,  // 设备地址,最低位为命令方向位
	ULONG			iSetByte )  // 方向数据
{  // 也可以用USBIO_WriteI2C实现
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	mBuffer[ 0 ] = (UCHAR)( iDeviceAddr & 0xFE );  // 设备地址,写操作
	mBuffer[ 1 ] = 0x03;
	mBuffer[ 2 ] = (UCHAR)iSetByte;  // I/O方向数据
	return( USBIO_StreamI2C( iIndex, 3, mBuffer, 0, NULL ) );  // 处理I2C数据流
}

BOOL	WINAPI	PCA9554_WriteIO(  // 输出PCA9554的I/O
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iDeviceAddr,  // 设备地址,最低位为命令方向位
	ULONG			iOutByte )  // 准备写出的I/O数据
{  // 也可以用USBIO_WriteI2C实现
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	mBuffer[ 0 ] = (UCHAR)( iDeviceAddr & 0xFE );  // 设备地址,写操作
	mBuffer[ 1 ] = 0x01;
	mBuffer[ 2 ] = (UCHAR)iOutByte;  // I/O数据
	return( USBIO_StreamI2C( iIndex, 3, mBuffer, 0, NULL ) );  // 处理I2C数据流
}

BOOL	WINAPI	PCA9554_ReadIO(  // 输入PCA9554的I/O
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iDeviceAddr,  // 设备地址,最低位为命令方向位
	PUCHAR			oInByte )  // 指向一个字节的缓冲区,返回后是读入的I/O数据
{  // 也可以用USBIO_ReadI2C实现
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH ];
	mBuffer[ 0 ] = (UCHAR)( iDeviceAddr & 0xFE );  // 设备地址,USBIO_StreamI2C自动处理读操作
	mBuffer[ 1 ] = 0x00;
	return( USBIO_StreamI2C( iIndex, 2, mBuffer, 1, oInByte ) );  // 处理I2C数据流
}

/* ********************************************************************************************** */
/* 用EPP或者MEM并口进行多位输出或者多位输入,模拟只读或者只写的SPI时序 */

/* 下面是用EPP并口USBIO_EppWriteData模拟只是进行输出的SPI时序,参考下图波形(选择等宽的中文字体时才能看出)
       ___                                                           ___
  WR#     |_________________________________________________________|       SPI_CS
       ______    ___    ___    ___    ___    ___    ___    ___    ______
  DS#        |__|   |__|   |__|   |__|   |__|   |__|   |__|   |__|          SPI_CLK
       ____        ______ ______        ______                      ____
  D0       |______|      |      |______|      |______|______|______|        SPI_DOUT0
       ____ ______        ______ ______ ______        ______        ____
  D1       |      |______|      |      |      |______|      |______|        SPI_DOUT1
       ____                      ______                      ______ ____
  D5       |______|______|______|      |______|______|______|      |        SPI_DOUT5

  如果用USBIO_MemWriteAddr0代替USBIO_EppWriteData,那么波形如下
       ___                                                           ___
  ADDR    |_________________________________________________________|       SPI_CS
       ______    ___    ___    ___    ___    ___    ___    ___    ______
  WR#        |__|   |__|   |__|   |__|   |__|   |__|   |__|   |__|          SPI_CLK

   相应的源程序如下 */

BOOL	WINAPI	Exam_EppSerialOut(
	ULONG			iIndex )  // 指定USB2ISP设备序号
{
	UCHAR	mBuffer[256];
	ULONG	mLength;
	mBuffer[0]=0x02;
	mBuffer[1]=0x01;
	mBuffer[2]=0x03;
	mBuffer[3]=0x22;
	mBuffer[4]=0x03;
	mBuffer[5]=0x00;
	mBuffer[6]=0x02;
	mBuffer[7]=0x20;
	mLength = 8;  /* 如果多于31个那么在WR#引脚的低电平中间将出现高电平脉冲 */
	return( USBIO_EppWriteData( iIndex, mBuffer, &mLength ) );
}

/* 下面是用MEM并口USBIO_MemReadAddr0模拟只是进行输入的SPI时序,参考下图波形(选择等宽的中文字体时才能看出)
       ___                                                                  ___
  ADDR    |________________________________________________________________|       SPI_CS
       _____      __      __      __      __      __      __      __      _____
  RD#       |____|  |____|  |____|  |____|  |____|  |____|  |____|  |____|         SPI_CLK
       ______    ____    ____    ____    ____    ____    ____    ____    ______
  D0/in      |IN|    |IN|    |IN|    |IN|    |IN|    |IN|    |IN|    |IN|          SPI_DIN0
       ______    ____    ____    ____    ____    ____    ____    ____    ______
  D7/in      |IN|    |IN|    |IN|    |IN|    |IN|    |IN|    |IN|    |IN|          SPI_DIN7

  如果用USBIO_EppReadData代替USBIO_MemReadAddr0,那么波形如下
       _______________________________________________________________________
  WR#
       _____      __      __      __      __      __      __      __      _____
  DS#       |____|  |____|  |____|  |____|  |____|  |____|  |____|  |____|         SPI_CLK

   相应的源程序如下 */

BOOL	WINAPI	Exam_MemSerialIn(
	ULONG			iIndex )  // 指定USB2ISP设备序号
{
	UCHAR	mBuffer[256];
	ULONG	mLength, i;
	mLength = 8;  /* 如果多于31个那么在ADDR引脚的低电平中间将出现高电平脉冲 */
	if ( USBIO_MemReadAddr0( iIndex, mBuffer, &mLength ) == FALSE ) return( FALSE );
	for ( i = 0; i < mLength; i ++ ) {
/*		printf( "D0 is %d, D1 is %d, D7 is %d\n", mBuffer[i]&1, mBuffer[i]>>1&1, mBuffer[i]>>7&1 );*/
	}
	return( TRUE );
}

/* ********************************************************************************************** */
/* 用UIO通用I/O位流命令实现自定义的同步串行接口 */

/* UIO方式共可以使用8个I/O引脚D7-D0,最多可以8个输入或者6个输出
   上位机以字节流控制USBIO_对最终位流进行输入和输出,有4种基本操作和1个结束操作:
#define		mUSBIO_CMD_UIO_STM_IN	0x00		// UIO接口的命令流:输入数据D7-D0
#define		mUSBIO_CMD_UIO_STM_DIR	0x40		// UIO接口的命令流:设定I/O方向D5-D0,位5-位0为方向数据
#define		mUSBIO_CMD_UIO_STM_OUT	0x80		// UIO接口的命令流:输出数据D5-D0,位5-位0为数据
#define		mUSBIO_CMD_UIO_STM_US	0xC0		// UIO接口的命令流:以微秒为单位延时,位5-位0为延时值
#define		mUSBIO_CMD_UIO_STM_END	0x20		// UIO接口的命令流:命令包提前结束

   例子:操作10位ADC芯片TLC1549,其时序为非标准
   连线: USBIO__D0 <-> TLC1549_CS, USBIO__D1 <-> TLC1549_IO_CLK, USBIO__D7 <-> TLC1549_DOUT
   下面是用UIO通用I/O位流命令实现的任意波形,参考下图波形(选择等宽的中文字体时才能看出)
         ______                                                                        ____________
  D0/out       |______________________________________________________________________|            |_________   TLC1549_CS#
         ____     ___    ___    ___    ___    ___    ___    ___    ___    ___    ___    Delay 24uS    ___
  D1/out     |___| 1 |__| 2 |__| 3 |__| 4 |__| 5 |__| 6 |__| 7 |__| 8 |__| 9 |__| 10|________________| 1 |__|   TLC1549_I/O_CLOCK

  D7/in  ------| A9  |  A8  |  A7  |  A6  |  A5  |  A4  |  A3  |  A2  |  A1  |  A0  |__/-----------| B9  | B8   TLC1549_DATA_OUT

   相应的源程序如下 */

BOOL	WINAPI	TLC1549_ReadADC(  // 读取TLC1549的ADC结果
	ULONG			iIndex,  // 指定USB2ISP设备序号
	PULONG			oLastADC )  // 指向一个双字单元,返回读出的上次ADC的结果
{
#define		TLC1549_MAX_BIT		10	// 10位ADC
	UCHAR	mBuffer[ mUSBIO_PACKET_LENGTH * 2 ];
	ULONG	i, j, mLength;
	i = 0;
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STREAM;  // 命令码
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x01;  // default status: D0=1, D1=0, CS#=HIGH, I/O_CLOCK=LOW
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_DIR | 0x03;  // D0 output, D1 output, other input
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x00;  // D0=0, CS#=LOW
	for ( j = 0; j < 8; j ++ ) {  // input 8 bit
		mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x02;  // D1=1, I/O_CLOCK=HIGH
		mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_IN;  // input 1 byte from D7-D0, input A9,A8,A7,A6,A5,A4,A3,A2
		mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x00;  // D1=0, I/O_CLOCK=LOW
	}
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_END;  // 当前命令包提前结束,因为一个包放不下,所以分成两个包
	i = mUSBIO_PACKET_LENGTH;
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STREAM;  // 命令码
	for ( j = 0; j < TLC1549_MAX_BIT - 2; j ++ ) {  // input 2 bit
		mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x02;  // D1=1, I/O_CLOCK=HIGH
		mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_IN;  // input 1 byte from D7-D0, input A1,A0
		mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x00;  // D1=0, I/O_CLOCK=LOW
	}
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_OUT | 0x01;  // D0=1, CS#=HIGH
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_US | 24;  // delay 24uS,实际上这个延时完全不需要,因为USB传输每1mS一次,下次传输是在1mS之后
	mBuffer[ i++ ] = mUSBIO_CMD_UIO_STM_END;  // 当前命令包提前结束
	mLength = 0;
	j = USBIO_WriteRead( iIndex, i, mBuffer, 8, 2, &mLength, mBuffer );  // 执行数据流命令,先输出再输入,执行两次输入,每次最多8字节
	*oLastADC = 0;
	if ( j ) {
		if ( mLength == TLC1549_MAX_BIT ) {  // 输入长度正确
			for ( i = 0; i < TLC1549_MAX_BIT; i ++ ) {  // 将每字节的位7合并为10位ADC结果数据
				*oLastADC = ( *oLastADC << 1 ) | ( mBuffer[ i ] >> 7 );  // 位7移到位0
			}
			return( TRUE );
		}
	}
	return( FALSE );
}

/* ********************************************************************************************** */
/* 例子:操作4线接口SPI存储器25F512、25F020 */
/* 连线: USBIO__DCK/D3 <-> 25FXX_SCK, USBIO__DOUT/D5 <-> 25FXX_SI, USBIO__DIN/D7 <-> 25FXX_SO, USBIO__D0 <-> 25FXX_CS# */

BOOL	WINAPI	AT25F512_ReadBlock(  // 读AT25F512的块 (包括:输出器件读命令码,输出3字节共24位地址,读入数据块)
	ULONG			iIndex,  // 指定USB2ISP设备序号
	ULONG			iAddress,  // 指定操作地址
	ULONG			iInLength,  // 准备读取的数据字节数,单次建议小于1024字节
	PVOID			oInBuffer )  // 指向一个缓冲区,返回后是读入的数据
{
	static	BOOL	mTheFirst = TRUE;
	if ( mTheFirst ) {  // 首次进入时需要设置I/O方向
		if ( USBIO_SetStream( iIndex, 0x81 ) == FALSE ) return( FALSE );  // 设置串口流模式:SPI为单入单出,SPI字节中的位顺序是高位在前
		mTheFirst = FALSE;
	}
	if ( iInLength == 0 || iInLength > mDEFAULT_BUFFER_LEN ) return( FALSE );
	*( (PUCHAR)oInBuffer + 0 ) = 0x03;  // 读存储器命令码,注意各器件不一定命令码相同
	*( (PUCHAR)oInBuffer + 1 ) = (UCHAR)( iAddress >> 16 & 0xFF );  // 指定读操作的地址A23-A16
	*( (PUCHAR)oInBuffer + 2 ) = (UCHAR)( iAddress >> 8 & 0xFF );  // 指定读操作的地址A15-A8
	*( (PUCHAR)oInBuffer + 3 ) = (UCHAR)( iAddress & 0xFF );  // 指定读操作的地址A7-A0
//	memset( (PUCHAR)oInBuffer + 4, 0xFF, iInLength );  // 对于有些SPI器件,可能要求在读出数据时SI输入保持为1或者0,那么就要在此设置
	if ( USBIO_StreamSPI4( iIndex, 0x80, iInLength + 4, oInBuffer ) == FALSE ) return( FALSE );  // 处理4线接口SPI数据流,自动片选为D0
/* 对于25F512的读操作,要先输出4个字节命令及地址,再输入若干个字节数据,调用API和API返回时都是指总长度,所以返回数据的前4个字节是在输出命令及地址时输入的,应该丢弃 */
	memmove( oInBuffer, (PUCHAR)oInBuffer + 4, iInLength );  // 因为USBIO_的SPI是数据流,所以实际返回数据应该去掉自己发出的4个字节(命令和地址)
	return( TRUE );
}

/* ********************************************************************************************** */
/* 例子:操作类似SPI的非标准串行时序的8位ADC芯片ADC0831、TLC0831 */
/* 连线: USBIO__DCK/D3 <-> ADC0831_CLK, USBIO__DIN/D7 <-> ADC0831_DO, USBIO__D2 <-> ADC0831_CS# */

BOOL	WINAPI	ADC0831_ReadADC(  // 读取ADC结果
	ULONG			iIndex,  // 指定USB2ISP设备序号
	PUCHAR			oADC )  // 指向一个字节单元,返回读出的ADC结果
{
	static	BOOL	mTheFirst = TRUE;
	UCHAR	mBuffer[ 256 ];
	ULONG	i;
	if ( mTheFirst ) {  // 首次进入时需要设置I/O方向
		if ( USBIO_Set_D5_D0( iIndex, 0x0C, 0x04 ) == FALSE ) return( FALSE );  // 设置USBIO_的D5-D0引脚的I/O方向,DCK/D3输出默认为0,D2输出默认为1
		mTheFirst = FALSE;
	}
	for ( i = 0; i < 12; i ++ ) {
		mBuffer[ i ] = 0x00;  // CS=0 for 1st bit to 12th bit
	}
	mBuffer[ i++ ] = 0x04;  // CS=1 for 13th bit
	if ( USBIO_BitStreamSPI( iIndex, i, mBuffer ) == FALSE ) return( FALSE );  // 处理SPI位数据流,输入输出共13位,实际未全部用到
	*oADC = 0;
	for ( i = 0; i < 8; i ++ ) {  // 将每字节的位7合并为8位ADC结果数据
		*oADC = ( *oADC << 1 ) | ( mBuffer[ i + 1 ] >> 7 );  // 位7移到位0,跳过首字节无效数据,第2个时钟的输入数据才是MSB位
	}
	return( TRUE );
}

/* ********************************************************************************************** */

main( ) {
	return(1);
}

⌨️ 快捷键说明

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