1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 正点原子运营官 于 2020-4-14 19:32 编辑
1)实验平台:ALIENTEK NANO STM32F411 V1开发板 2)摘自《正点原子STM32F4 开发指南(HAL 库版》关注官方微信号公众号,获取更多资料:正点原子 第三十九章 USB 读卡器实验 上一章我们向大家介绍了如何利用 STM32 的 USB 来做一个触控 USB 鼠标,本章我们将利 用 STM32 的 USB 来做一个 USB 读卡器。本章分为如下几个部分: 39.1 USB 读卡器简介 39.2 硬件设计 39.3 软件设计 39.4 下载验证 39.1 USB 读卡器简介 ALIENTEK MiniSTM32 开发板板载了一个 SD 卡插槽,可以用来接入 SD 卡,另外 MiniSTM32 开发板板载了一个 8M 字节的 SPI FLASH 芯片,通过 STM32 的 USB 接口,我们可以实现一个简单的 USB 读卡器,来读写 SD 卡和 SPI FLASH。 本章我们还是通过移植官方的 USB Mass_Storage 例程来实现,该例程在 STSW-STM32121STM32_USB-FS-Device_Lib_V4.0.0ProjectsMass_Storage 下可以找到(STSW-STM32121 是官方的 USB 库压缩包,在光盘:8,STM32 参考资料STM32 USB 学习资料文件夹下),注意这里并非完全照搬官网的例程,有部分代码是被我们修改过的,以支持我们的应用。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 驱动部分代码(改为 SPI),并将对 NAND FLASH 的操作修改为对 SPI FLASH 的操作。只要这两步完成了,剩下的就比较简单了,对底层磁盘的读写,都是在 mass_mal.c 文件实现的,所以我们只需要修改该函数的 MAL_Init、 MAL_Write、MAL_Read 和 MAL_GetStatus 等 4 个函数,使之与我们的 SD 卡和 SPI FLASH 对应起来即可。 本章我对 SD 卡和 SPI FLASH 的操作都是采用 SPI 方式,所以速度相对 SDIO 和 FSMC 控制的 NAND FLASH 来说,相对会慢一些。 39.2 硬件设计 本节实验功能简介:开机的时候先检测 SD 卡和 SPI FLASH 是否存在,如果存在则获取其 容量,并显示在 LCD 上面(如果不存在,则报错)。之后开始 USB 配置,在配置成功之后就 可以在电脑上发现两个可移动磁盘。我们用 DS1 来指示 USB 正在读写 SD 卡,并在液晶上显示出来,同样我们还是用 DS0 来指示程序正在运行。 所要用到的硬件资源如下: 1) 指示灯 DS0 、DS1 2) 串口 3) TFTLCD 模块 4) SD 卡 5) SPI FLASH 6) USB 接口 这几个部分,在之前的实例中都已经介绍过了,我们在此就不多说了。不过还是要注意一 下 P13 的连接,要和上一章一样! 39.3 软件设计 本章,我们在第三十三章(实验 28)的基础上修改,首先打开实验 28 的工程,在 HARDWARE 文件夹所在的文件夹下新建一个 USB 的文件夹,并拷贝官方 USB 驱动库相关代 码到该文件夹下即拷贝:en.stm32cubef1STM32Cube_FW_F1_V1.8.0MiddlewaresST 文件夹下 的 STM32_USB_Device_Library 文件夹到该文件夹下面。 然后,在 USB 文件夹下面新建 CONFIG 文件夹,用来存放 USB 读卡器实现的相关代码, 拷贝自:STM32Cube_FW_F1_V1.8.0ProjectsSTM3210E_EVALApplicationsUSB_Device MSC_Standalone 文件夹。注意:部分代码是有修改的,并非完全照抄官方代码,具体代码我们 就不细说了(详见光盘本例程源码)。 最后,在 main.c 里面,我们修改 main 函数如下: extern vu8 USB_STATUS_REG; //USB 状态 extern vu8 bDeviceState; //USB 连接 情况 extern USBD_HandleTypeDef hU***DeviceFS; 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); //初始化串口 LED_Init(); //初始化 LED LCD_Init(); //初始化 LCD W25QXX_Init(); //初始化 W25Q64 mem_init(); //初始化内存池 POINT_COLOR=RED; //设置字体为红色 LCD_ShowString(30,50,200,16,16,"Mini STM32"); 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,"2019/11/16"); if(SD_Init())//SD 卡初始化 LCD_ShowString(30,130,200,16,16,"SD Card Error!"); //检测 SD 卡错误 else //SD 卡正常 { LCD_ShowString(30,130,200,16,16,"SD Card Size: MB"); Mass_Memory_Size[1]=(long long)SD_GetSectorCount()*512; //得到 SD 卡容量(字节),当 SD 卡容量超过 4G 的时候,需要用到两个 u32 来表示 Mass_Block_Size[1] =512;//因为我们在 Init里面设置了 SD 卡的操作字节为 512 个, //所以这里一定是 512 个字节. Mass_Block_Count[1]=Mass_Memory_Size[1]/Mass_Block_Size[1]; LCD_ShowNum(134,130,Mass_Memory_Size[1]>>20,5,16); //显示 SD 卡容量 } if(W25QXX_TYPE!=W25Q64) LCD_ShowString(30,150,200,16,16,"W25Q64 Error!"); //检测 W25Q64 错误 else //SPI FLASH 正常 { Mass_Memory_Size[0]=4916*1024;//前 4.8M 字节 Mass_Block_Size[0] =512;//因为我们在 Init里面设置了 SD 卡的操作字节为 512 个, //所以这里一定是 512 个字节. Mass_Block_Count[0]=Mass_Memory_Size[0]/Mass_Block_Size[0]; LCD_ShowString(30,150,200,16,16,"SPI FLASH Size:4916KB"); } LCD_ShowString(30,170,200,16,16,"USB Connecting...");//提示 USB 开始连接 USB_Reset(); MX_USB_DEVICE_Init();//u*** 初始化 LCD_ShowString(30,190,200,16,16,"USB inited..."); delay_ms(1800); while(1) { delay_ms(1); if(USB_STA!=USB_STATUS_REG)//状态改变了 { LCD_Fill(30,190,240,190+16,WHITE);//清除显示 if(USB_STATUS_REG&0x01)//正在写 { LCD_ShowString(30,190,200,16,16,"USB Writing..."); //提示 USB 正在写入数据 } if(USB_STATUS_REG&0x02)//正在读 { LCD_ShowString(30,190,200,16,16,"USB Reading..."); //提示 USB 正在读出数据 } if(USB_STATUS_REG&0x04) LCD_ShowString(30,210,200,16,16,"USB Write Err ");//提示写入错误 else LCD_Fill(30,210,240,210+16,WHITE);//清除显示 if(USB_STATUS_REG&0x08) LCD_ShowString(30,230,200,16,16,"USB Read Err ");//提示读出错误 else LCD_Fill(30,230,240,230+16,WHITE);//清除显示 USB_STA=USB_STATUS_REG;//记录最后的状态 } if(Device_STA!=USB_GetStatus()) { Device_STA = USB_GetStatus();//记录新的状态 if(Device_STA==USBD_STATE_CONFIGURED) { POINT_COLOR=BLUE; LCD_ShowString(30,170,200,16,16,"USB Connected "); //提示 USB 连接成功 } else { POINT_COLOR=RED; LCD_ShowString(30,170,200,16,16,"USB disConnected ");//提示 USB 断开 } } tct++; if(tct==200) { tct=0; LED0=!LED0;//提示系统在运行 if(USB_STATUS_REG&0x10) { offline_cnt=0;//USB 连接了,则清除 offline 计数器 bDeviceState=USBD_STATE_CONFIGURED; } else//没有得到轮询 { offline_cnt++; if(offline_cnt>10) { bDeviceState=USBD_STATE_SUSPENDED; //2s 内没收到在线标记,代表 USB 被拔出了 } } USB_STATUS_REG=0; } } } 在 main 函数里面,我们将 SPI FLASH 的最开始 4.8M 地址范围用作 SPI FLASH Disk,也就是文件系统管理的范围大小,这个我们在之前的 FATFS 也介绍过。 通过此部分代码就可以实现了我们之前在硬件设计部分描述的功能,这里我们用到了一个全局变量 USB_STATUS_REG,用来标记 USB 的相关状态,这样我们就可以在液晶上显示当前USB 的状态了。软件设计部分就为大家介绍到这里。 39.4 下载验证 在代码编译成功之后,我们通过下载代码到 MiniSTM32 开发板上,在 USB 配置成功后(假 设已经插入 SD 卡,注意:USB 数据线,要插在开发板侧面的 USB 口!不是 USB_232 端口!), LCD 显示效果如图 39.4.1 所示: 图 39.4.1 USB 连接成功 此时,电脑提示发现新硬件如图 39.4.2 所示: 图 39.4.2 USB 读卡器被电脑找到 等 USB 配置成功后,DS1 不亮,DS0 闪烁,并且在电脑上可以看到我们的磁盘,如图 39.4.3 所示: 图 39.4.3 电脑找到 USB 读卡器的两个盘符 我们打开设备管理器,在通用串行总线控制器里面可以发现多出了一个 USB Mass StorageDevice,同时看到磁盘驱动器里面多了 2 个磁盘,如图 39.4.4 所示: 图 39.4.4 通过设备管理器查看磁盘驱动器 此时,我们就可以通过电脑读写 SD 卡或者 SPI FLASH 里面的内容了。在执行读写操作的时候,就可以看到 DS1 亮,并且会在液晶上显示当前的读写状态。 注意,在对 SPI FLASH 操作的时候,最好不要频繁的往里面写数据,否则很容易将 SPI FLASH 写爆!! |
|
相关推荐
|
|
2105 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1941 浏览 3 评论
4537 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2084 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2599 浏览 1 评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 08:21 , Processed in 0.557184 second(s), Total 65, Slave 48 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号