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

USB库STM32F0x2移植到STM32F070笔记

[复制链接]
aimejia 发布时间:2018-5-23 13:17
1. 前言' Y: j& u# Q; c1 f! v+ ^  }
ST官方提供的USB库STM32F0x2_USB-FS-Device_LibV1.0.0 是基于标准库的,适用于STM32F0x2系列MCU,但是对于STM32F070来说,就需要稍作修改,本文就一直到STM32F070作一个笔记。; v  T- }- h0 d" S

" l$ L7 x5 Y7 |% R" D4 C4 x2. 移植
) Q  E( [6 O; ?# I& J% Y1 R从STM中文官网上下载STM32F0x2 USB库,地址:https://www.stmcu.org.cn/document/detail/index/id-214961。用MDK打开,首先在Manager Project Items下的Project Targets下新增一项 “STM32F070”:
# d- p! O. M6 \: r# V2 c
5 o6 Q3 \" n4 ~7 [; |6 G3 V1 _* W 1.png + c& w1 S1 ?- Y

& D6 `: h$ {1 B然后切换到”STM32F070”这个Target: 。此后对所有工程属性的修改都会使用于“STM32F070”,而不再是原先的“USBD_HID-STM32072B-EVAL”了。3 w' b7 O0 m4 o- I; c
' P/ r1 H2 {# J& M: |7 g+ k
接下来修改device为STM32F070RB:
3 A- I: R1 N5 n+ a: D8 l  O
5 E; v: F3 Q" a+ R; S( G 2.png
; P7 \3 @4 c/ s' `# M$ e2 r5 l0 |, n0 N& Z/ ?
工程配置弄好了后,接下来我们来修改代码部分。
* ~6 ?/ T8 T. a& k5 R4 y) Y$ K* a
& H3 u+ E+ m) ]) }9 z4 K首先我们来编译一下工程,发现此时是可以编译通过的。但是烧录到STM32F070的板子里(这里使用ST的NUCLEO-F070RB板)去时却不能成功运行。
; P4 t* Z5 ^# ]6 [2 Y( G2 p: i" \' A5 R0 i% A: d- C
STM32F072与STM32F070这两个MCU都有USB,且此IP没有什么不同,那么差异是什么呢?- K5 T4 b8 q! x. O+ r

7 v  ]1 O# ]& i: _: ~- n对比它俩的时钟树:
& ?% ^9 Z( J9 Q7 A% t2 P) g. O" ~, z4 o
3.png 3 z& _  l1 {8 f
5 G! k+ r0 q# K/ P1 K
如上图是STM32F072的时钟树,可知STM32F072是有一个内部48M的晶振,这个晶振是专门给USB提供时钟的。. q; C2 G6 l/ z' n. ]

# L0 R4 I/ ]- B; K; _ 4.png
$ \: }1 d* {+ q! o# n( Y+ x" u
, \' r  E5 B9 `' X# B& X, T, I如上图是STM32F070的时钟树,对比STM32F072,发现STM32F070是没有那个48M内部晶振的,因此在给USB提供晶振时,需要使用到外部晶振,于是,在代码处找到设置晶振的代码进行修改:
- L4 y) Y* [; n9 g; v0 i0 \& C3 _+ ]8 U
usb_bsp.c 的USB_BSP_Init函数内:! j8 S. X& _% j& p. Y/ a1 |8 }
  1. [cpp] view plain copy
    + F! g. \8 c  V7 P4 A# K
  2. RCC_HSEConfig(RCC_HSE_Bypass);  , I) O: k# @7 }5 x( c
  3.   
    " |/ A1 f! ?$ S
  4.   /* Wait till HSE is ready */  8 m/ F' ~$ k" R3 v, J
  5.   while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)  
    * C- t% P. o2 c1 _: E
  6.   {}  ) P& ^. i8 Y: S4 Z7 _0 X! |5 S
  7.   , ?0 X" x/ t) Z/ i# j/ o+ z
  8.   /*Config the PREDIV for RCC_CFGR2*/  3 [0 K$ j8 R3 G! |$ X' _. s
  9.   RCC_PREDIV1Config(RCC_PREDIV1_Div1);  1 f$ r" s  c) B/ ]
  10.     /*HSE/PREDIV selected as PLL input clock*/  
    5 z' \. |! {; H: _1 W
  11.   RCC_PLLConfig(RCC_PLLSource_PREDIV1,RCC_PLLMul_6);  % D) W; @1 u& h2 A! Q8 q7 Q
  12.   /* Enable PLL */  : d9 B) j8 {+ a9 a
  13.   RCC_PLLCmd(ENABLE);  
    3 u. J' r- ?4 `& W  t
  14.   , }" }9 S3 S7 N) Y% Y2 w
  15.   /* Wait till PLL is ready */  8 U  Y, ^$ E) i1 G
  16.   while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)  2 t! Q9 X8 `" x3 ?
  17.   {}  ; N8 Q/ A9 b7 y8 R, i) k- H+ F6 Y
  18.     /*use the PLLCLK as system input clock*/  
    ' G% U& T6 X! R8 e( `, L
  19.   RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  1 m2 L, v8 l" v+ s. V3 K
  20.     /* Wait till PLL is used as system clock source */    ]% n1 k( }# k* W5 @; A
  21.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)  / m) x9 K% s0 w9 p/ h* l
  22.     {  , @, F4 y  A& {) `1 Z4 U4 A
  23.     }  / L, P. q% T( Y4 O0 z
  24.   RCC_HCLKConfig(RCC_SYSCLK_Div1);  4 ?6 j. a  q6 l! l! T" v( N
  25.   RCC_PCLKConfig(RCC_HCLK_Div1);  
    % B; k) ^  v' o! S% J2 H: B
  26.   /* Configure USBCLK from PLL clock */  
    $ W8 d! e% n: v
  27.   RCC_USBCLKConfig(RCC_USBCLK_PLLCLK);
复制代码
在usb_conf.h头文件中注释掉一些宏:3 F8 V, v! w; d
  1. [cpp] view plain copy& C2 O  m" k5 ]9 W% i+ O4 N
  2. //#include "stm32072b_eval.h"  * t7 V; i& i' H: X. m" V# `
  3. ...  2 \: ^* ^1 `# W8 ?  X+ \; Q# @
  4. //#ifdef USE_STM32072B_EVAL  0 T7 \4 |  Z& W& U, n$ f* `
  5. /* When using STM32072B_EVAL board the internal pullup must be enabled */  
    ! R! x. H( `5 S0 j( o" G
  6. #define INTERNAL_PULLUP  
    ! `, ?( c; U/ E
  7. //#endif  
    8 Y& p/ _& Z  O0 b
  8. ...  
    + t4 `4 N  E/ b; T# }
  9. //#define USB_DEVICE_LOW_PWR_MGMT_SUPPORT   //关掉低功耗管理  * w5 W9 ]# n1 \" J# j6 v
  10. ...  
    # }/ \9 c/ ~& j4 _$ m
  11. //#define USB_CLOCK_SOURCE_CRS          //STM32F070下是没有CRS的  
复制代码
接下来整理一下systick:
# e5 ?9 {& D8 I( M
  1. [cpp] view plain copy
    ! ^' k/ N* o0 U
  2. void SysTick_Handler(void)  
    6 l% \/ g: p" x# w" o& f
  3. {  , H1 {) A7 L$ Z: l- b3 H
  4.   
    0 \! ~, Z; p7 h' y3 C7 o* w
  5. #if 0  
    6 u! I+ a  c$ I% }: M) R0 {
  6.     uint8_t buf[4] ={0,10,10,0};  % x2 ]0 H9 w/ S! w& Z
  7.     USBD_HID_SendReport (&USB_Device_dev,  & h, H; \$ h( E6 o0 M
  8.                          buf,  ' d# T6 v; m! h4 D0 o$ x+ C. C
  9.                          4);  " X# d- q- T9 Z+ e$ y
  10. #endif  1 @1 r& ^) f/ m, v0 ^$ o
  11. //#if 0    _# U9 }8 x( g. O5 r
  12. //  uint8_t *buf;  
    # M* K, E. o$ _% y
  13. //  
    ! W( D5 A/ F- ?, R; r; d0 ^  k# g
  14. //  /* Get Joystick position */  # c5 A2 |8 w0 \# f$ u. h
  15. //  buf = USBD_HID_GetPos();  9 b% q5 l% D8 ]9 ~: n) ^- T" @
  16. //  3 S8 z0 j+ W* J" l
  17. //  /* Update the cursor position */  
    . S$ I5 s2 d1 G/ Z4 f
  18. //  if((buf[1] != 0) ||(buf[2] != 0))  
    - p, Y9 q1 w0 V" s% A
  19. //  {  : ]+ f$ n$ z2 f- H- p' T
  20. //    /* Send Report */  # `7 a/ ]* g1 g4 T' k1 l
  21. //    USBD_HID_SendReport (&USB_Device_dev,  
    ! K) D2 T3 j0 e! o# d  }; g* C8 l* T& a
  22. //                         buf,  $ a1 g" T# y8 v! x0 R
  23. //                         4);  
    - ~9 C1 `* Q1 V# C! K
  24. //  }  " F+ S% V/ o4 B& _$ i
  25. //#endif  
    8 A8 }7 n3 {; w: H
  26.   TimingDelay_Decrement();  " m/ _+ T: D8 A0 O7 H8 @
  27. }  
复制代码
这个是延时函数:* y- S) g) r1 O% _
  1. 0 b9 P2 L  ~# G7 t; u+ J7 }) ?
  2. [cpp] view plain copy: O. J' q+ t- Y/ g" f5 E2 P4 t5 U
  3. void HAL_Delay(__IO uint32_t nTime)  1 N5 c7 r$ B; W/ U0 k% V
  4. {  $ v( F- W! m) Y" A
  5.   TimingDelay = nTime;  
    , ^' P2 F2 ]: r+ E; ~3 `
  6.   
    ( k6 a2 H5 F$ ~' q2 \5 X+ ?8 n- N
  7.   while(TimingDelay != 0);    @$ I$ ^. l2 E% e; ]) d8 x
  8. }  
    " t7 S" g& W) A* K  B2 _) }
  9.   1 S1 n1 g- l' r0 I, a  |
  10. /**
    9 e! y7 \; d# d& ]% I: [" L: X
  11.   * @brief  Decrements the TimingDelay variable. ; v3 m2 |% ^' I8 B0 i1 C( g
  12.   * @param  None
    , L8 h% v+ |5 Z
  13.   * @retval None
    # t  j* l; J+ i
  14.   */  
    " ?; a6 U) z' c
  15. void TimingDelay_Decrement(void)  ; S% c- e) Z0 j- f6 b
  16. {  ; f4 A; U; v0 O# y- L
  17.   if (TimingDelay != 0x00)  1 K+ r/ Z7 T( N4 R- T% r
  18.   {  , ?7 @4 O* {& h0 }
  19.     TimingDelay--;  / o/ @7 m6 N7 y2 t
  20.   }    U) r3 M2 W& @9 Q: H. k, X
  21. }
复制代码
修改下systick的间隔时间:% I7 U7 A0 U2 s
0 b8 S' g+ [2 @4 F! m2 ]; A* d% ~
在usbd_usr.c文件中的:
. Y4 {) V( o0 h9 |0 t
  1. [cpp] view plain copy, s9 w; @+ R* \" n
  2. void USBD_USR_Init(void)  1 P# k+ j' \; I7 w0 L+ F6 H0 h
  3. {  
    " H; b/ P* O4 z+ E" w  @
  4.   /* SysTick used for periodic check mouse position */  / y  g& f# @6 Y6 m
  5.   SysTick_Config(SystemCoreClock /1000);  
    9 s6 i, g: i1 Z5 C- I) [
  6. }  
复制代码
最后在main函数内定时发送HID消息:
6 e$ n  p) @& E" l2 \
  1. [cpp] view plain copy0 v' t4 p- ?2 y' F5 Z
  2. int main(void)  
    , z$ N( d2 L$ ?; z" }, T( i0 g& R
  3. {  
    - `" Y- a% V; J4 ?, k3 s
  4.     uint8_t buf[4] ={0,10,10,0};    R3 X. {1 n- j. j( b' d
  5.   /*!< At this stage the microcontroller clock setting is already configured, * ]& h" I3 u3 c' v
  6.        this is done through SystemInit() function which is called from startup 5 Q: e" G' r7 Z9 ~9 N) }
  7.        file (startup_stm32f072.s) before to branch to application main.
    1 k" y6 Q! ^& |, K7 R# o/ N' ^
  8.        To reconfigure the default setting of SystemInit() function, refer to & Y- R, O' T. E5 a& I( o
  9.        system_stm32f0xx.c file
    8 ]8 C1 s7 x! ?  l9 m( |: G
  10.       */  / C# v3 s9 @, _( {1 i! W% t1 }
  11.   ' V3 `( s- R% n
  12.   /* The Application layer has only to call USBD_Init to 5 X  Z, u, `/ _  |$ x* M
  13.   initialize the USB low level driver, the USB device library, the USB clock
    7 J, o% w7 o0 r+ |* _8 b
  14.   ,pins and interrupt service routine (BSP) to start the Library*/  ; j, O3 x5 T7 m+ E; E$ N8 ~/ w
  15.   ; y) D* H3 j5 `
  16.   USBD_Init(&USB_Device_dev,  
    % T, m7 ?8 R$ n3 Q% j& Q8 p  Q1 v5 B& y
  17.             &USR_desc,  - E3 G. L7 [. S" b7 f6 Q
  18.             &USBD_HID_cb,  
    . E$ q$ `* o- v7 v. I4 V
  19.             &USR_cb);  4 Q& @  i/ ]# D& z" z" g
  20.   ) @, l0 l8 J; n3 V
  21.   while (1)  ) Q+ x% _0 N4 [! Y2 y  ?- V3 Y
  22.   {  
    ) Z2 x# L1 _( u1 E* R/ q; M7 l- x
  23. #if 1  ' Q! ]) k0 V+ r* R7 _& ^$ n
  24.       USBD_HID_SendReport (&USB_Device_dev,  
    # G1 Q! {9 d! L! @. e6 r& I
  25.                          buf,  " b* D# F/ B: C5 X( }2 O
  26.                          4);  
    + v, H9 @) a# q% ^5 q$ a
  27.       //delay  8 |2 T- ~9 T6 L2 ^9 r! Z" {
  28.       HAL_Delay(1000);  , v5 q# g% N5 P* k* M+ \" V
  29. #endif  . x4 E  w. i, [. X" z
  30.   }  
    0 Y- j/ Z5 x2 X$ D& K
  31. }  
复制代码
这样代码部分就完成了,通过以上main函数的代码可知,我们是每隔1S向PC端发送一次鼠标消息,鼠标会向右下角移动10个像素。
( [( n8 R( A5 B9 k3 C- m( n
; V% |/ Y3 C0 f" J; q$ e) w* |最后在NUCLEO板上测试OK!
3 H1 v* ?% v+ s6 O  d7 W( d8 O8 o0 Q, p2 w* V" [8 j
, E6 t# v% h: R- h
8 A6 }3 d( r9 v  }
/ t/ P) l! E! @( ?' ?# L4 Q4 S8 L

6 S. ~$ c( _8 p. w7 D, Q  ~5 L' `. E6 v( x: r+ Y) v
转载自FLYDREAM02 B, s9 W$ X$ Q' i3 J
# x8 U- z) ~# x( W* U$ {4 N
赞 收藏 1 评论0 发布时间:2018-5-23 13:17

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版