Chinaunix首页 | 论坛 | 博客
  • 博客访问: 339139
  • 博文数量: 88
  • 博客积分: 1695
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-06 15:48
个人简介

喜欢美食, 旅行..

文章分类

全部博文(88)

文章存档

2014年(2)

2013年(12)

2012年(14)

2010年(8)

2009年(52)

我的朋友

分类: 嵌入式

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                 //51单片机头文件

#include "CH375INC.H"           //CH372/CH375头文件

 

///////////////////////////////////////////////

//说明: CH372总线地址,这个是按照学习笔记1总线扩展方式定的

//       采用别的方式,地址另外设定

///////////////////////////////////////////////

unsigned char volatile xdata CH375_CMD_PORT _at_ 0x03F1;          

unsigned char volatile xdata CH375_DAT_PORT _at_ 0x03F0;

 

/*********************延时程序********************/

///////////////////////////////////////////////

//函数: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/CH375INT#引脚可以连接到单片机的中断引脚,中断为低电平有效或者下降沿有效,如果不使用中断,那么也可以用查询方式,由单片机程序查询CH372/CH375INT#引脚为低电平 */

IT0 = 0;     /* 置外部信号为低电平触发 */

    IE0 = 0;     /* 清中断标志 */

    EX0 = 1;    /* 允许CH372中断,假定CH372INT#引脚连接到单片机的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 内部自动处理了其它中断状态。所以可以看到中断服务程序中对端点0SETUPOUTIN还有USB总线复位都不做处理。

 

 

 
阅读(4773) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~