首页 > 其他 > 详细

USB的“Virtual_COM_Port”例程代码详细分析--初始化分析

时间:2021-03-28 17:45:21      阅读:26      评论:0      收藏:0      [点我收藏+]

一.初始化

USB进行枚举前的初始化流程图

 技术分享图片

  1. main()开始

 

int main(void)
{
  Set_System();//初始化时钟系统、使能相关的外围设备电源;
  Set_USBClock();//配置和使能USB时钟
  USB_Interrupts_Config();//主要功能是配置USB所用到的中断;USB低优先级中断和唤醒中断
  USB_Init();//USB系统初始化
  
  while (1)
  {
  }
}

 

技术分享图片

 

 

 

  1. 开始USB系统初始化USB_Init()

 

void USB_Init(void)
{
    /*
    初始化三个全局指针,指向DEVICE_INFO、USER_STANDARD_REQUESTS 和 DEVICE_PROP结构体。
后面两个是函数指针结构体,里面都是USB请求实现、功能实现的函数指针。
    */
  pInformation = &Device_Info;            //USB设备信息
  pInformation->ControlState = 2;         //设置控制状态为IN_DATA
  pProperty = &Device_Property;            //设备本身支持的属性和方法
  pUser_Standard_Requests = &User_Standard_Requests; //初始化主机标准请求
  /* Initialize devices one by one */
  pProperty->Init();                       //初始化
    /*
调用pProperty->Init()(实质上是执行Virtual_Com_Port_init()函数)完成设备的初始化。
上层函数调用下层函数是常规操作。而下层函数调用上层文件函数称之为回调。
回调函数的意义在于给同一种操作模式,提供不同的回调函数即可实现不同的功能。
 回调函数的实现方法是函数指针数组,这是指针的高级应用。
    */
}

 

2.1 USB设备信息DEVICE_INFO

 

//USB内核将主机发送过来的用于实现USB设备的设置包保存在设备信息结构表中
typedef struct _DEVICE_INFO
{
  uint8_t USBbmRequestType;       /* bmRequestType */
  uint8_t USBbRequest;            /* bRequest */
  uint16_t_uint8_t USBwValues;         /* wValue */
  uint16_t_uint8_t USBwIndexs;         /* wIndex */
  uint16_t_uint8_t USBwLengths;        /* wLength */

  uint8_t ControlState;            /* 控制状态 */
  uint8_t Current_Feature;         /* 当前功能 */
  uint8_t Current_Configuration;   /* 当前篇日志 */
  uint8_t Current_Interface;       /* 选择当前配置接口 */
  uint8_t Current_AlternateSetting;/* 选择当前接口备选设置 */

  ENDPOINT_INFO Ctrl_Info;
}DEVICE_INFO;

 

2.2 USB控制状态

 

typedef enum _CONTROL_STATE
{
  WAIT_SETUP,       /* 0 */
  SETTING_UP,       /* 1 */
  IN_DATA,          /* 2 */
  OUT_DATA,         /* 3 */
  LAST_IN_DATA,     /* 4 */
  LAST_OUT_DATA,    /* 5 */
  WAIT_STATUS_IN,   /* 7 */
  WAIT_STATUS_OUT,  /* 8 */
  STALLED,          /* 9 */
  PAUSE             /* 10 */
} CONTROL_STATE;    /* The state machine states of a control pipe*/

 

2.3 USB功能实现Device_Property

 

DEVICE_PROP Device_Property =
  {
    Virtual_Com_Port_init,
    Virtual_Com_Port_Reset,
    Virtual_Com_Port_Status_In,
    Virtual_Com_Port_Status_Out,
    Virtual_Com_Port_Data_Setup,
    Virtual_Com_Port_NoData_Setup,
    Virtual_Com_Port_Get_Interface_Setting,
    Virtual_Com_Port_GetDeviceDescriptor,
    Virtual_Com_Port_GetConfigDescriptor,
    Virtual_Com_Port_GetStringDescriptor,
    0,
    0x40 /*MAX PACKET SIZE*/
  };

 

2.4 USB标准请求USER_STANDARD_REQUESTS

 

//标准请求的处理函数,非USB寄存器的操作,而是用户自己设定的寄存器操作  好像都是设置当前的设备状态
USER_STANDARD_REQUESTS User_Standard_Requests =
  {
    Virtual_Com_Port_GetConfiguration,//获得配置
    Virtual_Com_Port_SetConfiguration,//设置配置
    Virtual_Com_Port_GetInterface,//获得接口
    Virtual_Com_Port_SetInterface,//设置接口
    Virtual_Com_Port_GetStatus,//得到状态
    Virtual_Com_Port_ClearFeature,//清除特性
    Virtual_Com_Port_SetEndPointFeature,//设置端点特性
    Virtual_Com_Port_SetDeviceFeature,//设置设备特性  
    Virtual_Com_Port_SetDeviceAddress//设置设备地址
  };
  1. 设备的初始化Virtual_Com_Port_init()

 

void Virtual_Com_Port_init(void)
{

  Get_SerialNum();//获取设备序列号

  pInformation->Current_Configuration = 0;//使当前配置为0,说明还没进行枚举。

  PowerOn();//将USB上电 连接设备

    //主要是CNTR寄存器的初始化 开启所有必须处理的中断(除DMA溢出中断)
  USB_SIL_Init();

  USART_Config_Default();//将USART配置为默认设置
    
  bDeviceState = UNCONNECTED;  //设备状态标志 当前状态未连接
}

 

3.1获取设备序列号Get_SerialNum()

 

void Get_SerialNum(void)
{//获取设备版本号,将其存入到版本号字符串。
  uint32_t Device_Serial0, Device_Serial1, Device_Serial2;

  Device_Serial0 = *(uint32_t*)ID1;
  Device_Serial1 = *(uint32_t*)ID2;
  Device_Serial2 = *(uint32_t*)ID3;  

  Device_Serial0 += Device_Serial2;

  if (Device_Serial0 != 0)
  {
    IntToUnicode (Device_Serial0, &Virtual_Com_Port_StringSerial[2] , 8);
    IntToUnicode (Device_Serial1, &Virtual_Com_Port_StringSerial[18], 4);
  }
}

 

3.2 USB上电PowerOn()

 

RESULT PowerOn(void)
{
  uint16_t wRegVal;
 /**
在PowerOn函数使能了复位中断以后,将进入到USB的复位中断里面去。
然后再执行函数USB_SIL_Init 将所有的USB中断都打开。
这个函数首先把D+的上拉电阻上电;这样电脑就可以检测到设备了。
  */ 
#if !defined (USE_NUCLEO)
  /*** cable plugged-in ? ***/
  USB_Cable_Config(ENABLE);    //上电连接,实质上就是将USB控制线置为低电平,便于主机检测
#endif

  /*** CNTR_PWDN = 0 ***/   //USB 收发器内部参照电压
//这句话虽然将强制复位USB模块,但由于复位中断允许位没有使能,不会引起复位中断
  wRegVal = CNTR_FRES;   //强制复位
  _SetCNTR(wRegVal);

  /* The following sequence is recommended:建议遵循以下顺序
    1- FRES = 0
    2- Wait until RESET flag = 1 (polling)
    3- clear ISTR register */

  /*** CNTR_FRES = 0 ***///清除复位信号
  wInterrupt_Mask = 0;
  
  _SetCNTR(wInterrupt_Mask); 
  
  /* Wait until RESET flag = 1 (polling) */
    //等待复位标志置一
  while((_GetISTR()&ISTR_RESET) == 1);
  
  /*** Clear pending interrupts ***/
    //清除挂起标志
  SetISTR(0);
  
  /*** Set interrupt mask ***/
    //复位中断屏蔽位 挂起中断屏蔽位 唤醒中断屏蔽位使能 
  wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;
  _SetCNTR(wInterrupt_Mask);
  /*
     后面的一个语句执行后,复位中断已经被允许,而此时集线器多半已经开始复位端口了。或者说稍微有限
   延迟,设备固件还能继续初始化一些部件,但已经不会影响整个工作流程了。
   所以,接下来直接进入复位中断。
    */
  return USB_SUCCESS;
}

 

PowerOn函数使能了复位中断以后,将进入到USB的复位中断里面去。然后再执行函数USB_SIL_Init 将所有的USB中断都打开。

3.4 ISTR事件中断服务程序USB_Istr()

 

#if (IMR_MSK & ISTR_RESET)//初始化时第一次进入
    //USB复位请求中断
  if (wIstr & ISTR_RESET & wInterrupt_Mask)
  {
    _SetISTR((uint16_t)CLR_RESET); //清除复位中断标志
    Device_Property.Reset();       //进入到复位中断 
        //实际上是调用Virtual_Com_Port_Reset()函数进行处理

 

3.5 实现对端点的复位Virtual_Com_Port_Reset()

void Virtual_Com_Port_Reset(void)
{
  /* Set Virtual_Com_Port DEVICE as not configured 还没被配置*/
  pInformation->Current_Configuration = 0;   //当前配置为0

  /* Current Feature initialization */
  pInformation->Current_Feature = Virtual_Com_Port_ConfigDescriptor[7];  //需要总线供电

  /* Set Virtual_Com_Port DEVICE with the default Interface*/
  pInformation->Current_Interface = 0;  //当前接口为0

  SetBTABLE(BTABLE_ADDRESS);   //设置包缓冲区地址

技术分享图片

 

 

  /* Set this device to response on default address */
  SetDeviceAddress(0);       //设置设备地址默认为0
  bDeviceState = ATTACHED;   //设置当前状态为连接状态

 

复位中断执行完后,开发板的USB接口能够以默认的地址对主机来的数据包进行响应了。这个阶段的分析结束,下面正式分析代码实现的枚举过程。

 

3.6 CNTR寄存器的初始化USB_SIL_Init()

 

uint32_t USB_SIL_Init(void)
{  //USB中断初始化
  /* USB interrupts initialization */
  /* clear pending interrupts */
  _SetISTR(0);     //清除挂起标志
  wInterrupt_Mask = IMR_MSK;
  /* set interrupts mask */
    //开启所有必须处理的中断(除DMA溢出中断)
  _SetCNTR(wInterrupt_Mask);
  return 0;
}

 

3.7 串口初始化USART_Config_Default()

 

USB的“Virtual_COM_Port”例程代码详细分析--初始化分析

原文:https://www.cnblogs.com/wsx288/p/14588526.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!