📄 exam_api.c
字号:
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 + -