📄 ch375host.c
字号:
//=================================================================================================
//*************************************************************************************************
// Module Name : CH375Host.C
// Device object:
// Create date : 2005-11-07
// Modify date : 2005-11-16
// Description : USB 1.1 Host for CH375
// USB 2.0 Host for CH375
// Author : Li yuanzheng
// Version : V1.0
//*************************************************************************************************
//=================================================================================================
//
// 如果设备端不是CH37X,那么分析描述符
// CH375中断为查询方式
//
//-------------------------------------------------------------------------------------------------
// Includes
//-------------------------------------------------------------------------------------------------
#include <regx52.h> // SFR declarations
//#include <string.h>
//#include <stdio.h>
//#include <intrins.h>
#include "CH375Host.H"
//=================================================================================================
//
#define UNKNOWN_USB_DEVICE 0xF1
//*************************************************************************************************
//*************************************************************************************************
// Global VARIABLES
//*************************************************************************************************
//*************************************************************************************************
//
unsigned char RECV_LEN; // 刚接收到的数据的长度
unsigned char idata RECV_BUFFER[ CH375_MAX_DATA_LEN ]; // 数据缓冲区,用于保存接收到的下传数据,长度为0到64字节
unsigned char idata *CommandBuffer;
unsigned char idata *ReceiveBuffer;
#define p_dev_descr ( (PUSB_DEV_DESCR)RECV_BUFFER )
#define p_cfg_descr ( (PUSB_CFG_DESCR_LONG)RECV_BUFFER )
unsigned char EndpOutAddr; // USB数据接收端点的端点地址
unsigned char EndpOutSize; // USB数据接收端点的端点尺寸
unsigned char EndpInAddr; // USB状态发送端点的端点地址,为0则只支持单向接口
unsigned char Endp6Mode, Endp7Mode; //
//=================================================================================================
//=================================================================================================
// LED Flash
//=================================================================================================
//=================================================================================================
//
//=================================================================================================
//=================================================================================================
//
// CH375的INT#引脚连接方式为"查询方式"
//-------------------------------------------------------------------------------------------------
// 查询 CH375 中断并更新中断状态
UINT8 xQueryInterrupt( void )
{
CH375_INT_WIRE = 1;
while( CH375_INT_WIRE ) // 如果CH375的中断引脚输出高电平则等待
{
if( RI==1 ) // 串口接收到数据
xWriteCH375Cmd( CMD_ABORT_NAK ); // 放弃当前操作
return( 0xEF );
}
xWriteCH375Cmd( CMD_GET_STATUS ); // 获取当前中断状态
CH375IntStatus &= 0x80; if ( CH375IntStatus ) CH375IntStatus = 0; // 操作无意义,用于至少延时2uS
CH375IntStatus = xReadCH375Data( ); // 获取中断状态
if ( CH375IntStatus == USB_INT_DISCONNECT ) CH375DiskStatus = DISK_DISCONNECT; // 检测到USB设备断开事件
else if ( CH375IntStatus == USB_INT_CONNECT ) CH375DiskStatus = DISK_CONNECT; // 检测到USB设备连接事件
return( CH375IntStatus );
}
//-------------------------------------------------------------------------------------------------
// 设置CH37X的工作模式
void CH375_SetUSBMode( unsigned char mode )
{
unsigned char i;
xWriteCH375Cmd( CMD_SET_USB_MODE ); // 设置USB工作模式
xWriteCH375Data( mode );
Endp6Mode = Endp7Mode = 0x80; // 主机端复位USB数据同步标志
for( i=100; i!=0; i-- ) // 等待设置模式操作完成,不超过30uS
{
if( xReadCH375Data( ) == CMD_RET_SUCCESS ) return; // 成功
}
mStopIfError( 0xFF ); // CH375出错
}
//=================================================================================================
//=================================================================================================
// 数据同步
// USB的数据同步通过切换DATA0和DATA1实现: 在设备端, USB设备可以自动切换;
// 在主机端, 必须由SET_ENDP6和SET_ENDP7命令控制CH375切换DATA0与DATA1.
// 主机端的程序处理方法是为设备端的各个端点分别提供一个全局变量,
// 初始值均为DATA0, 每执行一次成功事务后取反, 每执行一次失败事务后将其复位为DATA1
// (初始值均为80H, 每执行一次成功事务后将位6取反, 每执行一次失败事务后将其复位为80H.)
//=================================================================================================
//=================================================================================================
//
//-------------------------------------------------------------------------------------------------
// 主机接收成功后,切换DATA0和DATA1实现数据同步
void CH375_ToggleReceive( void )
{
xWriteCH375Cmd( CMD_SET_ENDP6 );
xWriteCH375Data( Endp6Mode );
Endp6Mode ^= 0x40; // 位7为1则位6为同步触发位, 否则同步触发位不变
mDelayuS( 2 );
}
//-------------------------------------------------------------------------------------------------
// 主机发送成功后,切换DATA0和DATA1实现数据同步
void CH375_ToggleSend( void )
{
xWriteCH375Cmd( CMD_SET_ENDP7 );
xWriteCH375Data( Endp7Mode );
Endp7Mode ^= 0x40; // 位7为1则位6为同步触发位, 否则同步触发位不变
mDelayuS( 2 );
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
// 主机接收失败后,复位设备端的数据同步到DATA0
unsigned char CH375_ClrStall6( void )
{
xWriteCH375Cmd( CMD_CLR_STALL );
// xWriteCH375Data( 2 | 0x80 ); // 对于IN端点,有效地址是81H~8FH
xWriteCH375Data( EndpOutAddr | 0x80 );// 如果设备端不是CH37X芯片,那么需要修改端点号
Endp6Mode = 0x80;
return( xQueryInterrupt( ) );
}
//-------------------------------------------------------------------------------------------------
// 主机发送失败后,复位设备端的数据同步到DATA0
unsigned char CH375_ClrStall7( void )
{
xWriteCH375Cmd( CMD_CLR_STALL );
// xWriteCH375Data( 2 ); // 对于OUT端点,有效地址是01H~0FH
xWriteCH375Data( EndpOutAddr ); // 如果设备端不是CH37X芯片,那么需要修改端点号
Endp7Mode = 0x80;
return( xQueryInterrupt( ) );
}
//-------------------------------------------------------------------------------------------------
// 数据读写, 单片机读写CH372或者CH375芯片中的数据缓冲区
//-------------------------------------------------------------------------------------------------
// 从CH37X读出数据块
unsigned char CH375_ReadUSBData( unsigned char *buffer )
{
unsigned char i, length;
xWriteCH375Cmd( CMD_RD_USB_DATA ); // 从CH375的端点缓冲区读取接收到的数据
i = xReadCH375Data( ); // 后续数据长度( 0--64B )
length = i;
while( i-- )
{
*buffer++ = xReadCH375Data( );
}
return( length );
}
//-------------------------------------------------------------------------------------------------
// 向CH37X写入数据块
void CH375_WriteUSBData( unsigned char length, unsigned char *buffer )
{
xWriteCH375Cmd( CMD_WR_USB_DATA7 ); // 向CH375的端点缓冲区写入准备发送的数据
xWriteCH375Data( length ); // 后续数据长度, length不能大于64
while( length-- )
{
xWriteCH375Data( *buffer++ );
}
}
//-------------------------------------------------------------------------------------------------
// 主机操作
//-------------------------------------------------------------------------------------------------
// 执行USB事务
unsigned char CH375_IssueToken( unsigned char EndpAndPID )
{
unsigned char status;
// 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功
xWriteCH375Cmd( CMD_ISSUE_TOKEN );
xWriteCH375Data( EndpAndPID ); // 高4位目的端点号, 低4位令牌PID
status = xQueryInterrupt( ); // 等待CH375操作完成
return( status );
}
//-----------------------------------------------
// 执行USB事务,适用于CH375A
unsigned char CH375_IssueToken_X( unsigned char EndpAndPID, unsigned char toggle )
{
unsigned char status;
// 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功
xWriteCH375Cmd( CMD_ISSUE_TOKEN_X );
xWriteCH375Data( toggle ); // 同步标志的位7为主机端点IN的同步触发位, 位6为主机端点OUT的同步触发位, 位5~位0必须为0
xWriteCH375Data( EndpAndPID ); // 高4位目的端点号, 低4位令牌PID
status = xQueryInterrupt( ); // 等待CH375操作完成
return( status );
}
//=================================================================================================
//=================================================================================================
// 主机端发送、接收数据子程序
//=================================================================================================
//=================================================================================================
//
//-------------------------------------------------------------------------------------------------
// 主机发送
void CH375_HostSend( unsigned char length, unsigned char *buffer )
{
unsigned char status;
unsigned char len;
while( length ) // 连续输出数据块给USB设备
{
if( length > EndpOutSize ) len = EndpOutSize; // 单次发送不能超过端点尺寸
else len = length;
CH375_WriteUSBData( len, buffer );// 将数据先复制到CH375芯片中
CH375_ToggleSend( ); // 数据同步
// status = CH375_IssueToken( ( 2 << 4 ) | DEF_USB_PID_OUT ); // 请求CH375输出数据
status = CH375_IssueToken( ( EndpOutAddr << 4 ) | DEF_USB_PID_OUT ); // 请求CH375输出数据
// CH375成功发出数据
if( status == USB_INT_SUCCESS )
{
length -= len; // 计数
buffer += len; // 操作成功
}
// CH375发出数据错误
else
{
CH375_ClrStall7( ); // 清除设备的数据接收端点
}
}
}
//-------------------------------------------------------------------------------------------------
// 主机接收, 返回长度
unsigned char CH375_HostReceive( unsigned char *buffer )
{
unsigned char status;
if( EndpInAddr ) // 支持双向接口
{
CH375_ToggleReceive( ); // 设置主机接收的同步标志
// status = CH375_IssueToken( ( 2 << 4 ) | DEF_USB_PID_IN );
status = CH375_IssueToken( ( EndpInAddr << 4 ) | DEF_USB_PID_IN );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -