📄 ch372.txt
字号:
CH375的slaver的程序(C51)
发表时间:2005-08-23 18:03:17 浏览人数:534 发布者:administrator
CH375做slaver的程序
/***************************************
** USB 1.1 Slaver for CH375 **
** 单片机用89C2051 **
****************************************/
#include <INTRINS.H>
#include "REG2051.H"
#include "CH375INC.H"
#define DELAY_START_value 1 /* 根据单片机的时钟选择延时初值 */
#define MY_USB_VENDOR_ID 0x4348 /* 厂商ID */
#define MY_USB_DEVICE_ID 0x5537 /* 设备ID */
unsigned char RECV_LEN; /* 刚接收到的数据的长度 */
unsigned char idata RECV_BUFFER[ CH375_MAX_DATA_LEN ]; /* 数据缓冲区,用于保存接收到的下传数据,长度为0到64字节 */
unsigned char idata *cmd_buf;
unsigned char idata *ret_buf;
typedef union _REQUEST_PACK{
unsigned char buffer[8];
struct{
unsigned char bmReuestType; //标准请求字
unsigned char bRequest; //请求代码
unsigned int wvalue; //特性选择高
unsigned int wIndx; //索引
unsigned int wLength; //数据长度
}r;
} mREQUEST_PACKET, *mpREQUEST_PACKET;
//设备描述符
unsigned char code DevDes[]={
0x12 //描述符大小
,0x01 //常数DEVICE
,0x10 //USB规范版本信息
,0x01
,0x00 //类别码,
,0x00 //子类别码
,0x37 //协议码
,0x08 //端点0的最大信息包大小
,0x48 //厂商ID
,0x43
,0x37 //产品ID
,0x55
,0x00 //设备版本信息
,0x01
,0x00 //索引值
,0x00
,0x00
,0x01 //可能配置的数目
,0x00 //无意义
,0x00
,0x00
,0x00
,0x00
,0x00
};
//配置描述符
unsigned char code ConDes[]={ //配置描述符
0x09 //描述符大小
,0x02 //常数CONFIG
,0x27 //此配置传回所有数据大小
,0x00 //
,0x01 //接口数
,0x01 //配置值
,0x00 //索引
,0x80 //电源设置
,0x40 //需要总线电源
//接口描述符
,0x09 //描述符大小
,0x04 //常数INTERFACE
,0x00 //识别码
,0x00 //代替数值
,0x03 //支持的端点数
,0x08 //类别码
,0x08 //子类别码
,0x37 //协议码
,0x00 //索引
//端点描述符
,0x07 //描述符大小
,0x05 //常数ENDPOINT
,0x82 //端点数目及方向
,0x02 //支持的传输类型
,0x40 //支持的最大信息包大小
,0x00
,0x00 //
,0x07
,0x05
,0x02
,0x02
,0x40
,0x00
,0x00
,0x07
,0x05
,0x81
,0x03
,0x08
,0x00
,0x01
,0x07
,0x05
,0x01
,0x02
,0x08
,0x00
,0x00
}; //配置描述符
unsigned char code LangDes[]={0x04,0x03,0x09,0x04}; //语言描述符
unsigned char code SerDes[]={0x12,0x03,'C',0,'H',0,'3',0,'7',0,'5',0,'U',0,'S',0,'B',0}; //字符串描述符
unsigned char mVarSetupRequest; // USB请求码
unsigned char mVarSetupLength; // 后续数据长度
unsigned char code * VarSetupDescr; // 描述符偏移地址
unsigned char VarUsbAddress ;
bit CH375FLAGERR; //错误清0
bit CH375CONFLAG; //配置标志
mREQUEST_PACKET request;
/*
Ch375与51等的连接
CH375 51
D0 P1.0
. .
. .
. .
D7 P1.7
A0 P3.7
RD P3.5
WR P3.4
CS 接地
INT P3.2(int0)
*/
#define CH375_DATA_PORT P1 /* CH375端口的I/O地址 */
sbit CH375_CMD_DAT = P3^7; /* CH375地址线输入A0,A0=1时写命令,A0=0时读写数据 */
sbit CH375_RD = P3^5; /* CH375读选通输入,低电平有效 */
sbit CH375_WR = P3^4; /* CH375写选通输入,低电平有效 */
sbit led = P3^3; /* 指示灯 */
sbit CH375_INT_WIRE = P3^2; /* CH375中断请求输出,低电平有效 */
void delay50ms(void);
void delay1s(void);
void flash_led(void);
void CH375_WR_CMD_PORT( unsigned char cmd );
void CH375_WR_DAT_PORT( unsigned char dat );
unsigned char CH375_RD_DAT_PORT(void);
void set_usb_mode( unsigned char mode );
void CH375_Init( void );
void ComInit(void);
void SendChar(unsigned char buff);
void mCh375Ep0Up(void);
void mCh375DesUp(void);
void delay50ms(void)
{
unsigned char i, j;
for( i=200; i!=0; i-- )
for( j=250; j!=0; j-- );
}
void delay1s(void)
{
unsigned char i,j,k;
for( i=10; i!=0; i-- )
for( j=200; j!=0; j-- )
for( k=250; k!=0; k-- );
}
void flash_led(void)
{
unsigned char i;
for( i=10;i>0;i-- )
{
led=!led;
delay1s();
}
}
/* 与CH372/CH375有关的基本I/O操作 */
/* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 */
void CH375_WR_CMD_PORT( unsigned char cmd )
{
_nop_();
_nop_();
CH375_CMD_DAT = 1; /* 命令 */
CH375_DATA_PORT = cmd;
CH375_RD = 1;
CH375_WR = 0;
_nop_();
_nop_();
CH375_WR = 1;
CH375_CMD_DAT = 0;
CH375_DATA_PORT = 0xFF;
}
/* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 */
void CH375_WR_DAT_PORT( unsigned char dat )
{
_nop_();
CH375_CMD_DAT = 0; /* 数据 */
CH375_DATA_PORT = dat;
CH375_RD = 1;
CH375_WR = 0;
_nop_();
CH375_WR = 1;
CH375_DATA_PORT = 0xFF;
}
/* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
unsigned char CH375_RD_DAT_PORT(void)
{
unsigned char rev_data;
CH375_DATA_PORT = 0xFF;
CH375_CMD_DAT = 0; /* 数据 */
CH375_WR = 1;
CH375_RD = 0;
_nop_();
rev_data = CH375_DATA_PORT;
CH375_RD = 1;
return( rev_data );
}
/* 设置CH37X的工作模式 */
void set_usb_mode( unsigned char mode )
{
unsigned char i;
unsigned char RD_Data;
CH375_WR_CMD_PORT( CMD_SET_USB_MODE );
CH375_WR_DAT_PORT( mode );
for( i=100; i!=0; i-- ) /* 等待设置模式操作完成,不超过30uS */
{
RD_Data=CH375_RD_DAT_PORT();
if( RD_Data == CMD_RET_SUCCESS )
return; /* 成功 */
}
while(1)
{
flash_led(); /* CH375出错 */
}
}
/* CH375初始化子程序 */
void CH375_Init( void )
{
unsigned char i, k;
unsigned char RD_Data;
CH375_DATA_PORT = 0xFF;
CH375_INT_WIRE = 1;
CH375_WR = 1;
CH375_RD = 1;
CH375_CMD_DAT = 0;
/* 测试CH375是否正常工作 */
for( k=100; k!=0; k-- )
{
CH375_WR_CMD_PORT( CMD_CHECK_EXIST ); /* 测试CH375是否正常工作 */
i = 0x5A;
CH375_WR_DAT_PORT( i ); /* 写入测试数据 */
i = ~i; /* 返回数据应该是测试数据取反 */
RD_Data = CH375_RD_DAT_PORT();
if ( RD_Data != i ) /* CH375不正常 */
{
for ( i=5; i!=0; i-- )
{
CH375_WR_CMD_PORT( CMD_RESET_ALL ); /* 多次重复发命令,执行硬件复位 */
}
delay50ms(); /* 延时50ms */
}
else
break;
}
if( k==0 )
{
while(1)
{
flash_led(); /* CH375出错 */
}
}
/*
#ifdef MY_USB_VENDOR_ID
#ifdef MY_USB_DEVICE_ID
// 设置外部自定义的USB设备VID和PID,可选操作,不执行该命令则使用默认的VID和PID,
// 如果设置使用自定义的ID,那么计算机端驱动程序INF安装文件中的"USB\VID_4348&PID_5537"需要进行类似修改
CH375_WR_CMD_PORT( CMD_SET_USB_ID ); // 设置外部自定义的USB设备VID和PID,可选操作
CH375_WR_DAT_PORT( (unsigned char)MY_USB_VENDOR_ID ); // 写入厂商ID的低字节
CH375_WR_DAT_PORT( (unsigned char)(MY_USB_VENDOR_ID>>8) ); // 写入厂商ID的高字节
CH375_WR_DAT_PORT( (unsigned char)MY_USB_DEVICE_ID ); // 写入设备ID的低字节
CH375_WR_DAT_PORT( (unsigned char)(MY_USB_DEVICE_ID>>8) ); // 写入设备ID的高字节
#endif
#endif
*/
/* 设置USB工作模式, 必要操作 */
// set_usb_mode( 1 ); //外部固件模式
set_usb_mode( 2 ); //内部固件模式
}
/* 串行口通讯子程序 */
/* 串行口初始化 */
void ComInit(void)
{
TMOD = 0x20; /*T1为方式2 */
TH1 = 0xFE; /*计数常数0xFE,波特率:14400 晶振:11.0592MHz */
TL1 = 0xFE;
PCON = PCON & 0x7f; /* SMOD=0 */
SCON = 0x50; /* 串行口工作在方式3 */
TR1 = 1;
}
/* 发送数据 */
void SendChar(unsigned char buff)
{
SBUF = buff;
while( !TI );
TI=0;
}
//端点0数据上传
void mCh375Ep0Up(void)
{
unsigned char i,len;
if( mVarSetupLength ) //长度不为0传输具体长度的数据
{
if( mVarSetupLength<=8 )
{
len=mVarSetupLength;
mVarSetupLength=0;
} //长度小于8则传输要求的长度
else
{
len=8;
mVarSetupLength-=8;
} //长度大于8则传输8个,切总长度减8
CH375_WR_CMD_PORT( CMD_WR_USB_DATA3 ); //发出写端点0的命令
CH375_WR_DAT_PORT( len ); //写入长度
for( i=0;i!=len;i++ )
CH375_WR_DAT_PORT( request.buffer ); //循环写入数据
}
else
{
CH375_WR_CMD_PORT( CMD_WR_USB_DATA3 ); //发出写端点0的命令
CH375_WR_DAT_PORT( 0 ); //上传0长度数据,这是一个状态阶段
}
}
//复制描述符以便上传
void mCh375DesUp(void)
{
unsigned char k;
for (k=0; k!=8; k++ )
{
request.buffer[k]=*VarSetupDescr; //依次复制8个描述符,
VarSetupDescr++;
}
}
/* CH375数据接收程序 */
void mCh375Interrupt(void)
{
unsigned char InterruptStatus;
unsigned char length, len;
CH375_WR_CMD_PORT(CMD_GET_STATUS); /* 获取中断状态并取消中断请求 */
InterruptStatus = CH375_RD_DAT_PORT(); /* 获取中断状态 */
RECV_LEN=0;
switch( InterruptStatus ) // 分析中断状态
{
case USB_INT_EP2_OUT: // 批量端点下传成功
CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 从当前USB中断的端点缓冲区读取数据块,并释放缓冲区 */
length = CH375_RD_DAT_PORT(); /* 首先读取后续数据长度 */
if ( length != 0 ) /* 如果长度为0则不处理 */
{
RECV_LEN = length; /* 命令包的数据长度 */
ret_buf = RECV_BUFFER; /* 接收缓冲区 */
while ( length -- )
{
*ret_buf = CH375_RD_DAT_PORT();
ret_buf++;
}
}
break;
case USB_INT_EP2_IN: //批量端点上传成功,未处理
break;
case USB_INT_EP1_IN: //中断端点上传成功,未处理
break;
case USB_INT_EP1_OUT: //中断端点下传成功,未处理
break;
case USB_INT_EP0_SETUP: //控制端点建立成功
CH375_WR_CMD_PORT( CMD_RD_USB_DATA );
length=CH375_RD_DAT_PORT();
for( len=0;len!=length;len++ )
request.buffer[len] = CH375_RD_DAT_PORT(); // 取出数据
if( length==0x08 )
{
mVarSetupLength=request.buffer[6]&0x7f; //控制传输数据长度最大设置为128
// if((c1=request.r.bmReuestType)&0x40 ) //厂商请求,未处理
// {}
// if((c1=request.r.bmReuestType)&0x20) //类请求,未处理
// {}
if( !(request.r.bmReuestType&0x60) ) //标准请求
{
mVarSetupRequest=request.r.bRequest; //暂存标准请求码
switch( request.r.bRequest ) // 分析标准请求
{
case DEF_USB_CLR_FEATURE: //清除特性
if((request.r.bmReuestType&0x1F)==0x02) //不是端点不支持
{
switch( request.buffer[4] )
{
case 0x82:
CH375_WR_CMD_PORT( CMD_SET_ENDP7 ); //清除端点2上传
CH375_WR_DAT_PORT( 0x8E ); //发命令清除端点
break;
case 0x02:
CH375_WR_CMD_PORT( CMD_SET_ENDP6 );
CH375_WR_DAT_PORT( 0x80 ); //清除端点2下传
break;
case 0x81:
CH375_WR_CMD_PORT( CMD_SET_ENDP5 ); //清除端点1上传
CH375_WR_DAT_PORT( 0x8E );
break;
case 0x01:
CH375_WR_CMD_PORT( CMD_SET_ENDP4 ); //清除端点1下传
CH375_WR_DAT_PORT( 0x80 );
break;
default:
break;
}
}
else
{
CH375FLAGERR=1; //不支持的清除特性,置错误标志
}
break;
case DEF_USB_GET_STATUS: //获得状态
request.buffer[0]=0;
request.buffer[1]=0; //上传状态
break;
case DEF_USB_SET_ADDRESS: //设置地址
VarUsbAddress=request.buffer[2]; //暂存USB主机发来的地址
break;
case DEF_USB_GET_DESCR: //获得描述符
if( request.buffer[3]==1 ) //设备描述符上传
VarSetupDescr=DevDes;
else
if( request.buffer[3]==2 ) //配置描述符上传
VarSetupDescr=ConDes;
else
if( request.buffer[3]==3 )
{
if( request.buffer[2]== 0 )
VarSetupDescr=LangDes;
else
VarSetupDescr=SerDes; //做字符串处理
}
mCh375DesUp(); //其余描述符不支持
break;
case DEF_USB_GET_CONFIG: //获得配置
request.buffer[0]=0; //没有配置则传0
if( CH375CONFLAG )
request.buffer[0]=1; //已经配置则传1;这是在描述符里规定的
break;
case DEF_USB_SET_CONFIG: //设置配置
CH375CONFLAG=0;
if( request.buffer[2] != 0 )
{
CH375CONFLAG=1; //设置配置标志
}
break;
case DEF_USB_GET_INTERF: //得到接口
request.buffer[0]=1; //上传接口数,本事例只支持一个接口
break;
default :
CH375FLAGERR=1; //不支持的标准请求
break;
}
}
}
else //不支持的控制传输,不是8字节的控制传输
{
CH375FLAGERR=1;
}
if( !CH375FLAGERR )
mCh375Ep0Up(); //没有错误/调用数据上传,长度为0上传为状态
else
{
CH375_WR_CMD_PORT( CMD_SET_ENDP3 ); //设置端点1为STALL,指示一个错误
CH375_WR_DAT_PORT( 0x0F );
flash_led();
}
break;
case USB_INT_EP0_IN: //控制端点上串成功
if( mVarSetupRequest==DEF_USB_GET_DESCR ) //描述符上传
{
mCh375DesUp();
mCh375Ep0Up();
}
else
if( mVarSetupRequest==DEF_USB_SET_ADDRESS ) //设置地址
{
CH375_WR_CMD_PORT( CMD_SET_USB_ADDR );
CH375_WR_DAT_PORT( VarUsbAddress ); //设置USB地址,设置下次事务的USB地址
}
break;
case USB_INT_EP0_OUT: //控制端点下传成功
CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); //发出读数据命令
length=CH375_RD_DAT_PORT();
if( length>0 ) //长度为0跳出
{
for( len=0;len!=length;len++ )
CH375_RD_DAT_PORT(); //取出下传数据
}
break;
default:
if( InterruptStatus&0x03 ) //总线复位
{
CH375FLAGERR=0; //错误清0
CH375CONFLAG=0; //配置清0
mVarSetupLength=0;
}
else
{ //命令不支持
flash_led();
}
break;
}
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); //释放缓冲区
led=0;
}
/*串行数据接收程序*/
void receive(void)
{
unsigned int count;
unsigned char buf;
RECV_LEN=0;
cmd_buf = RECV_BUFFER; /* 接收缓冲区 */
while( 1 )
{
RI=0;
*cmd_buf = SBUF;
cmd_buf++;
RECV_LEN++;
if( RECV_LEN == 64 )
{
while( 1 )
{
count=10000;
while( RI==0 )
{
count--;
if( count==0 )
return;
}
RI=0;
buf=SBUF;
}
}
count=10000;
while( RI==0 )
{
count--;
if( count==0 )
return;
}
}
}
void main(void)
{
unsigned char length;
delay1s(); /* 延时等待CH375初始化完成,如果单片机由CH375提供复位信号则不必延时 */
CH375_Init( ); /* 初始化CH375 */
ComInit();
led = 0;
while ( 1 )
{
if( RI==1 ) /* 从串口接收到的数据 */
{
led=1;
receive();
led=0;
/* 将从串口接收到的数据发送到USB设备 */
ret_buf = RECV_BUFFER; /* 接收缓冲区 */
length = RECV_LEN; /* 刚接收到的数据长度 */
if( length!=0 )
{
CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); /* 向USB端点2的发送缓冲区写入数据块 */
CH375_WR_DAT_PORT( length ); /* 首先写入后续数据长度 */
while( length-- )
{
CH375_WR_DAT_PORT( *ret_buf ); /* 数据 */
ret_buf++;
}
}
}
CH375_INT_WIRE=1;
if( CH375_INT_WIRE==0 ) /* 从USB设备接收到数据 */
{
mCh375Interrupt();
/* 将从USB设备接收到的数据发送到串口 */
ret_buf = RECV_BUFFER; /* 接收缓冲区 */
length = RECV_LEN; /* 刚接收到的数据长度 */
while( length-- )
{
SendChar( *ret_buf );
ret_buf++;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -