喜欢美食, 旅行..
分类: 嵌入式
2009-10-31 11:24:17
USB学习笔记:CH372基本读写程序(51单片机)
CH372官网上已经给出了CH372的测试程序,下面是我在官方网站的测试程序的基础上进行整理和梳理。CH375支持USB-HOST主机方式和USB-DEVICE/SLAVE 设备方式。,而CH375从设备方式与CH372的功能程序是一样的,于是两者作为从机芯片是一样的。
CH372 内置了USB 通讯中的底层协议,具有省事的内置固件模式和灵活的外置固件模式。在内置固件模式下,CH372自动处理默认端点0 的所有事务,本地端单片机只要负责数据交换,所以单片机程序非常简洁。在外置固件模式下,由外部单片机根据需要自行处理各种USB 请求,从而可以实现符合各种USB 类规范的设备。为了简单起见,一般PC机与单片机通信使用内置固件模式,下面程序也是基于内置固件模式的。
#pragma NOAREGS //禁止编译器使用绝对寄存器寻址,一定要加上
#include
#include "CH375INC.H" //CH372/CH375头文件
///////////////////////////////////////////////
//说明: CH372总线地址,这个是按照学习笔记1总线扩展方式定的
// 采用别的方式,地址另外设定
///////////////////////////////////////////////
unsigned char volatile xdata CH375_CMD_PORT _at_ 0x
unsigned char volatile xdata CH375_DAT_PORT _at_ 0x
/*********************延时程序********************/
///////////////////////////////////////////////
//函数:delay2us
//说明:延时2us
//入口:无
//返回:无
///////////////////////////////////////////////
void delay2us( )
{
unsigned char i;
for ( i = 2; i != 0; i -- );
}
///////////////////////////////////////////////
//函数:delay50ms
//说明:延时50ms
//入口:无
//返回:无
///////////////////////////////////////////////
void Delay50ms( )
{
unsigned char i, j;
for ( i="200"; i!=0; i-- ) for ( j="250"; j!=0; j-- );
}
/*********************基本读写程序********************/
///////////////////////////////////////////////
//函数:CH375_WR_CMD_PORT
//说明:写USB命令
//入口:unsigned char cmd:待写入命令
//返回:无
///////////////////////////////////////////////
void CH375_WR_CMD_PORT( unsigned char cmd )
{
delay2us();
CH375_CMD_PORT=cmd;
delay2us();
}
///////////////////////////////////////////////
//函数:CH375_WR_DAT_PORT
//说明:写一字节USB数据
//入口:unsigned char dat:待写入一字节数据
//返回:无
///////////////////////////////////////////////
void CH375_WR_DAT_PORT( unsigned char dat )
{
CH375_DAT_PORT=dat;
}
///////////////////////////////////////////////
//函数:CH375_RD_DAT_PORT
//说明:读一字节USB数据
//入口:无
//返回:从CH372/CH375读一字节数据
///////////////////////////////////////////////
unsigned char CH375_RD_DAT_PORT( void )
{
return( CH375_DAT_PORT );
}
/*********************初始化和中断服务程序********************/
///////////////////////////////////////////////
//函数:CH375_Init
//说明:CH372/CH375初始化
//入口:无
//返回:无
///////////////////////////////////////////////
void CH375_Init( )
{
/* 设置USB工作模式, 必要操作 */
unsigned char i;
CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); //设置USB工作模式
CH375_WR_DAT_PORT( 2 ); //设置为内置固件模式
for ( i="100"; i!=0; i-- )
{ /* 等待操作成功,通常需要等待10uS-20uS */
if ( CH375_RD_DAT_PORT( ) == CMD_RET_SUCCESS ) break;
}
/* 下面启用USB中断,CH372/CH375的INT#引脚可以连接到单片机的中断引脚,中断为低电平有效或者下降沿有效,如果不使用中断,那么也可以用查询方式,由单片机程序查询CH372/CH375的INT#引脚为低电平 */
IT0 = 0; /* 置外部信号为低电平触发 */
IE0 = 0; /* 清中断标志 */
EX0 = 1; /* 允许CH372中断,假定CH372的INT#引脚连接到单片机的INT0 */
}
///////////////////////////////////////////////
//函数:mCh375Interrupt
//说明:CH372/CH375中断程序
//入口:无
//返回:无
///////////////////////////////////////////////
void mCh375Interrupt( ) interrupt 0 using 1
{
unsigned char i, length;
unsigned char data buffer[64];
unsigned char InterruptStatus;
CH375_WR_CMD_PORT( CMD_GET_STATUS ); //获取中断状态并取消中断请求
InterruptStatus = CH375_RD_DAT_PORT( ); //获取中断状态
//采用边沿触发的外部中断请求,CPU在相应中断后,自动清除中断标志
switch ( InterruptStatus )
{
case USB_INT_BUS_RESET1: //USB总线复位
{
break;
}
case USB_INT_BUS_RESET2: //USB总线复位
{
break;
}
case USB_INT_BUS_RESET3: //USB总线复位
{
break;
}
case USB_INT_BUS_RESET4: //USB总线复位
{
break;
}
case USB_INT_EP0_SETUP:
{ //端点0 的接收器接收到数据,SETUP 事务成功,内部固件模式时不需要处理
break;
}
case USB_INT_EP0_OUT:
{ //端点0 的接收器接收到数据,OUT 事务成功,内部固件模式时不需要处理
break;
}
case USB_INT_EP0_IN:
{ //端点0 的发送器发送完数据,IN 事务成功,内部固件模式时不需要处理
break;
}
case USB_INT_EP2_OUT: //批量端点/端点2接收到数据,OUT成功
{ //从当前USB中断的端点缓冲区读取数据块,并释放缓冲区
CH375_WR_CMD_PORT( CMD_RD_USB_DATA );
length = CH375_RD_DAT_PORT( ); /* 首先读取后续数据长度 */
for ( i = 0; i < length; i ++ ) buffer[ i ] = CH375_RD_DAT_PORT( ); //接收数据包
/* -----------测试数据正确性,将接收到的命令包数据返回给PC机----------- */
CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 );
/* 向USB端点2的发送缓冲区写入数据块 */
CH375_WR_DAT_PORT( length );
/* 首先写入后续数据长度,回传刚接收到的数据长度 */
for ( i = 0; i < length; i ++ ) CH375_WR_DAT_PORT( buffer[ i ] );
/* 数据返回,由计算机应用程序测试数据是否正确 */
/* ------------------------------------------------------------------------------------------------------ */
break;
}
case USB_INT_EP2_IN: //批量端点/端点2发送完数据,IN成功
{
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); //释放当前USB缓冲区
break;
}
default:
{
CH375_WR_CMD_PORT( CMD_UNLOCK_USB );
break;
}
}
}
///////////////////////////////////////////////
//函数:main
//说明:主程序。对CH372初始化,对USB进行读写及其他程序
//入口:无
//返回:无
///////////////////////////////////////////////
main( )
{
Delay50ms( );
CH375_Init( ); //对CH375/CH372初始化
EA = 1; //允许中断
while(1);
}
下面是中断状态的分析说明。在内置固件模式的USB设备方式下,单片机只需要处理表中标注为灰色的中断状态,CH372 内部自动处理了其它中断状态。所以可以看到中断服务程序中对端点0的SETUP、OUT和IN还有USB总线复位都不做处理。