完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html 第五十五章 USB 读卡器(Slave)实验 STM32F7 系列芯片都自带了 USB OTG FS 和 USB OTG HS(HS 需要外扩高速 PHY 芯片 实现,速度可达 480Mbps),支持 USB Host 和 USB Device,水星 STM32F7 开发板没有外扩高 速 PHY 芯片,仅支持 USB OTG FS(FS,即全速,12Mbps),所有 USB 相关例程,均使用 USB OTG FS 实现。 本章,我们将向大家介绍如何利用 USB OTG FS 在 ALIENTEK 水星 STM32F7 开发板实现 一个 USB 读卡器。本章分为如下几个部分: 55.1 USB 简介 55.2 硬件设计 55.3 软件设计 55.4 下载验证 55.1 USB 简介 USB ,是英文 Universal Serial BUS(通用串行总线)的缩写,而其中文简称为“通串线, 是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。 USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、 Microsoft 等多家公司联合提出的。 USB 发展到现在已经有 USB1.0/1.1/2.0/3.0 等多个版本。目前用的最多的就是 USB1.1 和 USB2.0,USB3.0 目前已经开始普及。STM32F767 自带的 USB 符合 USB2.0 规范。 标准 USB 共四根线组成,除 VCC/GND 外,另外为 D+和 D-,这两根数据线采用的是差分 电压的方式进行数据传输的。在 USB 主机上,D-和 D+都是接了 15K 的电阻到地的,所以在没 有设备接入的时候,D+、D-均是低电平。而在 USB 设备中,如果是高速设备,则会在 D+上接 一个 1.5K 的电阻到 VCC,而如果是低速设备,则会在 D-上接一个 1.5K 的电阻到 VCC。这样 当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速 设备。接下来,我们简单介绍一下 STM32 的 USB 控制器。 STM32F767 系列芯片自带有 USB OTG FS(全速)和 USB OTG HS(高速),其中 HS 需 要外扩高速 PHY 芯片实现,我们这里不做介绍。 STM32F767 的 USB OTG FS 是一款双角色设备 (DRD) 控制器,同时支持从机功能和主机 功能,完全符合 USB 2.0 规范的 On-The-Go 补充标准。此外,该控制器也可配置为“仅主机” 模式或“仅从机” 模式,完全符合 USB 2.0 规范。在主机模式下,OTG FS 支持全速(FS,12 Mb/s)和低速(LS,1.5 Mb/s)收发器,而从机模式下则仅支持全速(FS,12 Mb/s)收发器。 OTG FS 同时支持 HNP 和 SRP。 STM32F767 的 USB OTG FS 主要特性可分为三类:通用特性、主机模式特性和从机模式特 性。 1,通用特性 ➢ 经 USB-IF 认证,符合通用串行总线规范第 2.0 版 ➢ 集成全速 PHY,且完全支持定义在标准规范 OTG 补充第 1.3 版中的 OTG 协议 1,支持 A-B 器件识别(ID 线) 2,支持主机协商协议(HNP)和会话请求协议(SRP) 3,允许主机关闭 VBUS 以在 OTG 应用中节省电池电量 4,支持通过内部比较器对 VBUS 电平采取监控 5,支持主机到从机的角色动态切换 ➢ 可通过软件配置为以下角色: 1, 具有 SRP 功能的 USB FS 从机(B 器件) 2, 具有 SRP 功能的 USB FS/LS 主机(A 器件) 3,USB On-The-Go 全速双角色设备 ➢ 支持 FS SOF 和 LS Keep-alive 令牌 1,SOF 脉冲可通过 PAD 输出 2,SOF 脉冲从内部连接到定时器 2 (tiM2) 3,可配置的帧周期 3, 可配置的帧结束中断 ➢ 具有省电功能,例如在 USB 挂起期间停止系统、关闭数字模块时钟、对 PHY 和 DFIFO 电源加以管理 ➢ 具有采用高级 FIFO 控制的 1.25 KB 专用 RAM 1,可将 RAM 空间划分为不同 FIFO,以便灵活有效地使用 RAM 2,每个 FIFO 可存储多个数据包 3,动态分配存储区 4,FIFO 大小可配置为非 2 的幂次方值,以便连续使用存储单元 ➢ 一帧之内可以无需要应用程序干预,以达到最大 USB 带宽 2,主机(Host)模式特性 ➢ 通过外部电荷泵生成 VBUS 电压。 ➢ 多达 12 个(FS)/16 个(HS)主机通道(管道):每个通道都可以动态实现重新配置, 可支持任何类型的 USB 传输。 ➢ 内置硬件调度器可: 1,在周期性硬件队列中存储多达 12(FS)/16(HS)个中断加同步传输请求 2,在非周期性硬件队列中存储多达 12(FS)/16(HS)个控制加批量传输请求 ➢ 管理一个共享 RX FIFO、一个周期性 TX FIFO 和一个非周期性 TX FIFO,以有效使用 USB 数据 RAM。 3,从机(Slave/Device)模式特性 ➢ 1 个双向控制端点 0 ➢ 5(FS)/7(HS)个 IN 端点 (EP),可配置为支持批量传输、中断传输或同步传输 ➢ 5(FS)/7(HS)个 OUT 端点(EP),可配置为支持批量传输、中断传输或同步传输 ➢ 管理一个共享 Rx FIFO 和一个 Tx-OUT FIFO,以高效使用 USB 数据 RAM ➢ 管理多达 6(FS)/8(HS)个专用 Tx-IN FIFO(分别用于每个使能的 IN EP),降低应用程 序负荷支持软断开功能。 STM32F767 USB OTG FS 框图如图 55.1.1 所示: 图 55.1.1 USB OTG 框图 对于USB OTG FS功能模块,STM32F767通过AHB总线访问(AHB频率必须大于14.2Mhz), 其中 48Mhz 的 USB 时钟,是来自时钟树图里面的 PLL48CLK(和 SDMMC、RNG 共用)。 STM32F7 的主频一般为 216Mhz,而 USB 需要 48Mhz 的时钟,由主 PLL 经过 Q 分频得到: PLL48CLK=Fvco/PLLQ,Fvco 为 432,设置 PLLQ=9 就可以得到 48Mhz 的 PLL48CLK 频率。 STM32F767 USB OTG FS 的其他介绍,请大家参考《STM32F7 中文参考手册》第 37 章内 容,我们这里就不再详细介绍了。 要正常使用 STM32F767 的 USB,就得编写 USB 驱动,而整个 USB 通信的详细过程是很 复杂的,本书篇幅有限,不可能在这里详细介绍,有兴趣的朋友可以去看看电脑圈圈的《圈圈 教你玩 USB》这本书,该书对 USB 通信有详细讲解。如果要我们自己编写 USB 驱动,那是一 件相当困难的事情,尤其对于从没了解过 USB 的人来说,基本上不花个一两年时间学习,是没 法搞定的。不过,ST 提供了我们一个完整的 USB OTG 驱动库(包括主机和设备),通过这个 库,我们可以很方便的实现我们所要的功能,而不需要详细了解 USB 的整个驱动,大大缩短了 我们的开发时间和精力。 STM32F7 的 USB 例程全部是以 HAL 库的形式提供,使用起来比较复杂,为了更好的与 STM32F1/F2/F4 兼容,我们通过修改 STM32F1/F2/F4 的 USB OTG 库来支持 STM32F7。 ST 提供的 STM32F1/F2/F4 USB OTG 库在: http://www.stmcu.org/document/list/index/ category-523 这里可以下载到(STSW-STM32046)。不过,我们已经帮大家下载到开发板光盘: 8,STM32 参考资料→STM32 USB 学习资料,文件名:stm32_f105-07_f2_f4_u***-host-device_ lib.zip。该库包含了 STM32F1/F2/F4 的 USB 主机(Host)和从机(Device)驱动库,并提供 了 14 个例程供我们参考,如图 55.1.2 所示: 图 55.1.2 ST 提供的 USB OTG 例程 如图 61.1.2 所示,ST 提供了 3 类例程:①即设备类(Device,即 Slave)、②主从一体类 (Host_Device)和③主机类(Host),总共 14 个例程。整个 USB OTG 库还有一个说明文档: CD00289278.pdf(在光盘有提供),即 UM1021,该文档详细介绍了 USB OTG 库的各个组成部分以 及所提供的例程使用方法,有兴趣学习 USB 的朋友,这个文档是必须仔细看的。 这 14 个例程,虽然都是基于官方 STM32F1/F2/F4 EVAL 板,但是很容易移植到我们的水星 STM32F767 开发板上,稍作修改就可以支持 STM32F7 系列。本章我们就是移植:STM32_USB-Host -Device_Lib_V2.2.0ProjectUSB_Device_ExamplesMSC 这个例程,以实现 USB 读卡器功能。 55.2 硬件设计 本章实验功能简介:开机的时候先检测 SD 卡、SPI FLASH 和 NAND FLASH 是否存在, 如果存在则获取其容量,并显示在 LCD 上面(如果不存在,则报错)。之后开始 USB 配置, 在配置成功之后就可以在电脑上发现三个可移动磁盘。我们用 DS1 来指示 USB 正在读写,并 在液晶上显示出来,同样,我们还是用 DS0 来指示程序正在运行。 所要用到的硬件资源如下: 1) 指示灯 DS0 、DS1 2) 串口 3) LCD 模块 4) SD 卡 5) SPI FLASH 6) NAND FLASH 7) USB SLAVE 接口 前面 6 部分,在之前的实例中都介绍过了,我们在此就不介绍了。接下来看看我们电脑 USB 与 STM32 的 USB SLAVE 连接口。ALIENTEK 水星 STM32 开发板采用的是 5PIN 的 MiniUSB 接头,用来和电脑的 USB 相连接,连接电路如图 55.2.1 所示: 图 55.2.1 MiniUSB 接口与 STM32 的连接电路图 从上图可以看出,USB 座没有直接连接到 STM32F767 上面,而是通过 P7 转接,所以我们 需要通过跳线帽将 PA11 和 PA12 分别连接到 D-和 D+,如图 55.2.2 所示: 图 55.2.2 硬件连接示意图 不过这个 MiniUSB 座和 USB-A 座(USB_HOST)是共用 D+和 D-的,所以他们不能同时 使用。这个在使用的时候,要特别注意!!本实验测试时,USB_HOST 不能插入任何 USB 设 备!另外,如果只有 STM32F767 核心板的,可以利用核心板上面的 MicroUSB 接电脑,同样也 可以实现本例程的功能。 55.3 软件设计 本章,我们在:实验 39 NAND FLASH 实验 的基础上修改,代码移植自 ST 官方例程: STM32_USB-Host-Device_Lib_V2.2.0ProjectUSB_Device_ExamplesMSC。由于 V2.2.0 的库, 仅提供 IAR 工程,所以无法用 MDK 直接打开 ST 的这个例程,不过大家可以参考 V2.1.0 的库 (光盘有提供:STM32_USB-Host-Device_Lib_V2.1.0.rar),V2.1.0 的库提供了 MDK 工程,它 的工程结构和 V2.2.0 的库是一样的。 我们使用 IAR 打开该例程(V2.2.0 仅提供 IAR 工程)即可知道 USB 相关的代码有哪些, 如图 55.3.1 所示: 图 55.3.1 ST 官方例程 USB 相关代码 有了这个官方例程做指引,我们就知道具体需要哪些文件,从而实现本章例程。 首先,在本章例程(即实验 39 NAND FLASH 实验)的工程文件夹下面,新建一个 USB 文件夹,并拷贝官方 USB 驱动库相关代码到该文件夹下,即拷贝:光盘→ 8,STM32 参考资料 →STM32 USB 学习资料 →STM32_USB-Host-Device_Lib_V2.2.0→Libraries 文 件 夹 下 的 STM32_USB_Device_Library、STM32_USB_HOST_Library 和 STM32_USB_OTG_Driver 等三个 文件夹的源码到该文件夹下面。 然后,在 USB 文件夹下,新建 USB_APP 文件夹存放 MSC 实现相关代码,即:STM32_USB -Host-Device_Lib_V2.2.0→Project→USB_Device_Examples→MSC→src 下的部分代码:u***_bsp.c 、u***d_storage_msd.c、u***d_desc.c和 u***d_usr.c等4 个.c 文件,同时拷贝 STM32_USB-Host-Device _Lib_V2.2.0→Project→USB_Device_Examples→MSC→inc 下面的:u***_conf.h、u***d_conf.h 和 u***d_desc.h 等三个文件到 USB_APP 文件夹下,最后 USB_APP 文件夹下的文件如图 55.3.2 所 示: 图 55.3.2 USB_APP 代码 之后,根据 ST 官方 MSC 例程,在我们本章例程的基础上新建分组添加相关代码,具体细 节,这里就不详细介绍了,添加好之后,如图 55.3.3 所示: 图 55.3.3 添加 USB 驱动等相关代码 因为这个 USB 库是针对 STM32F1/F2/F4 系列的,并不是针对 STM32F7 系列,需要对部分 代码稍作修改。需要修改的地方有: 1,u***_core.c ,USB_OTG_CoreInit 函数改为: USB_OTG_STS USB_OTG_CoreInit(USB_OTG_CORE_HANDLE *pdev) { USB_OTG_STS status = USB_OTG_OK; USB_OTG_GUSBCFG_TypeDef u***cfg; USB_OTG_GCCFG_TypeDef gccfg; USB_OTG_GAHBCFG_TypeDef ahbcfg; #if defined (STM32F446xx) || defined (STM32F469_479xx) || defined (STM32F767xx) //增加对 STM32F767xx 的判断 USB_OTG_DCTL_TypeDef dctl; u32 tempreg; #endif u***cfg.d32 = 0; ……//省略部分未改动的代码 USB_OTG_EnableCommonInt(pdev); #endif #if defined (STM32F446xx) || defined (STM32F469_479xx) || defined (STM32F767xx) //增加对 STM32F767xx 的判断 //必须注释掉这个(对 u***cfg.srpcap 的修改),否则无法正常使用!! //u***cfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); //u***cfg.b.srpcap = 1; //必须新增对 GOTGCTL 寄存器 bit6,bit7 的设置,否则 USB 工作不正常 tempreg=USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); //读 GOTGCTL tempreg|=1<<6; //设置 BVALOEN=1 tempreg|=1<<7; //设置 BVALOVAL=1 USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGCTL,tempreg); //写 GOTGCTL dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL); dctl.b.sftdiscon = 0; USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32); dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL); //USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GUSBCFG, u***cfg.d32); USB_OTG_EnableCommonInt(pdev); #endif return status; } 2,u***_dcd.c ,DCD_Init 函数,将: #if defined (STM32F446xx) || defined (STM32F469_479xx) 改为: #if defined (STM32F446xx) || defined (STM32F469_479xx) || defined (STM32F767xx) //增加对 STM32F767xx 的判断 3,u***_dcd_int.c ,DCD_HandleEnumDone_ISR 函数,改为: static uint32_t DCD_HandleEnumDone_ISR(USB_OTG_CORE_HANDLE *pdev) { uint32_t hclk = 216000000; //hclk 时钟为 216Mhz USB_OTG_GINTSTS_TypeDef gintsts; USB_OTG_GUSBCFG_TypeDef gu***cfg; //RCC_ClocksTypeDef RCC_Clocks; //屏蔽掉,系统时钟直接赋值 USB_OTG_EP0Activate(pdev); /* Get HCLK frequency */ // RCC_GetClocksFreq(&RCC_Clocks); //屏蔽掉,系统时钟直接赋值 //hclk = RCC_Clocks.HCLK_Frequency; //屏蔽掉,系统时钟直接赋值 ……//省略部分未改动的代码 } 经过这三处修改(接下来的 USB 例程,都需要做这个修改),就可以使得该库支持 STM32F7 系列芯片了。此外,移植官方库的时候,我们重点要修改的就是 USB_APP 文件夹下面的代码。 其他代码(USB_OTG 和 USB_DEVICE 文件夹下的代码)一般不用修改。 u***_bsp.c 提供了几个 USB 库需要用到的底层初始化函数,包括:IO 设置、中断设置、VBUS 配置以及延时函数等,需要我们自己实现。USB Device(Slave)和 USB Host 共用这个.c 文件。 u***d_desc.c 提供了 USB 设备类的描述符,直接决定了 USB 设备的类型、断点、接口、字 符串、制造商等重要信息。这个里面的内容,我们一般不用修改,直接用官方的即可。注意, 这里:u***d_desc.c 里面的:u***d 即 device 类,同样:u***h 即 host 类,所以通过文件名我们可 以很容易区分该文件是用在 device 还是 host,而只有 u*** 字样的那就是 device 和 host 可以共用 的。 u***d_usr.c 提供用户应用层接口函数,即 USB 设备类的一些回调函数,当 USB 状态机处理 完不同事务的时候,会调用这些回调函数,我们通过这些回调函数,就可以知道 USB 当前状态, 比如:是否枚举成功了?是否连接上了?是否断开了?等,根据这些状态,用户应用程序可以 执行不同操作,完成特定功能。 u***d_storage_msd.c 提供一些磁盘操作函数,包括支持的磁盘个数,以及每个磁盘的初始化 和读写等函数。本章我们设置了 3 个磁盘:SD 卡、SPI FLASH 和 NAND FLASH。 以上 4 个.c 文件里面的函数,基本上都是以回调函数的形式,被 USB 驱动库调用的。这些 代码的具体修改过程,我们这里不详细介绍,请大家参考光盘本例程源码,这里只提几个重点 地方讲解下: 1,要使用 USB OTG FS,必须在 MDK 编译器的全局宏定义里面,定义:USE_USB_OTG_FS 宏,如图 55.3.4 所示: 图 55.3.4 定义全局宏 USE_USB_OTG_FS 2,因为水星 STM32F767 开发板没有用到 VUSB 电压检测,所以要在 u***_conf.h 里面, 将宏定义:#define VBUS_SENSING_ENABLED,屏蔽掉。 3,通过修改 u***d_conf.h 里面的 MSC_MEDIA_PACKET 定义值大小,可以一定程度提高 USB 读写速度(越大越快),本例程我们设置 32*1024,也就是 32KB 大小。 4,官方例程不支持大于 4G 的 SD 卡,得修改 u***d_msc_scsi.c 里面的 SCSI_blk_addr 类型 为 uint64_t,才可以支持大于 4G 的卡,官方默认是 uint32_t,最大只能支持 4G 卡。 5,官方例程在 2 个或以上磁盘支持的时候,存在 bug,需要修改 u***d_msc_scsi.c 里面的 SCSI_blk_nbr 变量,将其改为数组形式:uint32_t SCSI_blk_nbr[3]; 这里,数组大小是 3,我 们可以支持最多 3 个磁盘,修改数组的大小,即可修改支持的最大磁盘个数。修改该参数后, 相应的有一些函数要做修改,请大家参考本例程源码。 6,修改 u***d_msc_core.c 里面的 USBD_MSC_MaxLun 定义方式,去掉 static 关键字。然 后,在 u***d_msc_bot.c 里面修改 MSC_BOT_CBW_Decode 函数,将 MSC_BOT_cbw.bLUN > 1 改为:MSC_BOT_cbw.bLUN > USBD_MSC_MaxLun,以支持多个磁盘。 以上 6 点,就是我们移植的时候需要特别注意的,其他我们就不详细介绍了(USB 相关源码解释,请参考:CD00289278.pdf 这个文档),最后修改 main.c 里面代码如下: USB_OTG_CORE_HANDLE USB_OTG_dev; extern vu8 USB_STATUS_REG; //USB 状态 extern vu8 bDeviceState; //USB 连接 情况 int main(void) { u8 offline_cnt=0; u8 tct=0; u8 USB_STA; u8 Divece_STA; Cache_Enable(); //打开 L1-Cache HAL_Init(); //初始化 HAL 库 Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz delay_init(216); //延时初始化 uart_init(115200); //串口初始化 LED_Init(); //初始化 LED KEY_Init(); //初始化按键 SDRAM_Init(); //初始化 SDRAM LCD_Init(); //初始化 LCD W25QXX_Init(); //初始化 W25Q256 my_mem_init(SRAMIN); //初始化内部内存池 my_mem_init(SRAMEX); //初始化外部内存池 my_mem_init(SRAMDTCM); //初始化 DTCM 内存池 POINT_COLOR=RED; LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7"); LCD_ShowString(30,70,200,16,16,"USB Card Reader TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,110,200,16,16,"2016/7/20"); if(SD_Init())LCD_ShowString(30,130,200,16,16,"SD Card Error!"); //检测 SD 卡错误 else //SD 卡正常 { LCD_ShowString(30,130,200,16,16,"SD Card Size: MB"); LCD_ShowNum(134,130,SDCardInfo.CardCapacity>>20,5,16);//显示 SD 卡容量 } if(W25QXX_ReadID()!=W25Q256) LCD_ShowString(30,130,200,16,16,"W25Q256 Error!"); //检测 W25Q256 错误 else //SPI FLASH 正常 { LCD_ShowString(30,150,200,16,16,"SPI FLASH Size:25MB"); } if(FTL_Init())LCD_ShowString(30,170,200,16,16,"NAND Error!"); //检测 NAND 错误else //NAND FLASH 正常 { LCD_ShowString(30,170,200,16,16,"NAND Flash Size: MB"); LCD_ShowNum(158,170,nand_dev.valid_blocknum*nand_dev.block_pagenum* nand_dev.page_mainsize>>20,4,16); //显示 SD 卡容量 } LCD_ShowString(30,190,200,16,16,"USB Connecting..."); //提示正在建立连接 MSC_BOT_Data=mymalloc(SRAMIN,MSC_MEDIA_PACKET); //申请内存 USBD_Init(&USB_OTG_dev,USB_OTG_FS_CORE_ID,&USR_desc, &USBD_MSC_cb,&USR_cb); delay_ms(1800); while(1) { delay_ms(1); if(USB_STA!=USB_STATUS_REG)//状态改变了 { LCD_Fill(30,210,240,210+16,WHITE);//清除显示 if(USB_STATUS_REG&0x01)//正在写 { LED1(0); LCD_ShowString(30,210,200,16,16,"USB Writing...");//提示正在写入数据 } if(USB_STATUS_REG&0x02)//正在读 { LED1(0); LCD_ShowString(30,210,200,16,16,"USB Reading...");//提示正读出数据 } if(USB_STATUS_REG&0x04)LCD_ShowString(30,230,200,16,16, "USB Write Err ");//提示写入错误 else LCD_Fill(30,230,240,230+16,WHITE);//清除显示 if(USB_STATUS_REG&0x08)LCD_ShowString(30,250,200,16,16, "USB Read Err ");//提示读出错误 else LCD_Fill(30,250,240,250+16,WHITE);//清除显示 USB_STA=USB_STATUS_REG;//记录最后的状态 } if(Divece_STA!=bDeviceState) { if(bDeviceState==1)LCD_ShowString(30,190,200,16,16, "USB Connected ");//提示 USB 连接已经建立 else LCD_ShowString(30,190,200,16,16, "USB DisConnected ");//提示 USB 被拔出了 Divece_STA=bDeviceState; } tct++; if(tct==200) { tct=0; LED1(1); LED0_Toggle;//提示系统在运行 if(USB_STATUS_REG&0x10) { offline_cnt=0;//USB 连接了,则清除 offline 计数器 bDeviceState=1; }else//没有得到轮询 { offline_cnt++; if(offline_cnt>10)bDeviceState=0;//2s 内没收到在线标记代表 USB 被拔出 } USB_STATUS_REG=0; } } } 其中,USB_OTG_CORE_HANDLE 是一个全局结构体类型,用于存储 USB 通信中 USB 内 核需要使用的的各种变量、状态和缓存等,任何 USB 通信(不论主机,还是从机),我们都必 须定义这么一个结构体以实现 USB 通信,这里定义成:USB_OTG_dev。 然后,USB 初始化非常简单,只需要调用 USBD_Init 函数即可,顾名思义,该函数是 USB 设备类初始化函数,本章的 USB 读卡器属于 USB 设备类,所以使用该函数。该函数初始化了 USB 设备类处理的各种回调函数,以便 USB 驱动库调用。执行完该函数以后,USB 就启动了, 所有 USB 事务,都是通过 USB 中断触发,并由 USB 驱动库自动处理。USB 中断服务函数在 u***d_usr.c 里面: //USB OTG 中断服务函数,处理所有 USB 中断 void OTG_FS_IRQHandler(void) { USBD_OTG_ISR_Handler(&USB_OTG_dev); } 该函数调用 USBD_OTG_ISR_Handler 函数来处理各种 USB 中断请求。因此在 main 函数里 面,我们的处理过程就非常简单,main 函数里面通过两个全局状态变量(USB_STATUS_REG 和 bDeviceState),来判断 USB 状态,并在 LCD 上面显示相关提示信息。 USB_STATUS_REG 在 u***d_storage_msd.c 里面定义的一个全局变量,不同的位表示不同状 态,用来指示当前 USB 的读写等操作状态。 bDeviceState 是在 u***d_usr.c 里面定义的一个全局变量,0 表示 USB 还没有连接;1 表示 USB 已经连接。 注意:因为 USB 通信需要 48Mhz 的 USB 时钟,这了我们把 STM32 的主频倍频到 192Mhz (稍微超频,不影响正常使用),以得到 48Mhz 的 USB 时钟。接下来的几个 USB 例程,我们 也都采用 192Mhz 的主频,以得到 48Mhz 的 USB 时钟。软件设计部分,就给大家介绍到这里。 55.4 下载验证 在代码编译成功之后,我们下载到水星 STM32 开发板上,在 USB 配置成功后(假设已经 插入 SD 卡,注意:USB 数据线,要插在 USB_SLAVE 口!不是 USB_232 端口!另外,USB_HOST 接口,也不要插入任何设备,否则会干扰!!),LCD 显示效果如图 55.4.1 所示: 图 55.4.1 USB 连接成功 此时,电脑提示发现新硬件,并开始自动安装驱动,如图 61.4.2 所示: 图 55.4.2 USB 读卡器被电脑找到 等 USB 配置成功后,DS1 不亮,DS0 闪烁,并且在电脑上可以看到我们的磁盘,如图 55.4.3 所示: 图 55.4.3 电脑找到 USB 读卡器的三个盘符 我们打开设备管理器,在通用串行总线控制器里面可以发现多出了一个 USB 大容量存储 设备,同时看到磁盘驱动器里面多了 3 个磁盘,如图 55.4.4 所示: 图 55.4.4 通过设备管理器查看磁盘驱动器 此时,我们就可以通过电脑读写 SD 卡、SPI FLASH 和 NAND FLASH 里面的内容了。在 执行读写操作的时候,就可以看到 DS1 亮,并且会在液晶上显示当前的读写状态。 注意,在对 SPI FLASH 操作的时候,最好不要频繁的往里面写数据,否则很容易将 SPI FLASH 写爆!! |
|
相关推荐
|
|
2136 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1970 浏览 3 评论
4566 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2116 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2629 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 06:19 , Processed in 0.444979 second(s), Total 33, Slave 26 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号