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

【经验分享】STM32L0系列之【工程开始】

[复制链接]
STMCU小助手 发布时间:2021-11-15 21:01
1.前言+ z# X, g7 U6 G) S( t4 N& c; Z, Q
一直没有正经从完全无知开始去接触了解一款新的stm型号芯片。趁着这次11月份的新项目的开端需要用到stm32L0系列的单片机,搭载lora模块进行项目开发。这里开个系列博客记录下学习过程和调试过程。( O- c( X# y5 \6 q. R

7 w* L9 c! ^' H+ W5 @2.开发工具
( z' \5 d7 Z9 t: l) ^  ?. ^以前做stm32的开发都是基本用的stm32F系列,代码结构也是套用的公司以前的模板。
6 [/ u$ D; M. r& O本次L0系列采用了st公司提供的一个新的(对笔者来说是新的,之前没用过,其实以前出来比较久了)开发代码生成工具-STMCubeMx。) _# L& P$ V; O+ Y. _* G+ m" p( u
8 M1 t3 m7 ?& T- G2 `9 X& O
20191125101556652.png
& N8 X' \. W( o4 O; I; m

# S. I# b8 V3 X这个就是安装完后的工具图标。具体安装下载过程这里不做赘述,不了解的朋友可自行百度。# F0 R$ O; B( _
- c: M! Q' Z$ h+ D1 \
3.简述开发工具生成的代码结构
( |# S2 t; z9 o
Stm32CubeMx自动用户所选的IC型号以及需要用到的mcu资源,外设等自动生成相应的代码,生成的代码使用HAL库。其代码结构基本不需要进行什么修改(用户所选所设置皆正确的情况下),仅仅需要对一些HAL中的回调进行重写(如果你需要)。2 @* k$ L2 B- t+ v  T
20191125102002856.png
- g" z  q0 v$ W5 x9 A& J
( w$ X- k% e/ W$ y( c( _9 q
如图,代码编译工具还是使用keil软件,根据图中代码结构可以很清晰的看到整个代码分为
2 X. {3 \& X) e. B9 A. fApplication和Drivers(附加CMSIS)
& X1 `' O$ z2 l5 _! z, lApplication里分为MDK-ARM和User。
0 T0 }5 T' a8 n. L" |MDK-ARM是代码工程的一个目录(基于编译,比如编译生成文件,中间文件.o之类的)
$ q! f  v- B3 I( lUser是用户程序的主入口,如main.c等。$ P& C0 Y2 p+ A3 U$ U5 h( Y0 Q( i
需要注意的是User中还包含除main.c之外的两个文件,其中一个msp文件是工具自动生成的,后面分析。ic文件则是和中断回调相关的,这个相比都比较清楚。
2 }7 _& e* F4 L' |" G* R- g$ ~& b. i' c3 E8 S
20191125102405305.png
) G$ T6 l7 O4 T5 h& ^7 l! [) \
4 I. V' s9 _# Z; K- {; T
在Drivers中包含HAL_Driver和CMSIS.
+ h0 J9 h: q4 U# M' LCMSIS则是和内核相关的,如M0,M3等之类的内核。
1 q, c1 _8 t; z3 i( MHAL_Driver则是st给用户提供一些接口,如flash,rtc等的操作接口。
3 Q% o: ]# b+ j% ~5 l; G0 t( ]1 i6 Z9 ?5 S. S, X" r8 Y4 h1 a! c
3.1 main.c简析
' a! s' o- C) w, R$ K. |最简单main.c里面的代码至少包括三部分:HAL_Init,SystemClock_Config,while(1);
8 G2 B; P  Q* Q. K/ g, y- ^) f
0 U1 ]% J4 s- X4 x$ `5 ?7 w
  1. int main(void)
    7 q! i/ w  V# \0 ~$ O8 a
  2. {- V) }# Q& U# l7 B& ]' ~
  3.         HAL_Init(); //HAL库的初始化
    ; ^  `1 Z. V4 x! W5 B' C
  4.         SystemClock_Config();//系统时钟配置初始化- A( O' C- g" Z1 H( A# M
  5.         while(1)//主程序的运行
    + K1 m) ?0 X) t$ B- A
  6.         {
    # v" J+ T( I; r4 S6 w0 e1 C
  7.         }. R; [! Z( c: M: L' \: w: X! j
  8. }
复制代码

$ Q4 K* `& i7 K, r3.2 代码运行流程以及HAL库的调用结构
2 w6 `* L6 b; W$ `+ w3.2.1 HAL_Init()9 N6 q2 _: n3 c* L& m: f( W7 e. n
  1. /**( n3 f: F% t. A4 J
  2.   * @brief This function configures the Flash prefetch, Flash preread and Buffer cache,: v) ^% n6 K/ O6 A
  3.   *        Configures time base source, NVIC and Low level hardware
    . x& a2 f* v0 }. R. L. S2 u6 b
  4.   * @note This function is called at the beginning of program after reset and before, }1 U( ~4 F6 ^: \  o. S
  5.   *       the clock configuration
    5 z; Q. z6 r! `2 c/ N% s& l
  6.   * @note The time base configuration is based on MSI clock when exiting from Reset.
    9 Z+ C% }/ R& |+ k  Y! Q/ Z- Y
  7.   *       Once done, time base tick start incrementing." Z/ @) u% G8 e9 h$ F( d# q
  8.   *        In the default implementation,Systick is used as source of time base.! N" G7 O7 H! X/ S6 i! {
  9.   *        the tick variable is incremented each 1ms in its ISR.. }5 [. U5 V2 ^3 ]
  10.   * @retval HAL status8 G2 g. r) s* A% ^& b) `% h
  11.   */
    9 M4 p4 c+ X5 I: P/ l
  12. HAL_StatusTypeDef HAL_Init(void)) k1 u/ c1 y* ?+ o" n
  13. {
      t  ?8 G, B1 ~1 w& t# l  r( j
  14.   HAL_StatusTypeDef  status = HAL_OK;; F' ]/ a2 R" O) b' \

  15. : M# a- `: M- n6 z# D( }
  16.   /* Configure Buffer cache, Flash prefetch,  Flash preread *// M* _/ P; Z: K* j$ z
  17. #if (BUFFER_CACHE_DISABLE != 0)/ ]3 q0 w4 [: j! r$ }
  18.   __HAL_FLASH_BUFFER_CACHE_DISABLE();- @4 P0 ~; @9 E2 U& u
  19. #endif /* BUFFER_CACHE_DISABLE */
    7 x! y; O( G8 G' N

  20. # ]  D+ z3 ]; z4 k
  21. #if (PREREAD_ENABLE != 0)6 D' Q& B1 Q& Q- J/ X
  22.   __HAL_FLASH_PREREAD_BUFFER_ENABLE();( F6 Z4 q4 U* r+ O3 X/ r8 t
  23. #endif /* PREREAD_ENABLE */. d6 y5 A1 x* E+ R* ?9 O0 m; c5 @, [

  24. 4 U4 [2 Q/ v3 E% B
  25. #if (PREFETCH_ENABLE != 0), l8 Z8 t4 Y2 W$ z# w
  26.   __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
    5 K+ D5 y  i/ w$ b
  27. #endif /* PREFETCH_ENABLE */
    ) p7 _4 `3 D+ I( v: a& u. _; q# e

  28. . i; D7 ^0 K0 F( c
  29.   /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */$ [1 h) u' h7 c) y- W# m% f: q+ I
  30.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK): `7 ^) L' |9 J6 ?5 t: Q+ a4 g; C
  31.   {# I2 Q9 x! s% P! [/ o9 E( u3 W
  32.     status = HAL_ERROR;: i$ y+ ]. m* v# a, o/ I
  33.   }7 q, Q( r( l0 b, ~6 O3 v6 u! }
  34.   else
    3 Q! u0 t. ?& r2 C9 F& H
  35.   {
    2 }- p- Q0 x" O
  36.     /* Init the low level hardware */' z: L0 H& t2 h$ g; B
  37.     HAL_MspInit();8 p! w" E8 m, J$ G# k( V0 C! x6 n
  38.   }1 y" Y% V+ E8 L1 ]1 O' p
  39. 0 j3 Y  z$ ~: E6 c# p$ O9 J
  40.   /* Return function status */
    $ R# Z2 P4 w" b* A7 V
  41.   return status;- ]  g( q3 }9 ?* F/ }+ k5 R
  42. }
复制代码

( y# s( r; K+ \4 S这里抽出2个关键函数:
( `* P( N$ V1 N9 u9 eHAL_InitTick,HAL_MspInit6 V% z$ Z+ W8 Z/ p
可以看到mcu一启动则调用HAL_InitTick,它的功能是使用SysTick作为时基源并配置1ms刻度(复位后的默认时钟为MSI)
0 p: H2 u+ G7 u8 s. j9 D如果该函数出错,则调用HAL_MspInit。
1 M4 ]& t" f0 f. i( m/ N4 O/ o这里提下该函数HAL_MspInit是被__weak修饰,叫做弱函数。被这种修饰的函数,通常需要用户自己去实现。实现的位置在哪里?还记得前面提到msp文件吗,就在那里面,当然你也可以写到你想写的地方,msp这个文件只是为了方面管理整个代码工程中的需要重写的函数。
, h, h, f" g) c* Z: J3 ]$ u" A+ ^7 \$ |) b/ o
3.2.2 SystemClock_Config()8 G" z7 }1 A. T2 d  g$ Z
  1. /**2 \, l" z: U2 m" v, _. Q: ~
  2.   * @brief System Clock Configuration3 U( n  N. R. Y& t# }( V$ B+ A
  3.   * @retval None
    & \" Y4 x9 g0 B4 U8 s  R
  4.   */
    / y. y& E5 U7 W  Y( V6 u
  5. void SystemClock_Config(void)
    ) H' }6 m; V5 Y- @6 }9 D
  6. {6 A6 l0 o; ]: @8 S
  7.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    # g0 A. k  ~- g" [& U
  8.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};+ T5 j3 B: h( {% u! g2 f

  9. 4 A( E; m' p9 Q2 F9 r+ h# x
  10.   /** Configure the main internal regulator output voltage
    ( Q; H, H  S/ ^7 W% v* u! F
  11.   */9 E/ \* t* A, Q. E
  12.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);" j+ r* C  A6 Z' H
  13.   /** Initializes the CPU, AHB and APB busses clocks
    ; d4 L) I  O+ d% K
  14.   */
    & ?. g0 X/ ?$ K& X' h% D* S
  15.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;$ W3 X1 p# ]- w# a9 v
  16.   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
    - F3 c- V% B& ]+ o" \
  17.   RCC_OscInitStruct.MSICalibrationValue = 0;4 [& j  }% F  ^! J
  18.   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
      o& z3 o8 I* |" Y) V& f4 f
  19.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;& v  }% d6 t; Z& x$ R6 N# R& G. E
  20.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)) t4 _; H  a# S/ u% J5 [- V
  21.   {
    / K2 k4 p* p+ \0 g
  22.     Error_Handler();$ H! a$ U' \) l( |, v  L- \3 Y' A
  23.   }6 t* R1 A4 s! v: f) Q9 ]5 U
  24.   /** Initializes the CPU, AHB and APB busses clocks
    ; w+ I. t0 J. ]4 a) r1 S( p
  25.   */" C$ {/ a- d$ ]( K$ q
  26.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK2 r( l( G; z) K7 I7 W2 f  M/ D
  27.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;! Q  K* x9 x* P4 n) v5 I& V3 ?
  28.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
    9 P/ U$ x1 C% A9 [( g
  29.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;, z: L* C' h5 F/ I( e2 W  ^5 j3 S
  30.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;$ k3 f/ L! b, F
  31.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;$ u# ?- L- l" D- S4 N$ Y) b  k+ {

  32. . a3 r4 _* x0 A+ o  D9 q. v6 |
  33.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
    ( c5 \2 X- ~% h2 }
  34.   {! T6 g4 T: C" G2 `# k5 B; Y
  35.     Error_Handler();
    & H/ a, g/ `6 i  p; ~' s  m* P
  36.   }
    0 |% l3 d7 |) R" w
  37. }
复制代码

2 c8 Z6 ^. n% S5 t0 e; \5 Q7 j+ x这里可以看到对于mcu的时钟选择配置,完全对上刚开始创建工程时的选择。先简单将这个函数分隔下:3 M$ H  F" r9 w
第一步:配置内部主稳压器的输出电压
' f' U. u$ K: Y5 U. d1 b2 F第二步:初始化RCC振荡器。HAL_RCC_OscConfig,这里选择了MSI时钟,频率是4.194Mhz
! W5 P$ W8 S' W3 h& s+ k: ~第三步:初始化CPU,AHB和APB总线时钟,HAL_RCC_ClockConfig
4 M& f) a! a7 N& a3 k9 P如图;
8 x' k: W! K, J1 _! T8 }
9 ~, t' E. `8 v6 U0 D4 J! p1 |9 ^
20191125103747351.png
4 n5 c% Y0 a$ f5 ]6 }; }* ~
; g# ~$ D+ A$ F( G- j$ M
ps:关于STM32l0的时钟相关,可以参考datasheet。也可以往官网下载(英文版)2 b( \+ I" Q' m; ?4 w

$ S$ x% h% Z$ p  u# l4. 话说在前面系列6 ?, D/ Y5 |7 ?: |& [) M1 _; b
在使用St’m32CubeMx生成代码的时候,后期单独修改代码的时候,需要注意:
+ p3 K  h! d) R2 ^1.stm32l0xx_hal_conf.h 头文件指定了哪些文件是否参与编译,文件内是按模块声明的。$ l" t- v$ S0 [
2.第一次调试测试单独功能的时候,可以使用工具生成单独模块的代码进行单独测试。% e" Q* P# @5 q2 q% e$ ^
: W* `# ?$ ~$ T! Z8 d& P

  c1 e+ F" ~2 I$ c2 n! l  Z6 U* X" \! M( d$ |* \  M8 S
收藏 评论0 发布时间:2021-11-15 21:01

举报

0个回答

所属标签

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