完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1)实验平台:【正点原子】 NANO STM32F103 开发板
2)摘自《正点原子STM32 F1 开发指南(NANO 板-HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子 第三十二章 USB 读卡器实验 上一章我们向大家介绍了如何利用 STM32 的 USB 来做一个 USB 虚拟串口,本章我们将利用 STM32 的 USB 来做一个 USB 读卡器。本章分为如下几个部分: 32.1 USB 读卡器简介 32.2 硬件设计 323 软件设计 32.4 下载验证 32.1 USB 读卡器简介 ALIENTEK NANO STM32 开发板板载了一个 2M 字节的 SPI FLASH 芯片,通过 STM32 的 USB 接口,我们可以实现一个简单的 USB 读卡器,来读写 SPI FLASH。 本章我们还是通过移植官方的 USB Mass_Storage 例程来实现,该例程在 MDK 的安装目录 下可以找到(..MDKARMExamplesSTSTM32F10xUSBLibDemosMass_Storage)。 USB Mass Storage 类支持两个传输协议: 1)Bulk-Only 传输(BOT) 2)Control/Bulk/Interrupt 传输(CBI) Mass Storage 类规范定义了两个类规定的请求:Get_Max_LUN 和 Mass Storage Reset,所有 的 Mass Storage 类设备都必须支持这两个请求。 Get_Max_LUN(bmRequestType= 10100001b and bRequest= 11111110b)用来确认设备支持 的逻辑单元数。Max LUN 的值必须是 0~15。注意:LUN 是从 0 开始的。主机不能向不存在的 LUN 发送 CBW,本章我们定义 Max LUN 的值为 1,即代表 2 个逻辑单元。 Mass Storage Reset(bmRequestType=00100001b and bRequest= 11111111b)用来复位 Mass Storage 设备及其相关接口。 支持 BOT 传输的 Mass Storage 设备接口描述符要求如下: 接口类代码 bInterfaceClass=08h,表示为 Mass Storage 设备; 接口类子代码 bInterfaceSubClass=06h,表示设备支持 SCSI Primary Command-2(SPC-2); 协议代码 bInterfaceProtocol 有 3 种:0x00、0x01、0x50,前两种需要使用中断传输,最后 一种仅使用批量传输(BOT)。 支持 BOT 的设备必须支持最少 3 个 endpoint:Control, Bulk-In 和 Bulk-Out。USB2.0 的规 范定义了控制端点 0。Bulk-In 端点用来从设备向主机传送数据(本章用端点 1 实现)。Bulk-Out 端点用来从主机向设备传送数据(本章用端点 2 实现)。 ST 官方的例程是通过 USB 来读写 SD 卡(SDIO 方式)和 NAND FALSH,支持 2 个逻辑 单元,我们在官方例程的基础上,只需要修改删除 SD 驱动部分代码,并将对 NAND FLASH 的操作修改为对 SPI FLASH 的操作。只要这两步完成了,剩下的就比较简单了,对底层磁盘的 读写,都是在 mass_mal.c 文件实现的,所以我们只需要修改该函数的 MAL_Init、MAL_Write、 MAL_Read 和 MAL_GetStatus 等 4 个函数,使之与我们的 SPI FLASH 对应起来即可。 32.2 硬件设计 本节实验功能简介:开机的时候先检测 SPI FLASH 是否存在,如果存在则获取其容量, 并打印在串口调试助手(如果不存在,则报错)。之后开始 USB 配置,在配置成功之后就可 以在电脑上发现两个可移动磁盘。我们用 DS1 来指示 USB 正在读写 SPI FLASH,并在串口助 手显示出来,同样我们还是用 DS0 来指示程序正在运行。 所要用到的硬件资源如下: 1) 指示灯 DS0 、DS1 2) 串口 3) USB SLAVE 接口 4) SPI FLASH 这几个部分,在之前的实例中都已经介绍过了,我们在此就不多说了。 32.3 软件设计 本章,我们在第二十四章(实验 19)的基础上修改,首先打开实验 19 的工程,在 HARDWARE 文件夹所在的文件夹下新建一个 USB 的文件夹,并拷贝官方 USB 驱动库相关代 码到该文件夹下,即拷贝:光盘 → 8,STM32 参考资料→STM32 USB 学习资料→ STM32_USB-FS-Device_Lib_V4.0.0→Libraries 文件夹下的 STM32_USB-FS-Device_Driver 文件 夹到该文件夹下面。 然后,在 USB 文件夹下面新建 CONFIG 文件夹,用来存放 USB 读卡器实现的相关代码, 拷贝自:STM32_USB-FS-Device_Lib_V4.0.0→Projects→Mass_Storage→src 和 inc 文件夹。注意: 部分代码是有修改的,并非完全照抄官方代码,具体代码我们就不细说了(详见光盘本例程源 码)。 接下来,我们在工程文件里面新建 USB_CORE 和 USB_CONFIG 分组,分别加入: USBSTM32_USB-FS-Device_Driversrc 下面的代码和 USBCONFIG 下面的代码。然后把 USBSTM32_USB-FS-Device_Driverinc 和 USBCONFIG 文件夹加入头文件包含路径。 打开 main.c 文件,我们修改 main 函数如下: int main(void) { u8 offline_cnt=0; u8 tct=0; u8 USB_STA; u8 Divece_STA; HAL_Init(); //初始化 HAL 库 Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M delay_init(72); //初始化延时函数 uart_init(115200); //串口初始化为 115200 LED_Init(); //初始化与 LED 连接的硬件接口 printf("NANO STM32rn"); printf("DHT11 TESTrn"); KEY_Init(); //按键初始化 printf("NANO STM32rn"); printf("USB Card Reader TESTrn"); W25QXX_Init(); if(W25QXX_TYPE!=W25Q16) printf("W25Q16 Error!rn");//检测 SPI FLASH 错误 else //SPI FLASH 正常 { Mass_Memory_Size[0]=2048*1024;//前 2M 字节 Mass_Block_Size[0] =512; Mass_Block_Count[0]=Mass_Memory_Size[0]/Mass_Block_Size[0]; printf("SPI FLASH Size:2048KBrn"); } delay_ms(1800); USB_Port_Set(0); //USB 先断开 delay_ms(300); USB_Port_Set(1); //USB 再次连接 printf("USB Connecting...rn");//提示 USB 连接中 Data_Buffer=mymalloc(BULK_MAX_PACKET_SIZE*2*4); //为 USB 数据缓存区申请内存 Bulk_Data_Buff=mymalloc(BULK_MAX_PACKET_SIZE); //申请内存 //USB 配置 USB_Interrupts_Config(); Set_USBClock(); USB_Init(); delay_ms(1800); while(1) { delay_ms(1); if(USB_STA!=USB_STATUS_REG)//状态改变了 { if(USB_STATUS_REG&0x01)//正在写 { printf("USB Writing...rn");//提示 USB 正在写入数据 } if(USB_STATUS_REG&0x02)//正在读 { printf("USB Reading...rn");//提示 USB 正在读出数据 } if(USB_STATUS_REG&0x04)printf("USB Write Errrn");//提示写入错误 if(USB_STATUS_REG&0x08)printf("USB Read Errrn");//提示读出错误 USB_STA=USB_STATUS_REG;//记录最后的状态 } if(Divece_STA!=bDeviceState) { if(bDeviceState==CONFIGURED) printf("USB Connectedrn"); //提示 USB 连接已经建立 else printf("USB DisConnectedrn");//提示 USB 被拔出了 Divece_STA=bDeviceState; } tct++; if(tct==200) { tct=0; LED0=!LED0;//提示系统在运行 if(USB_STATUS_REG&0x10) { offline_cnt=0;//USB 连接了,则清除 offline 计数器 bDeviceState=CONFIGURED; }else//没有得到轮询 { offline_cnt++; if(offline_cnt>10)bDeviceState=UNCONNECTED; //2s 内没收到在线标记,代表 USB 被拔出了 } USB_STATUS_REG=0; } } } 通过此部分代码就可以实现了我们之前在硬件设计部分描述的功能,这里我们用到了一个 全局变量 USB_STATUS_REG,用来标记 USB 的相关状态,这样我们就可以在串口调试助手查 看当前 USB 的状态了。 软件设计部分就为大家介绍到这里。 32.4 下载验证 在代码编译成功之后,我们通过下载代码 NANO STM32F103 开发板上,在 USB 配置成功 后(注意:USB 数据线,要插在开发板的 USB_SLAVE 口!),串口助手打印如图 32.4.1 所示: 图 32.4.1 USB 连接成功 此时,电脑提示发现新硬件,并自动安装驱动,如图 32.4.2 所示: 图 32.4.2 USB 读卡器被电脑找到 等 USB 配置成功后,DS1 不亮,DS0 闪烁,并且在电脑上可以看到我们的磁盘,如图 32.4.3 所示: 图 32.4.3 电脑找到 USB 读卡器的两个盘符 我们打开设备管理器,在通用串行总线控制器里面可以发现多出了一个 USB Mass Storage Device,同时看到磁盘驱动器里面多了 1 个磁盘,如图 32.4.4 所示: 图 32.4.4 通过设备管理器查看磁盘驱动器 此时,我们就可以通过电脑读写 SPI FLASH 里面的内容了。在执行读写操作的时候,就可 以看到 DS1 亮,并且会在串口调试助手上打印当前的读写状态。 注意,在对 SPI FLASH 操作的时候,最好不要频繁的往里面写数据,否则很容易将 SPI FLASH 写爆!! |
|
相关推荐
|
|
969 浏览 0 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
954 浏览 2 评论
2066 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
1162 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
1587 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 14:05 , Processed in 0.662074 second(s), Total 66, Slave 48 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号