日志档案

发表于 2007-8-28 18:50:39

1

标签: USB  单片机  固件  

USB-固件程序详细注解(二)

看到头都大了,虽然不是全都明白,但起码走了一遍程序,附上我读完主程序涉及的所有注释.直接一句句往下读就行了,函数都在程序的后面的,找不到就用查找功能找一下.

void main(void)
{
 unsigned short ID;
 unsigned char high,low;
 init_port();
 init_special_interrupts(); 
 init_flags(); 
 ID=D12_ReadChipID();
 high=(unsigned char)(ID>>8);
 low=(unsigned char)ID;
 reconnect_USB();
 while( TRUE )
 { 
  if (bEPPflags.bits.bus_reset)         //总线复位处理
  {
   DISABLE;
   bEPPflags.bits.bus_reset = 0; //清总线复位标志
   ENABLE;
//   D12SUSPD = 1;                 //释放 PDIUSBD12 挂起控制
  }
/*  if (bEPPflags.bits.suspend)           //挂起改变处理
  {
   DISABLE;
   bEPPflags.bits.suspend= 0;    //清除挂起改变标志
   ENABLE;
   if(D12SUSPD == 1)             //进入挂起处理
   {
    D12SUSPD = 0;         //唤醒 PDIUSBD12,使得USB器件在
                                                      //MCU进入低功耗模式后再进入挂起
    P0 = 0xFF;           
    P1 = 0xFF;
    P2 = 0xFF;
    P3 = 0xFF;
    D12SUSPD = 1;        //释放挂起控制
    PCON |= 0x02;        //进入掉电模式
    while (1);           //芯片进入死循环,因为标志51进入掉电
   }                            //后,只有复位才可以唤醒芯片
  } // if suspend change*/

  if (bEPPflags.bits.setup_packet)    //Setup 包处理
  {
   DISABLE;
   bEPPflags.bits.setup_packet = 0;
   ENABLE;
   control_handler();          //调用请求处理子程序
//   D12SUSPD = 1;               //释放挂起控制
  } // if setup_packet
     if(bEPPflags.bits.configuration)    
   IspControl();
 } // Main Loop

}

void init_port()
{
 P0 = 0xFF;
 P1 = 0xFF;
 P2 = 0xFF;
 P3 = 0xFF;
// D12SUSPD = 0;
}

void init_special_interrupts(void)
{
 EA=1;
 IT1=0;
 EX1=1;
 PX1=1;
}

void init_flags()
{
 bEPPflags.bits.bus_reset=0;          
 bEPPflags.bits.suspend=0;            
 bEPPflags.bits.setup_packet=0;    
 bEPPflags.bits.remote_wakeup=0;  
 bEPPflags.bits.in_isr=0;       
 bEPPflags.bits.control_state=0;  
 bEPPflags.bits.configuration=0;  
 bEPPflags.bits.ep1_rxdone=0;
 bEPPflags.bits.main_rxdone=0; 
}

/*
   //*************************************************************************
   // structure and union definitions
   //*************************************************************************
*/
typedef union _epp_flags
{
 struct _flags
 {
//  unsigned char timer          : 1; //时间溢出
  unsigned char bus_reset      : 1; //总线复位标志
  unsigned char suspend        : 1; //挂起改变标志
  unsigned char setup_packet   : 1; //收到 setup 包
  unsigned char remote_wakeup  : 1; //远程唤醒标志(未使用)
  unsigned char in_isr      : 1; //USB中断标志
  unsigned char control_state  : 2; //控制端点处理状态
                                                  //0:  空闲
                                                  //1:  数据发送
                                                  //2:  数据接收

  unsigned char configuration  : 1; //配置标志(0:未配置;1:已经配置)
//  unsigned char verbose      : 1;
  unsigned char ep1_rxdone     : 1; //端点1收到数据标志
  unsigned char main_rxdone    : 1; //主端点收到数据标志
  unsigned char setup_dma      : 2; // V2.3
//  unsigned char dma_state      : 2;
//  unsigned char power_down     : 1; // Smart Board
 } bits;
 unsigned short value;
} EPPFLAGS;

unsigned short D12_ReadChipID(void)
{
 unsigned short i,j;
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, 0xFD);      // #define D12_COMMAND 0x03
 i=inportb(D12_DATA);              // #define D12_DATA 0x02
 j=inportb(D12_DATA);      
 i += (j<<8);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
 return i;
}

//向PDIUSBD12发送数据或命令的子程序
void outportb(unsigned char port,unsigned char val)
{
 unsigned char xdata *ext_address;
 MCU_D12CS=0;                      //片选信号,低有效
 ext_address=0xff00 + port;
 *ext_address = val;
 MCU_D12CS=1;
}

//从PDIUSBD12读取数据
unsigned char inportb(unsigned char port)
{
 unsigned char c;
 unsigned char xdata *ext_address;
 MCU_D12CS=0;
 ext_address=0xff00 + port;
 c = *ext_address ;
 MCU_D12CS=1;
 return c;
}

void reconnect_USB(void)
{
// D12SUSPD = 0;                    //唤醒 PDIUSBD12
 disconnect_USB();                //断开芯片与USB总线连接
 connect_USB();
}

void disconnect_USB(void)
{
 // 初始化 PDIUSBD12 工作状态(断开 Soft Connet 上拉电阻)
 D12_SetMode(D12_NOLAZYCLOCK, D12_SETTOONE | D12_CLOCK_12M);   //#define D12_NOLAZYCLOCK 0x02
}                                                                     //#define D12_SETTOONE    0x40
                                                                      //#define D12_CLOCK_12M 0x03
/*设置模式命令:F3H*/
void D12_SetMode(unsigned char bConfig, unsigned char bClkDiv)
{
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, 0xF3);
 outportb(D12_DATA, bConfig);
 outportb(D12_DATA, bClkDiv);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
}

void connect_USB(void)
{
 D12_SetDMA(D12_ENDP4INTENABLE | D12_ENDP5INTENABLE);       //#define D12_ENDP4INTENABLE 0x40
                                                                   //#define D12_ENDP5INTENABLE 0x80
 D12_SetMode(D12_NOLAZYCLOCK|D12_SOFTCONNECT, D12_SETTOONE | D12_CLOCK_12M);
                                                                   //#define D12_SOFTCONNECT 0x10
}

/*设置DMA命令:FBH*/
void D12_SetDMA(unsigned char bMode)
{
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, 0xFB);
 outportb(D12_DATA, bMode);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
}


 while( TRUE )
 { 
  if (bEPPflags.bits.bus_reset)         //总线复位处理
  {
   DISABLE;
   bEPPflags.bits.bus_reset = 0; //清总线复位标志
   ENABLE;
//   D12SUSPD = 1;                 //释放 PDIUSBD12 挂起控制
  }
/*  if (bEPPflags.bits.suspend)           //挂起改变处理
  {
   DISABLE;
   bEPPflags.bits.suspend= 0;    //清除挂起改变标志
   ENABLE;
   if(D12SUSPD == 1)             //进入挂起处理
   {
    D12SUSPD = 0;         //唤醒 PDIUSBD12,使得USB器件在
                                                      //MCU进入低功耗模式后再进入挂起
    P0 = 0xFF;           
    P1 = 0xFF;
    P2 = 0xFF;
    P3 = 0xFF;
    D12SUSPD = 1;        //释放挂起控制
    PCON |= 0x02;        //进入掉电模式
    while (1);           //芯片进入死循环,因为标志51进入掉电
   }                            //后,只有复位才可以唤醒芯片
  } // if suspend change*/

  if (bEPPflags.bits.setup_packet)    //Setup 包处理
  {
   DISABLE;
   bEPPflags.bits.setup_packet = 0;
   ENABLE;
   control_handler();          //调用请求处理子程序
//   D12SUSPD = 1;               //释放挂起控制
  } // if setup_packet
     if(bEPPflags.bits.configuration)    
   IspControl();
 } // Main Loop

}

void control_handler()
{
 unsigned char type, req;                 
        //读取请求类型,保留bit5和bit6
        //#define USB_REQUEST_TYPE_MASK    (unsigned char)0x60
        //#define USB_REQUEST_MASK         (unsigned char)0x0F
 type = ControlData.DeviceRequest.bmRequestType & USB_REQUEST_TYPE_MASK;
        ////读取请求代码,保留低4位
 req = ControlData.DeviceRequest.bRequest & USB_REQUEST_MASK;  
 if (type == USB_STANDARD_REQUEST)          //标准请求处理
  (*StandardDeviceRequest[req])();
 else
  stall_ep0();                       //无效请求,返回STALL
}

//USB设备请求寄存器
typedef struct _device_request
{
 unsigned char bmRequestType;              //请求类型(数据传输方向,类型,接收器)
 unsigned char bRequest;                   //USB请求
 unsigned short wValue;                    //USB请求值
 unsigned short wIndex;                    //USB请求索引
 unsigned short wLength;                   //计数长度 
} DEVICE_REQUEST;

extern CONTROL_XFER ControlData;

#define MAX_CONTROLDATA_SIZE 8

//Setup 包数据缓冲区
typedef struct _control_xfer
{
 DEVICE_REQUEST DeviceRequest;            //USB设备请求结构体,8个字节
 unsigned short wLength;                  //传输数据的总字节数
 unsigned short wCount;                   //传输字节数统计
 unsigned char * pData;                   //传输数据的指针
 unsigned char dataBuffer[MAX_CONTROLDATA_SIZE]; //请求的数据
} CONTROL_XFER;

/************************************************************
USB标准设备请求子程序入口地址表
************************************************************/

//USB标准设备请求入口地址指针表
code void (*StandardDeviceRequest[])(void) =
{
 get_status,
 clear_feature,
 reserved,
 set_feature,
 reserved,
 set_address,
 get_descriptor,
 reserved,
 get_configuration,
 set_configuration,
 get_interface,
 set_interface,
 reserved,
 reserved,
 reserved,
 reserved
};


#define NUM_ENDPOINTS 4

#define CONFIG_DESCRIPTOR_LENGTH    sizeof(USB_CONFIGURATION_DESCRIPTOR) \
     + sizeof(USB_INTERFACE_DESCRIPTOR) \
     + (NUM_ENDPOINTS * sizeof(USB_ENDPOINT_DESCRIPTOR))

extern CONTROL_XFER ControlData;
//extern IO_REQUEST idata ioRequest;
extern EPPFLAGS bEPPflags;
/*
USB 标准请求程序调用到的子程序
*/

//保留子程序
void reserved(void)
{
 stall_ep0();
}

void stall_ep0(void)
{
 D12_SetEndpointStatus(0, 1);
 D12_SetEndpointStatus(1, 1);
}

/*设置端点状态命令:40~45H*/
void D12_SetEndpointStatus(unsigned char bEndp, unsigned char bStalled)
{
 if(bEPPflags.bits.in_isr == 0)  //USB 中断服务标志
  DISABLE;
 outportb(D12_COMMAND, 0x40 + bEndp);
 outportb(D12_DATA, bStalled);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
}

/*
   //*************************************************************************
   // USB设备标准请求服务程序
   //*************************************************************************
*/
//获取状态
void get_status(void)
{
 unsigned char endp, txdat[2];
 unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
 unsigned char c;
 if (bRecipient == USB_RECIPIENT_DEVICE) {         //返回设备状态
  if(bEPPflags.bits.remote_wakeup == 1)
   txdat[0] = 3;                     //支持远程唤醒,自供电
  else
   txdat[0] = 1;
  txdat[1]=0;
  single_transmit(txdat, 2);               //发送数据
 } else if (bRecipient == USB_RECIPIENT_INTERFACE) {  //返回接口状态
  txdat[0]=0;
  txdat[1]=0;
  single_transmit(txdat, 2);
 } else if (bRecipient == USB_RECIPIENT_ENDPOINT) {  //返回端点状态
               //#define MAX_ENDPOINTS      (unsigned char)0x3
  endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
               //#define USB_ENDPOINT_DIRECTION_MASK      0x80
  if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
   c = D12_SelectEndpoint(endp*2 + 1); /* 读取输入端点状态 */
  else
   c = D12_SelectEndpoint(endp*2); /* 读取输出端点状态 */
  if(c & D12_STALL)
   txdat[0] = 1;                  //端点禁止
  else
   txdat[0] = 0;                 //端点有效
  txdat[1] = 0;
  single_transmit(txdat, 2);
 } else
  stall_ep0();                         //非标准请求,发STALL
}

void single_transmit(unsigned char * buf, unsigned char len)
{
 if( len <= EP0_PACKET_SIZE) {  //#define EP0_PACKET_SIZE    16
  D12_WriteEndpoint(1, len, buf);
 }
}

/*选择端点命令:00~05H*/
unsigned char D12_SelectEndpoint(unsigned char bEndp)
{
 unsigned char c;
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, bEndp);
 c = inportb(D12_DATA);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
 return c;
}

/*写端点缓冲区同时使缓冲区有效,包含写缓冲区命令:F0H*/
/*以及使缓冲区有效命令:FAH*/
unsigned char D12_WriteEndpoint(unsigned char endp, unsigned char len,unsigned char * buf)
{
 unsigned char i;
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, endp);
 inportb(D12_DATA);
 outportb(D12_COMMAND, 0xF0);
 outportb(D12_DATA, 0);
 outportb(D12_DATA, len);
 for(i=0; i<len; i++)
  outportb(D12_DATA, *(buf+i));
 outportb(D12_COMMAND, 0xFA);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
 return len;
}

//清除特性
void clear_feature(void)
{
 unsigned char endp;
        //读取请求类型中的接收方
 unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
 if (bRecipient == USB_RECIPIENT_DEVICE
  && ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) {
                //清除远程唤醒特性
  DISABLE;
  bEPPflags.bits.remote_wakeup = 0;
  ENABLE;
  single_transmit(0, 0);   //返回应答
 }
 else if (bRecipient == USB_RECIPIENT_ENDPOINT
  && ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) {
                //清除端点禁止特性,恢复其使用
  endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
  if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
   /* 清除输入端点STALL特性 */
   D12_SetEndpointStatus(endp*2 + 1, 0);
  else
   /* 清除输出端点STALL特性*/
   D12_SetEndpointStatus(endp*2, 0);
  single_transmit(0, 0);   //发送响应
 } else
  stall_ep0();             //没有该要求
}

/*设置端点状态命令:40~45H*/
void D12_SetEndpointStatus(unsigned char bEndp, unsigned char bStalled)
{
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, 0x40 + bEndp);
 outportb(D12_DATA, bStalled);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
}

//设置特性
void set_feature(void)
{
 unsigned char endp;
        //读取请求类型中的接收方
 unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
 if (bRecipient == USB_RECIPIENT_DEVICE
  && ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) {
                //设置远程唤醒特性
  DISABLE;
  bEPPflags.bits.remote_wakeup = 1;
  ENABLE;
  single_transmit(0, 0);     //发送响应
 }
 else if (bRecipient == USB_RECIPIENT_ENDPOINT
  && ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) {
  endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
  if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
   /* 设置输入端点禁止 */
   D12_SetEndpointStatus(endp*2 + 1, 1);
  else
   /* 设置输出端点禁止 */
   D12_SetEndpointStatus(endp*2, 1);
  single_transmit(0, 0);
 } else
  stall_ep0();
}

//设置地址
void set_address(void)
{
 D12_SetAddressEnable((unsigned char)(ControlData.DeviceRequest.wValue &
  DEVICE_ADDRESS_MASK), 1);
        //#define DEVICE_ADDRESS_MASK      0x7F
 single_transmit(0, 0);
}

/*设置/使能地址命令:D0H*/
void D12_SetAddressEnable(unsigned char bAddress, unsigned char bEnable)
{
    if(bEPPflags.bits.in_isr == 0)
         DISABLE;//EA=0
    outportb(D12_COMMAND, 0xD0);
 if(bEnable)
  bAddress |= 0x80;
 outportb(D12_DATA, bAddress);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;//EA=1
}

//获取描述符
void get_descriptor(void)
{       //读取请求的描述符类型
        //#define MSB(x)    (((x) >> 8) & 0xFF)
 unsigned char bDescriptor = MSB(ControlData.DeviceRequest.wValue);
 if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE) {
        //获取设备描述符
  code_transmit((unsigned char code *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR));
 } else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE) {
        //获取配置描述符+配置描述符+接口描述符+端点描述符
  code_transmit((unsigned char code *)&ConfigDescr, CONFIG_DESCRIPTOR_LENGTH);
 } else
  stall_ep0();
}

void code_transmit(unsigned char code * pRomData, unsigned short len)
{
 ControlData.wCount = 0;
 if(ControlData.wLength > len)
  ControlData.wLength = len;

 ControlData.pData = pRomData;
 if( ControlData.wLength >= EP0_PACKET_SIZE) {
  D12_WriteEndpoint(1, EP0_PACKET_SIZE, ControlData.pData);
  ControlData.wCount += EP0_PACKET_SIZE;

  DISABLE;
  bEPPflags.bits.control_state = USB_TRANSMIT;
  ENABLE;
 }
 else {
  D12_WriteEndpoint(1, ControlData.wLength, pRomData);
  ControlData.wCount += ControlData.wLength;
  DISABLE;
  bEPPflags.bits.control_state = USB_IDLE;
  ENABLE;
 }
}

//获取配置
void get_configuration(void)
{
 unsigned char c = bEPPflags.bits.configuration;
 single_transmit(&c, 1);      //返回配置值
}

void single_transmit(unsigned char * buf, unsigned char len)
{
 if( len <= EP0_PACKET_SIZE) {
  D12_WriteEndpoint(1, len, buf);
 }
}


void set_configuration(void)
{

 if (ControlData.DeviceRequest.wValue == 0) {
  /* 配置值不对,设备进入未配置状态 */
  single_transmit(0, 0);                 //发送响应
  DISABLE;
  bEPPflags.bits.configuration = 0;      //标志未配置
  ENABLE;
  init_unconfig();                       //进入地址状态,禁止0 除外的所有端点
 } else if (ControlData.DeviceRequest.wValue == 1) {
  /* 配置设备 */
  single_transmit(0, 0);

  init_unconfig();
  init_config();                        //配置处理,允许端点收发
  
  DISABLE;
  bEPPflags.bits.configuration = 1;     //标志已配置
  ENABLE;
 } else
  stall_ep0();                         //没有该请求,返回STALL
}

void init_unconfig(void)
{
// unsigned char i;

 D12_SetEndpointEnable(0); /* Disable all endpoints but EPP0. */
}

/*设置端点使能命令:D8H*/
void D12_SetEndpointEnable(unsigned char bEnable)
{
 if(bEPPflags.bits.in_isr == 0)
  DISABLE;
 outportb(D12_COMMAND, 0xD8);
 if(bEnable)
  outportb(D12_DATA, 1);
 else
  outportb(D12_DATA, 0);
 if(bEPPflags.bits.in_isr == 0)
  ENABLE;
}

void init_config(void)
{
 D12_SetEndpointEnable(1); /* Enable  generic/iso endpoints. */
}

//获取接口信息
void get_interface(void)
{
 unsigned char txdat = 0;        /* 本设备只有一个接口 */
 single_transmit(&txdat, 1);
}

//设置接口
void set_interface(void)
{
 if (ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0)
  single_transmit(0, 0);       //发送响应
 else
  stall_ep0();
}

void IspControl(void)
{
 P1=GenEpBuf[0];
}

unsigned char idata GenEpBuf[EP1_PACKET_SIZE]={0,0,0,0};
#define EP1_PACKET_SIZE    4

 

系统分类: 单片机   |   用户分类: USB接口技术   |   来源: 原创   |   【推荐给朋友】

    阅读(1099)    回复(0)  

投一票您将和博主都有获奖机会!