1. IO初始化

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //P12: USB DP, P11: USB DM
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

初始化USB Enable的IO口为输出脚

2. USB中断初始化

void usbIntInit(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    /* 2 bit for pre-emption priority, 2 bits for subpriority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    /* Enable the USB interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

/* Enable the USB Wake-up interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

实际USB有3个中断,分别为USB_HP_CAN1_TX_IRQn(USB高优先级中断)、USB_LP_CAN1_RX0_IRQn(USB低优先级中断)和USBWakeUp_IRQn(USB唤醒中断)。

USB_HP_CAN1_TX_IRQn仅由USB同步(Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,大部分的例子没有用到,先不考虑使用。

3. 设置USB频率

/* Select USBCLK source */
    RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
  
    /* Enable the USB clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);

4. 调用USB库的API函数USB_Init()

此时编译会有错误提示,undefined reference to `Device_Property'和undefined reference to `User_Standard_Requests'

Device_Property是一个结构,参考例程Custom_HID中建立一个空的结构。

DEVICE_PROP Device_Property =
{
    usbClassInit,
    usbClassReset,
    usbClassStatusIn,
    usbClassStatusOut,
    usbClassDataSetup,
    usbClassNoDataSetup,
    usbClassGetInterfaceSetting,
    usbClassGetDeviceDescriptor,
    usbClassGetConfigDescriptor,
    usbClassGetStringDescriptor,
    0,
    0x40 /*MAX PACKET SIZE*/
};

所有处理的函数都是空的,例如

void usbClassInit(void)
{
}

同样对User_Standard_Requests

USER_STANDARD_REQUESTS User_Standard_Requests =
{
    usbClassGetConfiguration,
    usbClassSetConfiguration,
    usbClassGetInterface,
    usbClassSetInterface,
    usbClassGetStatus,
    usbClassClearFeature,
    usbClassSetEndPointFeature,
    usbClassSetDeviceFeature,
    usbClassSetDeviceAddress
};

编译通过。

5. 在USB库的API函数USB_Init()中可以看到会调用Device_Property的usbClassInit。

参考例程JoyStickMouse中Joystick_init,看起来应该都是一样的处理,

void Joystick_init(void)
{
  /* Update the serial number string descriptor with the data from the unique ID*/
  Get_SerialNum();
    
  pInformation->Current_Configuration = 0;
  /* Connect the device */
  PowerOn();

/* Perform basic device initialization operations */
  USB_SIL_Init();

bDeviceState = UNCONNECTED;
}

第一步是根据MCU的96位ID生成唯一的Serial Number,然后PowerOn,PowerOn里面会控制USB_EN脚,USB_SIL_Init是初始化端点(EndPoint)的读写。

1. PowerOn是USB IP的上电复位过程。

RESULT PowerOn(void)
{
  uint16_t wRegVal;
  
  /*** cable plugged-in ? ***/
  USB_Cable_Config(ENABLE);

/*** CNTR_PWDN = 0 ***/
  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;
}

USB_CNTR是USB控制寄存器(),USB_ISTR是USB中断状态寄存器。

a) PDWN = 0, 退出断电模式;FRES = 1, 强制复位

wRegVal = CNTR_FRES;
  _SetCNTR(wRegVal);

wInterrupt_Mask = 0;
  _SetCNTR(wInterrupt_Mask);

b) 等待复位结束

while((_GetISTR()&ISTR_RESET) == 1);

c) 清除USB中断

SetISTR(0);

d) 设置USB中断使能,CNTR_WKUPM(唤醒请求)/ CNTR_SUSPM(挂起模块请求)/ CNTR_RESETM(复位中断)

wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;
_SetCNTR(wInterrupt_Mask);

2. USB_SIL_Init是初始化USB IP和端点0

uint32_t USB_SIL_Init(void)
{
  /* USB interrupts initialization */
  /* clear pending interrupts */
  _SetISTR(0);
  wInterrupt_Mask = IMR_MSK;
  /* set interrupts mask */
  _SetCNTR(wInterrupt_Mask);
  return 0;
}

a) 清除所有中断

_SetISTR(0);

b)设置中断源

wInterrupt_Mask = IMR_MSK;
  _SetCNTR(wInterrupt_Mask);

#define IMR_MSK (CNTR_CTRM  | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM  | CNTR_SOFM \
                 | CNTR_ESOFM | CNTR_RESETM )

设置到这里USB的中断处理函数USB_LP_CAN1_RX0_IRQn已经可以进了。

基于STM32F103的USB学习笔记4 - 初始化相关推荐

  1. 基于STM32F103的USB学习笔记27 - CustomHID

    基于JoyStickMouse例程修改即可. 1. 调整描述符 设备描述符可以不用改. 配置描述符长度改为41,主要是增加一个端点. #define USB_CONFIG_DESC_LEN       ...

  2. 基于STM32F103的USB学习笔记35 - Mass Storage之SCSI命令

    参考文档:UFI Command Specification.SCSI Reference Guide CBW包中CB部分(0FH-1EH)的第一个字节是操作码,对于Mass Storage来说,使用 ...

  3. 基于STM32F103的USB学习笔记38 - Mass Storage之SPI Flash做U盘

    1. 将整个Flash作为U盘的空间 Flash大小为4MB,SPI NorFlash的Sector大小为4KB,所以MSC_MEMORY_BLOCK_SIZE设置为4096.. 3个函数的实现如下, ...

  4. USB学习笔记(4)STM32关于USB库的解读

    USB学习笔记(4)STM32关于USB库的解读 为了方便在STM32上实现USB功能,本文对USB库的文件进行解读. USB-FS_Device peripheral interface(外围接口) ...

  5. USB学习笔记(2)USB协议

    USB学习笔记(2)USB协议 本文对前面提到的USB枚举过程中的标准请求以及各种描述符做出大致解释,方便后面的实操. 1. USB标准请求 USB协议定义了一个8字节的标准设备请求,主要用在设备的枚 ...

  6. 【毕业设计之python系列】基于Flask的在线学习笔记的设计与实现

    基于Flask的在线学习笔记的设计与实现 摘要 在线学习笔记系统是一种为学生和教师提供在线学习和教学的平台.本文基于Flask框架,设计并实现了一个在线学习笔记系统.该系统支持用户注册.登录.创建课程 ...

  7. 统计学习导论 - 基于R的应用 学习笔记1

    统计学习导论 - 基于R的应用 学习笔记 Chapter 1 导论 统计学习是什么: 关于估计ƒ的一系列方法 Y=f(x)+ξ f:X 提供给 Y 的系统信息,是 x 的函数 ξ:随机误差项:均值为0 ...

  8. USB学习笔记(3)HID应用分析

    USB学习笔记(3)HID应用分析 本文根据前面对USB系统的了解,和USB协议的学习,列出鼠标,键盘,多媒体控制器,自定义HID设备等HID设备的各种描述符. 前景提要:每个设备有且仅有一个设备描述 ...

  9. 计算机基础与程序设计(基于C语言)学习笔记

    计算机基础与程序设计(基于C语言)学习笔记 前言 这是一个学习笔记 课程导入 在线学习工具:https://c.runoob.com/compile/11 为什么要学习程序设计 (1)存储程序和程序控 ...

最新文章

  1. FMDatabase常见的几个操作
  2. 关于Spring的69个面试问答——终极列表
  3. Java abstract 关键字
  4. 自定义ProgressBar
  5. MATLAB可视化实战系列(四十)-基于MATLAB 自带手写数字集的CNN(LeNet5)手写数字识别-图像处理(附源代码)
  6. cadence 常见pcb电阻_经验分享|高频PCB设计中出现的干扰分析及对策
  7. 算法与数据结构(python):递归
  8. html+id选择器如何使用方法,id选择器_HTML+CSS前端基础知识教程_腾讯视频
  9. Fork_Join - Java多线程编程
  10. 【Nutch2.2.1基础教程之2.1】集成Nutch/Hbase/Solr构建搜索引擎之一:安装及运行【单机环境】
  11. 普通html和vue单选框的样式,vue2实现自定义样式radio单选框
  12. python回车键绑定按钮_python tkinter 绑定回车键
  13. 信数金服:决策模型的迭代
  14. 【OpenCV】OpenCV实战从入门到精通之 -- 离散傅里叶变换相关函数详解
  15. 安卓 dump 工具 影响_工具如何影响文化?
  16. STM32 编码器的CUBEMX的使用
  17. qgc地面站如何导入离线地图_如何下载百度地图离线包并导入OruxMaps
  18. ora 01033 linux,ORA-01033: ORACLE initialization or shutdown in progres
  19. ZigBee模块无线传输星形拓扑组网结构简介
  20. DNF检测原理分析篇

热门文章

  1. Java石头剪刀布(简单小游戏)
  2. 多表联查(多表连接)(join)
  3. WIN32下使用DirectSound接口的简单音频播放器(支持wav和mp3)
  4. 中间件漏洞(Apache篇)
  5. 华为杯第一届中国研究生网络安全创新大赛-Bit_QR
  6. 飞行堡垒9win键解锁
  7. docker创建python容器
  8. linux学习11 正则表达式与文件格式化处理
  9. BAAI 2020 北京智源大会 | Yolanda Gil | Thoughtful Artificial Intelligence
  10. 精品软件 推荐 酷我音乐 一个可以下载320k 音质的音乐播放软件