你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

使用STM32制作U盘(device)

[复制链接]
攻城狮Melo 发布时间:2022-11-3 21:48
硬件环境
+ J+ Y  i+ `7 F3 o" `- _STM32(支持USB)" j1 y/ B# P# i% G# I6 |4 F. Q
存储介质(SPI FLASH、E2P、甚至是片内FLASH均可),本实验使用外部SPI flash(W25Q64)。
& v! R- F+ i: t- k9 G& }& N# _  G2 }使用STM32CubeMX进行配置初始化信息: c8 ]& M6 S! V7 d
1.配置MCU的时钟,外设等信息,可以使用一路串口进行输出Log信息,串口波特率越高越好; m( `! o3 h+ J) Y* P: X
2.MCU管脚配置
6 A: g+ O7 _/ F: b
' j6 Y- {" [, O 8b99d1c2df2844dd8a50e8c493cdfc2b.png 2 t. e$ W! X* l' q5 x1 j
& Y2 g1 z! G" Z- N
4. 时钟配置8 t$ A$ Q8 Q6 @6 E! K
我这里的硬件中有8M的HSE,然后需要注意的是,USB时钟需要配置到48M; \) `3 F8 \: R. d- t

( |. m3 M6 R$ |* _# e' M b7acf9dc412a4a6887a078d5bca6864b.png
- N7 Q0 U7 l: \4 p9 b( }( z9 y' H) g$ [' }* g- a
3.USB配置,记得打开中断
* [7 F$ v' d( C+ O2 H- T+ Q5 E
  k% I( g- v  a7 k: V) ] 0879b662144348a6803d4ca12b7f2787.png   \9 L8 p* c4 j( j
% z% a8 h) K5 r# Z
4.串口
2 I8 e% {' P: D- D
6 H+ L3 ?% Y; z# o 8a0b450eb6a645c288c8e48a3d04a56f.png
4 r4 y  J/ ?& X, ~; Z6 w' [% ?) K2 w1 A- k4 |( Q% T
5.存储介质的通信接口,如使用内部flash,则不需要配置
3 z! x/ S, p! W+ u3 E, ~W25Q64 是SPI FLASH,配置SPI接口,这个配置可能需要根据芯片手册进行调整* X8 G/ l! S) o: t

& S" X% f! K4 Z7 a3 ]! o6 C 21e21095783747e4a081e27bd2ba3ae4.png
3 e. x* q# \% Z% X  C0 B& V' }, h3 V' A$ ?7 y1 V
6.中间件 USB_DEVICE
4 T+ k! _% W/ L) {4 G: [* yClass for FS IP选择大容量存储,其他可以默认,USB_DEBUG_LEVEL改不改都一样,做USB device时没看到打印出log来。如果配置了非0,那么需要重定向printf,并且勾选USE Micro LIB,否则可能会出现问题。# k. z/ E6 F7 d1 W# m

- D+ a- g6 M; R 6aebe1fa36c24165bf020f37cbd628d4.png 9 Q% o0 [8 K& b6 `4 F5 k. U

2 V8 {+ s! N% B( y' v' e7.将堆栈空间改大之后就可以生成代码了
/ b, Q! P9 q0 O) e& H2 d6 T9 J
! f6 N( Y* r( Y& n; F' _, Q& F& f: b修改程序
( O* W. |! `! I生成完程序后,直接编译烧录,然后将USB连接到电脑上,就可以看到已经多出来一个盘符,但是看不到容量和大小,也不能成功格式化磁盘,那是因为我们还没有完成数据的读取和写入
. h8 ]3 f$ E  s7 Y: l0 `$ B0 Z9 n6 U, i
修改添加存储介质的驱动代码
& M3 R2 z9 J) A0 n! W4 n这个步骤很关键,如果你的驱动有问题,那么就会导致格式化失败,也就没办法使用。
, K0 p6 Z* f. r. z
9 \5 r$ D7 d, l7 O( m7 T' HW25Q64
! R; }# R3 T: g( q3 C. I( H/ ^: |必要的函数. J8 _6 N5 V2 c  g$ T" Y
W25Q64.h; Y  k  A# {! J0 [

/ T- w+ x9 g$ T4 U9 t
  1. typedef struct
    0 G! a5 o9 ~& ~* h
  2. {
    . J+ [7 A7 j% @0 D7 W6 y" s
  3.     void (*init) (void);
    - B7 j) p3 ~0 V4 P7 C: |3 R6 b# X6 W
  4.     void (*read_sector) (uint32_t addr, uint8_t *pData, uint32_t length);
    7 |( a* ~% Y! ~7 z" |; f
  5.     void (*write_sector) (uint32_t addr, uint8_t *pData, uint32_t length);- I0 s. s' B1 t
  6.     uint8_t (*get_status) (void);8 F5 R; @9 K) d4 d, N
  7. }W25Q64_Dev_T;
    : X2 c; T- l* n. C% a+ U. w
  8. extern W25Q64_Dev_T w25q64_drv;
复制代码

1 q# K2 K  b" EW25Q64.c4 d5 D6 y( P( D* D: O  U# V: Q
$ z1 W; ]4 Q4 `  R+ U8 B
  1. static void w25q64_write_enable(void);) p5 I6 u; N/ u; h
  2. static void w25q64_write_disable(void);
    ( M& Y0 ]0 Q6 ~' U1 k; ^
  3. static void w25q64_chip_init(void);
    5 ~: A, p8 q% F$ y6 {
  4. static void w25q64_page_write(uint32_t addr, uint8_t *pData, uint32_t length);  //256byte max
    6 U8 N1 i! u( H, x6 C# l& ]
  5. static void w25q64_sector_write(uint32_t addr, uint8_t *pData, uint32_t length);//4kbyte max. b6 C/ T7 F5 N$ y
  6. static void w25q64_sector_read(uint32_t addr, uint8_t *pData, uint32_t length);
    & }! q8 w2 R' _3 m1 _
  7. static void w25q64_erase_sector(uint32_t addr);
    7 D' G' L' r0 q
  8. static uint8_t w25q64_read_satatus(void);7 \5 C7 r9 }* E& M' y

  9. + u. k6 y' B; E# Z2 l
  10. static uint8_t data_padding = 0xff;, U  K/ _. l+ I( o! `. F

  11. 2 D  L) g5 x6 f2 D- ^( S
  12. W25Q64_Dev_T w25q64_drv =
    0 x. _& @6 I! f7 U' H9 _: e
  13. {$ N' F4 |6 O2 y/ R6 S1 Y/ X
  14.     w25q64_chip_init,) w" z! N& ]# |8 ]. P; p  A8 h  X
  15.     w25q64_sector_read,
    8 O2 A7 W( y. G% m# l
  16.     w25q64_sector_write,
    " ], h: n! V$ T' f
  17.     w25q64_read_satatus,  W8 t! d( W# f7 K( l6 c
  18. };
复制代码

+ k& X3 e% I0 J& _" u数据读写函数添加到USB驱动中

7 ]6 L$ e4 O1 C# s9 F1 S我们要修改的文件是 usbd_storage_if.c3 u& e3 b. @/ e. q* K) S7 J3 k

7 D( h" w. [0 ?4 m
  1. #define STORAGE_LUN_NBR                  14 S. q: _2 N6 ^5 f
  2. #define STORAGE_BLK_NBR                  W25Q64_SECTOR_NBR//改为flash介质的sector 数量3 W2 N3 R$ Z2 R8 G, o
  3. #define STORAGE_BLK_SIZ                  W25Q64_SECTOR_SIZE//改为flash介质的sector 大小
复制代码
, t+ `* v! C; c3 R
int8_t STORAGE_Init_FS(uint8_t lun)7 f( ?7 F9 g9 u  N+ s
% p4 Z" o$ p$ W
我们可以添加我们刚刚写的存储介质初始化,如果正常,则返回 USBD_OK
& S/ o0 \) L8 b$ E+ j4 x/ W
6 \3 p5 [3 C, T( L5 Y% Iint8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
/ P3 L2 ]0 v  w, n9 [! a9 l/ z  Y7 R3 d& N5 i! l; o# `
获取存储介质的大小,函数已经填充好,我们可以不动
7 B5 R8 X* \! _4 S4 E6 K! h% P. l2 E4 T4 E5 V5 g& ~& F
int8_t STORAGE_IsReady_FS(uint8_t lun)
1 j9 s! ^8 \- {9 ]
  h, F  g2 u6 X; k获取介质状态,我们要对存储介质的状态进行判断,这里我们要判断两点,一个是是否正在读写状态中,另外一个就是存储介质是否是不可工作状态
3 X3 }3 T1 }5 Q2 `- ~" k9 _
2 J& ?- E  j) v6 N9 ^int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
) h" ]  i' t& O5 C3 T9 y3 H
$ k" y5 g8 M3 H' @4 i8 \判断是否是写保护,我们可以直接返回USBD_OK
/ R& P% H7 z0 ]4 x( V! ~# z
3 I; M+ c  i2 yint8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
1 g& l  x) i) |0 e2 R( e0 i3 g" o5 R% d1 D* F' F# e) q
读取一个扇区,我们将准备好的读取一个扇区的代码填充进来就好2 i; Z8 d# a$ Y' b
( b$ U( |( N+ ]" N6 S
例上述W25Q64的驱动代码:  x4 w4 s  E- K0 T

/ r4 A  g3 a6 d+ o3 E& k
  1. /**
    / p* W+ ?# N& C9 z1 d  g$ E
  2.   * @brief  .1 K7 u) b* f9 S. h3 a1 R$ T, v: N0 i
  3.   * @param  lun: .
    + s! u$ u! D: C# y# r4 k
  4.   * @retval USBD_OK if all operations are OK else USBD_FAIL+ Z" k# {8 J, X8 T; h. X6 ^8 I
  5.   */
    0 [5 S7 d0 Q- A: y- t
  6. int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    5 y& T/ s; C0 C+ j/ s
  7. {
    ; h6 S4 {) y! M  A; y" \6 [
  8.   /* USER CODE BEGIN 6 */
    ; D' w2 k" O8 f: J
  9.   while(STORAGE_IsReady_FS(1) != 0);
    0 w$ _# ~& s6 N5 i
  10.   storage_status = 1;
    4 R# F' A: @9 Q8 ~
  11.   w25q64_drv.read_sector(blk_addr*W25Q64_SECTOR_SIZE, buf, blk_len*W25Q64_SECTOR_SIZE);
    / |+ E1 o# M+ N' m$ q6 ]% H
  12.   storage_status = 0;/ O: K# \$ _4 P2 |# j4 F" B% W
  13.   return (USBD_OK);
    % q% b$ U. A. ~9 e
  14.   /* USER CODE END 6 */9 S6 n0 `8 u% X% S
  15. }
复制代码

8 j; k% z* _; G  Z/ X. i: l" F6 Oint8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
5 v- y" F7 k9 y- T8 [* {% @& ^2 ^, R( s, ]
写入一个扇区,我们将准备好的读取一个扇区的代码填充进来就好) T% A0 J1 [! u' J- f: H$ g

4 X' _* m- ~: I6 B% l$ D3 O例上述W25Q64的驱动代码:
$ w/ R3 |: J  `8 y  G# I$ m* n( e) t3 O/ V& ^  _+ V
  1. /**8 L# W# S3 e- J0 V4 x
  2.   * @brief  .4 S* q6 I  i8 a  H- _" \; V. s& n
  3.   * @param  lun: .
    ' K4 G  S& U5 b  m3 A
  4.   * @retval USBD_OK if all operations are OK else USBD_FAIL$ w% D1 ~6 A1 o( _1 S! t8 S6 v. n
  5.   */
    , B0 ?5 I0 g7 M
  6. int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    ; I' x8 }- b# u: ^
  7. {- O+ n% c. f+ n3 Q
  8.   /* USER CODE BEGIN 7 */' D3 X, Q4 V* j) Q
  9.   while(STORAGE_IsReady_FS(1) != 0);
    " Y  R' t( \; d8 T* V
  10.   storage_status = 1;! ]- ?8 j3 a( f8 Q. D, W. }
  11.   w25q64_drv.write_sector(blk_addr*W25Q64_SECTOR_SIZE, buf, blk_len*W25Q64_SECTOR_SIZE);* i& b. a6 N6 L. k! l7 q
  12.   storage_status = 0;+ f/ b; a& D) r3 X  z( _

  13. 1 ~; |  _  p& c  [7 I  w
  14.   return (USBD_OK);. Q4 `1 t# g% I' k' B
  15.   /* USER CODE END 7 */
    $ z) f- _) P; e. ?/ S9 J5 L
  16. }
复制代码

( u/ D# S" h1 }8 \int8_t STORAGE_GetMaxLun_FS(void)5 w7 j1 z: t: A9 \; ^  V
( F# e# n! P' p. ~" f. n
读取磁盘介质的个数,一般我们只虚拟出一个来,不用管就行
3 O, W1 `" [  g# R$ V3 Q: h& C( ^9 R/ g5 o+ p2 X
我们使用的spi flash的sector大小为4k,也就是4096,USB这边是520,所以我们需要将其修改一致4 @; @. E5 Y8 p1 M( M

) p6 D/ L7 U" ?( C  @修改usbd_msc.h4 n# x7 ]3 v* A& F, W- D8 C1 L8 B
6 j! y. P9 m: \
  1. /** @defgroup USBD_BOT_Exported_Defines
    , R. v9 `/ L3 T" o
  2.   * @{+ M, Q* T. W% X1 T5 t$ k. _9 ?
  3.   */
    ( |6 e+ H  X- U0 t/ @' H2 F
  4. /* MSC Class Config */: g& P0 P; ?/ y/ Y/ E& V6 G+ [
  5. #ifndef MSC_MEDIA_PACKET
    . [7 }9 U3 Y* U! P8 p
  6. #define MSC_MEDIA_PACKET             4096U //512U8 Y& }: V+ o0 O- u4 f
  7. #endif /* MSC_MEDIA_PACKET */7 i/ ?+ e. Y! E0 \

  8. + O/ L1 y% T; }: F4 T5 W# j
  9. #define MSC_MAX_FS_PACKET            0x40U  //0x40
    : u; Q9 v) e0 [3 F
  10. #define MSC_MAX_HS_PACKET            0x1000U //0x200$ ]1 A* t7 d. c+ n8 y

  11. 0 ^! M0 q3 o( \, e8 y" V  m# o
  12. #define BOT_GET_MAX_LUN              0xFE
    7 i) }% e4 _5 q3 Z7 i
  13. #define BOT_RESET                    0xFF
    $ @5 x) `: e0 B% b
  14. #define USB_MSC_CONFIG_DESC_SIZ      32
    # |3 B4 P0 p* N4 |) i/ h$ D, Z

  15. ) v' m  N, e9 V. z) I0 p# E
  16. #define MSC_EPIN_ADDR                0x81U
    % P2 c8 u- i$ f8 l, b0 n/ \
  17. #define MSC_EPOUT_ADDR               0x01U
复制代码

7 ]+ w. [" Z; E' ~修改usbd_conf.h
3 K5 p4 l; i) ^' v6 g: Z  S2 F* J& }1 R8 m' S1 [1 _3 {: j
  1. /** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
    . t/ |" q2 D0 B: G8 O
  2.   * @brief Defines for configuration of the Usb device.* n: o5 y! ]  K( ^
  3.   * @{/ c% L+ F# k( ]) ~9 h
  4.   */
      i8 t1 D& q* r1 F& ^; Y0 Z

  5. # d* p. {1 [7 ^
  6. /*---------- -----------*/
    0 i+ U5 F* K: E' F' Z# C: W9 o* {
  7. #define USBD_MAX_NUM_INTERFACES     1( r/ I/ |# T' E5 w
  8. /*---------- -----------*/
    ' o% a5 D4 w3 {, _
  9. #define USBD_MAX_NUM_CONFIGURATION     1# z/ G+ t) B+ B; J. E  j/ x& G# e
  10. /*---------- -----------*/. \/ e* m9 K  @5 t/ O5 J% d
  11. #define USBD_MAX_STR_DESC_SIZ     4096 //512
    2 j6 g7 Y) V( Y" e, z9 f% i
  12. /*---------- -----------*/( P( S! s4 L' W
  13. #define USBD_DEBUG_LEVEL     37 [, Y6 j% o) ^) _" b
  14. /*---------- -----------*/; t+ r3 e1 V% {8 i1 @$ T( e; h* w
  15. #define USBD_SELF_POWERED     1& f) a3 a3 H+ M* ^' ]. s
  16. /*---------- -----------*/
    0 o# y. h4 ?4 u! w4 V
  17. #define MSC_MEDIA_PACKET     4096 //512
复制代码

. ?- B1 }9 U" X' B+ q4 o至此,我们的U盘就做好了
/ l5 i! r; `/ i0 ]; p) E* Z————————————————
" h" k% X. R& H4 R/ u3 l& ~& y版权声明:Logan Li7 S* K2 H! L1 }. y- v) B# q
- R# o0 |1 M/ C& y

) F. Q- A9 [5 s. d. \& h
收藏 评论0 发布时间:2022-11-3 21:48

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版