欢迎大家留言交流~

要实现USB读卡器,其核心就是F429作为从设备用USB_MSC与主机通讯,利用FATFS从SD卡、SPI_FLASH、NANDFLASH中读写数据。

什么是OTG?OTG是On-The-Go的缩写,是近年发展起来的技术。2001年12月18日由USB Implementers Forum公布,主要应用于各种不同的设备或移动设备间的联接,进行数据交换。

产生背景

USB技术的发展,使得PC和周边设备能够通过简单的方式、适度的制造成本,将各种数据传输速度的设备连接在一起。上述我们提到的应用,都是通过USB连接到PC,并在PC的控制下进行数据交换。

但这种方便的交换方式,一旦离开了PC,各设备间无法利用USB口进行操作,因为没有一个设备能够像PC一样充当主机。

作用

OTG技术就是在没有Host的情况下,实现设备间的数据传送。

USB模式为三种:1.OTG/dual_role_device 具备一根OTG_ID线用来判断为主设备或时从设备的,作为OTG设备的时候使用。也就是可以根据外接的来判断对面是主还是从,自己进行主从转换。

2.host_only,仅作为主设备。OTG_ID就用不到了。

3.device_only,本次实验是要我们的设备做一个大容量存储设备,就是处于这个模式。

F429实验

由于USB要用48MHZ,而主频HCLK之前是180M,无法正数分频至48M。原子采用倍频HCLK到192MHZ,再分频USB时钟频率至48MHZ。

但是F429的HCLK不是最大只能到180MHZ吗?我用cubemx也无法设置到192MHZ啊。原子说,超频的不多不影响使用,那我觉得还是不要这么做比较好,不正规。

输入USB时钟频率为48MHZ让cubemx自己去算,算出来HCLK是120MHZ,太低了。

上网查找,HCLK为168MHZ时可以。我设置下去,果然可行。那么就要注意了,如果用到了USB,之前其他功能的时钟肯定就改变了。

所以,以后如果要用到USB,直接将HCLK设置为168MHZ。

VBUS管脚不用选,原子原理图上的USB接口上的VBUS也没有接单片机,直接通往5V就好了。

FATFS支持USB DISK也就是U盘,但是必须是在HOST模式,支持MSC的情况下。

F103实验

选上USB,看来F103只支持从设备啊。选项都默认。

配置中间层,选择MSC大容量存储设备。其余选项默认

修改中断,让USB的中断最高。生成代码。

与原子不同,他用的USB驱动是2013年版的,cubemx生成的是2020年版的。所以有一定差异。主要表现在USB调用SD卡的函数不同,他是在mass_mal.c(F103)usbd_storage_msd.c(F429)中,我的是在usbd_storage_if.c(F103)中,但是作用是一样的,主机操作USB_slave读写,但是USB驱动不知道该去读写哪的扇区,这种文件就是供用户修改,可以连接至SD卡的读写函数。

下载验证

程序编写完毕后,编译下载,计算机第一次识别不出来,磁盘驱动器能识别出来是STM 的USB设备,但是在计算机中找不到磁盘,原来是SD卡没插入。那肯定不行啊。。。

接着插入SD卡,重启开发板,真的识别出来了。

这个“U盘”的名字是我在格式化tf卡的时候,起的名字。他存储在tf卡的启动扇区,扇区0的FAT32格式下。

打开U盘,只有一个文件,这个文件就是上个FATFS实验生成的。

打开这个文件

尝试修改一下,看用开发板的FATFS读出的一致么。我看到网上有人提问如果开发板没有做FATFS,这种USB读卡器还能用么。到此,我们知道,USB驱动调用的都是直接调用SD卡的读写函数,跟FATFS一样,都是中间层。同为中间层不存在调用关系。

修改完后,操作开发板挂载SD卡,然后读这个文件。一致!

用开发板创建一个文件,创建成功,关闭失败,读取失败

怀疑是文件名称问题,改回原有名称,尝试创建。

还是关闭文件失败。那是不是有可能是FATFS的创建文件功能收到了影响呢?

用上一个实验的工程实验,没有问题,一切正常。

因为我看到我尝试把USB中断优先级比TIM1低

我以前调试过USB,USB的优先级应该最高。把USB中断优先级设为1,TIM设为2

结果还是不行。但是USB优先级调高肯定没问题。

我现在怀疑是否栈的空间不够了,调至0x2000看看效果。

还是不行啊。在写完文件后关闭返回的是1.

而且读出的数据也不对

因为在FATFS实验中给的栈是0x1000,那么是不是还得增加栈的大小啊,设置为0x2000。

还是不行!

实在不知道了,上网求助!顺带吐槽一下原子哥,不是帮顶就是说好好检查下代码。大哥,我给你跪了。

还是STM社区给力,大神真多。

还真有可能是FATFS和USB同时操作SD卡造成的影响。我去看原子例程的USB读卡器实验,发现都没有FATFS。也就是没有同时实现USB、FATFS同时操控SD卡。

那么我的代码中USB是用的封装过的函数,即SD卡实验中的函数。

在读写中关闭了中断。也就是说其他中断打扰不了USB.

而FATFS调用的是自动生成的

bsp_driver_sd.c是自动生成的SD卡操作底层文件。

然后被自动生成的sd_diskio.c中间层调用。

FATFS调用->SD_read调用->BSP_SD_ReadBlocks..

我们看到整个过程,没有关闭中断保护。那么就有可能FATFS对SD卡的操作被其他中断打断。那么增加关闭中断,试试效果

不接USB线实验下FATFS。

成了。。。

接上USB线,等待计算机识别出来SD卡,再实验FATFS

计算机识别出“U盘”,并且文件内容正确

而且FATFS也可以成功操作。

那么我们试试创建新文件“TanCheng.txt”和内容,成功

但是呢,在计算机中刷新了很多遍,还是看不见“TanCheng.txt”

重新插拔usb线,相当于重新枚举下设备,文件才出来。

那么我尝试从计算机修改“TanCheng.txt”内容,看FATFS能否成功。成功!

那么我们之前设置的优先级为1,还是不够高,设置为0怎么样?

不成功,能识别出来是USB,但是操作失败。所以还是设置回优先级为1吧。

得了,测试完毕,完成了USB读卡器的功能。也就是相当于U盘了。


总结:

刚开始配置完USB发现不行,真是吓一跳,因为USB驱动比FATFS难太多了。fatfs都那么费劲,这USB不得弄上个一个星期。赶紧回顾下以前的USB笔记,回顾了一下USB的枚举、设备描述符、管道等知识点。发现这么学实在是太费时间了。还是通过不断调试,上网查找资料解决实际问题吧。没想到调着调着看到大神的几句话就豁然开朗了。

说到这里还真的很奇怪,之前FATFS使用时不加开关中断也好使,加上USB就不好使了。可能USB的操作还是太频繁了吧。

  1. F103创建完代码后,去usbd_storage_if.c增加SD卡操作的函数。
  2. USB读卡器和FATFS的核心都是中间层,应用层通过这两个中间层去操作SD卡的底层,也就是读写。归根结底操作的都只是SD卡的读写函数而已。
  3. 读写SD卡期间一定要关中断,不然会造成正在读写SD卡时被打断,从而读写失败。但是cubemx重新生成代码又会把sd_diskio.c和bsp_driver_sd.c的文件重新创建,开关中断代码就被擦除了,虽然__weak uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)前面有weak,但是在整个fatfs中间层和底层都找不到合适的地方去重新定义这个函数,所以只好在每次cubemx之后记得加上
  4. __weak uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    {
      uint8_t sd_state = MSD_OK;
        __disable_irq();   // 关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)
      if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)
      {
        sd_state = MSD_ERROR;
      }
        __enable_irq();    // 开启总中断
      return sd_state;  
    }
  5. __weak uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    {
      uint8_t sd_state = MSD_OK;
        __disable_irq();   // 关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)
      if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK) 
      {
        sd_state = MSD_ERROR;
      }
        __enable_irq();    // 开启总中断
      return sd_state;  
    }
  6. 计算机无法实时看到SD卡上新增的文件,需要插拔一下,重新枚举。FATFS可以实时看到。
  7. 枚举的过程不要打断,比如debug什么的,全速运行。如果枚举不上,重新插拔试试。
  8. USB的优先级要设置高,但是不要到0!!

拓展阅读:

STM32的USB模块可以产生三种中断:USB唤醒中断、USB高优先级中断和USB低优先级中断,在STM32的参考手册中没有详细说明这三种中断对应哪些事件,现说明如下:
1)USB唤醒中断:在中断向量表中的位置是42。这个中断在USB设备从暂停模式唤醒时产生,唤醒事件由USB_ISTR寄存器的WKUP位标识。
2)USB高优先级中断:在中断向量表中的位置是19。这个中断仅由USB同步(Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,正确传输事件由USB_ISTR寄存器的CTR位标识。
3)USB低优先级中断:在中断向量表中的位置是20。这个中断由所有其它的USB事件产生,例如正确传输(不包括同步模式和双缓冲块模式)、USB复位等,事件标志位在USB_ISTR寄存器中。
在STM32的USB开发包的例子中包含了上述中断的处理,例如在USB扬声器的例子中,CTR_HP函数处理USB高优先级中断;在所有例子中都有USB_Istr()函数处理USB低优先级中断。

USB如何区分低速、全速和高速设备:对于全速和高速设备,上拉电阻是接在D+上;而低速设备则是上拉电阻接在D-上。

USB枚举过程:

(1)       USB主机检测到USB设备插入后,对设备复位。

(2)       USB主机对设备发送获取设备描述符的标准请求。

(3)       设备收到该请求后,在数据过程将设备描述符返回给主机。

(4)       主机在成功获取到一个数据包的设备描述符后并且确认无错误后,返回一个0长度的状态数据包给设备。

(5)       主机再对设备复位一下,接下来进入到设置地址阶段。

(6)       USB主机发出一个设置地址的请求,地址包含在建立包中。

(7)       USB设备在收到地址后,返回0长度的状态包。

(8)       主机收到0长度的状态包之后,返回一个ACK。

(9)       设备在收到这个ACK之后,就可以启用新的地址了。

USB一直进中断的原因:主机每1ms就给设备发送一个sof,3ms没反应主机就挂起。所以一直进中断属于正常现象。

USB虚拟串口使用时应注意:

(1)       用于上拉的控制位使能时,主机能检测到USB设备。

(2)       设备插入时,地址为0,后由主机分配地址。

(3)       枚举结束前(即设备被识别前),不能中断程序,否则设备不能被识别。

(4)       设备发送usb_SendDataToHost("\r\n$ERRCMD#\r\n", 10)注意数据长度为10,而不为16.(不知道是不是“\$#这样的符号不算,求大神赐教”)

主机发送“WHO’S DEMO”这类有空格的字符串时,空格会被省略,在设备里计算长度时应为9,而不为10.


从零实现 USB_SLAVE读卡器 USB_MSC+FATFS+SD/SPI_FLASH/NANDFLASH相关推荐

  1. cubemx 读卡器_STM32CubeMX基于SD卡的FATFS文件系统测试

    1.问题描述:使用STM32CubeMX配置SD基于SD卡的FATFS文件系统,并进行测试文件的读写. 2.测试准备: (1)测试环境: 软件平台:STM32CubeMX -4.22.0;KEIL5 ...

  2. VS code+STM32CubeMX 使用 FreeRTOS+FatFS+USB_DEVICE 搭建 SD卡 读卡器 和 读写 SD卡 示例项目

    文章目录 1. 新建项目 2. 配置 CubeMX 项目 3. 配置 EIDE 项目 4. 编写代码 5. 编译下载 6. 效果展示 本例介绍如何使用 vscode 插件 EIDE 和 STM32Cu ...

  3. 基于STM32CubeIDE 开发 FATFS + SD卡 + USB 的读卡器功能

    一.介绍 本次采用STM32CubeIDE 平台 STM32L476RE 芯片 自带 usb接口和 Mirco卡槽,实现通过USB连接电脑能正确对SD卡中的文件进行读写操作,同时芯片内部程序也可以以F ...

  4. 从零实现 FATFS+SD卡

    cubemx软件版本是V4.23.0,芯片型号是STM32F103ZET6.STM32F429IGT6;SD卡是闪迪的64G tf卡,然后用了转大卡的卡槽,exFAT. 该篇为调试过程,所以阅读时一定 ...

  5. STM32Cube的FATFS+SD卡

    最近两天由于之前研究的GPS+BD定位信息不只需要获取信息并显示,还需要对当时的信息进行存储,比如说我们在一个地方进行测量,测量人员记录了测量数值和位置,但是不免会出现错误,当然GPS出现错误也有可能 ...

  6. 基于STM32F407通过STM32CubeMX实现FATFS+SD卡多行存储

    在实际的工程运用中,大多数都需要将获取的数据进行存储,防止数据的丢失以及后期的数据验证. 一.主要任务 1 配置FATFS实现在SD卡中创建TXT文件: 2 将数据分行写入SD卡的TXT文件中: 3 ...

  7. 9、STM32 SDIO FATFS(SD卡)

    本篇文章使用STM32对SD卡通过SDIO配置,读写文件 在使用FATFS时值得注意得是若通信SDIO不启动DMA方式读写,容易导致其他任务中断打断读写时序,导致FATFS的执行出现异常,常见返回为F ...

  8. cubemx 读卡器_cubeMX 之 SD卡读写

    一.首先打开软件配置系统内核System Core选择调试接口,如果用ST-Link就选择S W (SYS -> Debug)  和 时基时钟  Timebase Source 选择时钟源,修改 ...

  9. 3.1、CUBEMX使用FATFS读写SPI_FLASH

    所需工具 CUBEMX5.6 STM32F103ZET6开发板(正点原子战舰) LINK及其他线束 1.CUBEMX设置 设置RCC 切记选择第三个,否则串口无法使用. 设置串口 设置SPI_FLAS ...

最新文章

  1. GitHub 的 AI 编程工具漏洞高达 40% ,再次陷入争议……
  2. 边缘检测的简单例子(MATLAB)
  3. Xshell分屏显示
  4. CookieValue注解
  5. EventUtil.addHandler方法
  6. php symfony 安装,Symfony4中文文档: 安装和设置Symfony框架
  7. boost boost::asio::read socket.read_some 区别
  8. -mmin find shell 报错_[shell]find用法小结
  9. 通过CVE-2017-17215学习路由器漏洞分析,从入坑到放弃
  10. java for while do-while 循环的经典题
  11. 家庭电信网弄外网唤醒并远程内网电脑
  12. Cocos2d-x面试题
  13. css3效果隔两秒旋转然后停两秒再继续旋转,无限循环
  14. 大学生性价比计算机推荐,快开学了 大学生该如何选择一款高性价比电脑?
  15. Python中的os.chdir()函数:改变当前工作目录
  16. 大二第二次月赛--买水果
  17. 【PMSM】二. 经典电流环、速度环设计(下)
  18. 大白话讲解Bootstrap是什么
  19. Java8新特性——lambda表达式
  20. The type initializer for ‘Gdip‘ threw an exception. (centos)

热门文章

  1. Round Robin 概念理解
  2. 大牛直播跨平台RTSP/RTMP转RTMP转发SDK 1
  3. 参考文献去哪里查找,参考文献标准格式是什么
  4. SpringSecurity OAuth2实现单点登录,微信扫码登录,Redis缓存验证码---入门到实战
  5. java templates_java中如何设定new template
  6. JVM性能调优监控工具hprof使用详解
  7. Mysql中 /*[叹号] */含义
  8. 汇编实验之用debug命令查看寄存器和内存中的内容
  9. 4 FFmpeg从入门到精通-FFmpeg转码
  10. 白平衡,颜色校正,颜色映射When Color Constancy Goes Wrong, brown