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

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

[复制链接]
STMCU小助手 发布时间:2021-11-15 21:01
1.前言
6 u. g3 |( s: }! V一直没有正经从完全无知开始去接触了解一款新的stm型号芯片。趁着这次11月份的新项目的开端需要用到stm32L0系列的单片机,搭载lora模块进行项目开发。这里开个系列博客记录下学习过程和调试过程。
* k/ y4 G, \+ {
8 K  Y+ ], f! p" q8 |! `2.开发工具
- j) o. a! x1 I以前做stm32的开发都是基本用的stm32F系列,代码结构也是套用的公司以前的模板。
$ g0 P" _. r1 n% k本次L0系列采用了st公司提供的一个新的(对笔者来说是新的,之前没用过,其实以前出来比较久了)开发代码生成工具-STMCubeMx。
+ P' f# G9 [1 `: y
6 o) E: b/ P$ F8 n9 y  l0 ^
20191125101556652.png
5 K& Y$ a8 [% l
1 ^- M, T" l; ]3 f# n$ h
这个就是安装完后的工具图标。具体安装下载过程这里不做赘述,不了解的朋友可自行百度。" m  y1 P: n" w% X6 _! T

3 p2 j9 H& R9 W( z3 y' C* _3.简述开发工具生成的代码结构
' r0 F. L8 u; x6 g3 H
Stm32CubeMx自动用户所选的IC型号以及需要用到的mcu资源,外设等自动生成相应的代码,生成的代码使用HAL库。其代码结构基本不需要进行什么修改(用户所选所设置皆正确的情况下),仅仅需要对一些HAL中的回调进行重写(如果你需要)。
+ D7 Z# B  C& |6 X/ ?) [. D1 n
20191125102002856.png

9 l  K6 v# ]1 ?
3 ?& m: x! G8 C" Y$ @1 V  a2 }如图,代码编译工具还是使用keil软件,根据图中代码结构可以很清晰的看到整个代码分为
* Y5 ?/ a2 r: WApplication和Drivers(附加CMSIS)
% p0 t* E% N+ y. }: TApplication里分为MDK-ARM和User。
$ R9 s. j) m9 k& J/ oMDK-ARM是代码工程的一个目录(基于编译,比如编译生成文件,中间文件.o之类的): A; d$ n5 T3 F; l- {
User是用户程序的主入口,如main.c等。& s, _: Q; }: Z3 C; |
需要注意的是User中还包含除main.c之外的两个文件,其中一个msp文件是工具自动生成的,后面分析。ic文件则是和中断回调相关的,这个相比都比较清楚。1 A5 ?- z. n$ ]2 N5 l
/ L3 D4 u3 V! `7 b/ P% Y. U
20191125102405305.png
  C, T4 o& A0 U% U

0 R/ ]  }" O0 c& m7 B. }在Drivers中包含HAL_Driver和CMSIS.
6 W; o  {4 N* A5 i+ h3 z1 q8 ?CMSIS则是和内核相关的,如M0,M3等之类的内核。6 x8 ?  m$ [" P
HAL_Driver则是st给用户提供一些接口,如flash,rtc等的操作接口。
' G1 T/ X6 X8 F5 v: ^) ?) [) r1 d& d% Y7 r" i/ J9 T
3.1 main.c简析
4 \/ ~4 f; n+ M6 n& Z8 \2 ^  ~最简单main.c里面的代码至少包括三部分:HAL_Init,SystemClock_Config,while(1);
0 {7 Z) Q' U* r. ?" p
# }* k# s" h+ }/ P! h: i" ~, e
  1. int main(void)
    ( o1 `6 Z5 L/ f$ w0 x
  2. {
      l- v( N$ _9 x6 H8 Q
  3.         HAL_Init(); //HAL库的初始化" ^% @+ |9 ^- U' X
  4.         SystemClock_Config();//系统时钟配置初始化3 x8 m2 D. y7 B* J, ?( e: e# a$ \
  5.         while(1)//主程序的运行
    6 \7 `3 x8 K' k- U' B8 |% I4 w
  6.         {6 F3 C9 d& o) Q  i4 [- }  U8 }/ O
  7.         }8 P/ s. l5 W" [/ R' E$ W
  8. }
复制代码
" v' j$ D6 q' J/ D6 F, A! R
3.2 代码运行流程以及HAL库的调用结构
/ Z6 |- z) t" D6 O7 f3.2.1 HAL_Init()6 m+ E# u3 K2 W$ Z+ j* t
  1. /**
    & x! J: M. g& q2 p7 y0 Y( H
  2.   * @brief This function configures the Flash prefetch, Flash preread and Buffer cache,
    " ~8 f! V1 Q0 L+ f( S2 ?
  3.   *        Configures time base source, NVIC and Low level hardware
    3 b8 S5 p! Z6 N; m0 t6 _# s
  4.   * @note This function is called at the beginning of program after reset and before
    ) e7 l! w$ B+ k6 M
  5.   *       the clock configuration( P) j+ M# E6 g  K
  6.   * @note The time base configuration is based on MSI clock when exiting from Reset.2 w7 `4 p  |" l' L% |* y
  7.   *       Once done, time base tick start incrementing.
    9 P9 `$ q1 @9 J
  8.   *        In the default implementation,Systick is used as source of time base.+ Y+ _- j( m1 p: o4 r% q6 i
  9.   *        the tick variable is incremented each 1ms in its ISR.
      x' ~! m- L: N+ `% i
  10.   * @retval HAL status1 p1 o9 \4 G6 |$ F  x
  11.   */5 o; z( M# V: t" u
  12. HAL_StatusTypeDef HAL_Init(void)& h: {$ W% I+ Q4 G2 h! p0 k
  13. {+ w5 V* N: D4 r
  14.   HAL_StatusTypeDef  status = HAL_OK;) h' ^% L. E  ?/ W! Q* a. J6 m

  15. . j; z; n: W6 F, ]6 h
  16.   /* Configure Buffer cache, Flash prefetch,  Flash preread */4 x  R: P8 s; [! o" W3 _+ C
  17. #if (BUFFER_CACHE_DISABLE != 0)5 o4 i' f* v2 C9 s6 ?7 ]: R) ^
  18.   __HAL_FLASH_BUFFER_CACHE_DISABLE();( S/ w/ ]$ i8 p# ?0 a$ t
  19. #endif /* BUFFER_CACHE_DISABLE */# W% B8 G' J& s; z4 J. {

  20. $ O. n. ~# U' {- O' H  P7 B, [
  21. #if (PREREAD_ENABLE != 0)
    & S6 e- J5 a5 g! @$ b1 }1 g
  22.   __HAL_FLASH_PREREAD_BUFFER_ENABLE();. K8 D& N! w6 m7 U* E
  23. #endif /* PREREAD_ENABLE */
    4 Z/ W: T" F1 _* S4 u. @2 _" @
  24. : a  O$ ^. G: u1 A3 o6 M
  25. #if (PREFETCH_ENABLE != 0)/ ^* X2 y1 f4 J; i1 O
  26.   __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
    - {3 @  Z, W6 J9 u2 J
  27. #endif /* PREFETCH_ENABLE */, _+ S( V" Y) m
  28. * |4 Z: [4 f( o% P+ |9 |
  29.   /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
    * ?8 I1 u( Y( T1 L9 w
  30.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)1 g# z( `/ R6 c* k) j
  31.   {
    ) M; C6 c# W; }( p3 o
  32.     status = HAL_ERROR;
    ' e5 x; F- b) c7 e8 c
  33.   }5 U/ |! P) u0 l8 W$ }5 m
  34.   else" q% i3 E. |+ U% {7 t- r1 @
  35.   {( C5 ^! G, x/ a7 {: p
  36.     /* Init the low level hardware */2 ^6 I2 g. S/ o6 V6 e
  37.     HAL_MspInit();
    - t  _! X0 Z8 h8 \6 R
  38.   }* q% `+ X) d7 c. K2 o/ O+ O; G
  39. , h) Q9 {# E. H6 K  w% {
  40.   /* Return function status */2 ?; V. N) t5 i# n
  41.   return status;" O. v5 q  l0 M7 k2 Z8 g$ _
  42. }
复制代码
$ x  H; k% N3 `
这里抽出2个关键函数:
, w" G9 z' C. n/ [; SHAL_InitTick,HAL_MspInit! ?) F! b7 s/ V* s
可以看到mcu一启动则调用HAL_InitTick,它的功能是使用SysTick作为时基源并配置1ms刻度(复位后的默认时钟为MSI)
$ W7 O8 R9 v# @9 I- v如果该函数出错,则调用HAL_MspInit。6 G- J9 y( I' ^6 `4 q
这里提下该函数HAL_MspInit是被__weak修饰,叫做弱函数。被这种修饰的函数,通常需要用户自己去实现。实现的位置在哪里?还记得前面提到msp文件吗,就在那里面,当然你也可以写到你想写的地方,msp这个文件只是为了方面管理整个代码工程中的需要重写的函数。4 d# @5 v& R# A- L2 G8 v5 w
( C/ O$ u- B: I, U- @
3.2.2 SystemClock_Config()9 E+ T! I$ y; l4 T
  1. /**
    9 H3 z: b  M4 D7 E& ~. K
  2.   * @brief System Clock Configuration2 |5 i. y% X% R5 K3 R2 l
  3.   * @retval None7 M# E# @8 y# z. F4 z* h
  4.   */
    1 p- K4 ]/ z5 g8 v# a
  5. void SystemClock_Config(void)
    + e$ J* c. v' a
  6. {
    - P2 \) G: b6 N, f' R
  7.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};/ J" A3 J( |* R
  8.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};4 a0 X; r. E+ s

  9. + \6 H# b. ]: d9 M
  10.   /** Configure the main internal regulator output voltage
    7 k/ r, d2 I) g
  11.   */* m9 V5 d8 O( `- d. W
  12.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);# R8 |1 B/ G* x
  13.   /** Initializes the CPU, AHB and APB busses clocks
    2 s8 @" x# P% O9 c0 @0 y
  14.   */, ?4 ^( J, m' w$ [6 C8 A* f
  15.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
    2 ^$ s0 \& `- t+ Z3 p
  16.   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
    & `3 g$ O- p% c# P
  17.   RCC_OscInitStruct.MSICalibrationValue = 0;7 {9 f/ i3 ^& h( ~
  18.   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;  ?3 N/ D2 O7 S3 u3 Q* t
  19.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    " b" o9 n: T- ]2 A/ P) [
  20.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK): ^' p9 x5 I5 t  h4 B$ ?
  21.   {# d4 D. {. D* i3 U
  22.     Error_Handler();6 p, l* K2 x# V0 e/ z, q9 U
  23.   }
    7 j3 P# ]* g* _4 h' R9 `, l
  24.   /** Initializes the CPU, AHB and APB busses clocks 2 j* c3 s3 g8 J+ c3 b- F
  25.   */- @3 o' W1 C0 ~
  26.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK) v; ^7 I9 g3 N" {$ U. U0 U
  27.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    ) V6 T' x" b9 O
  28.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
    " e" ~& ]3 J% w5 q' M. q- O6 U) w
  29.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;3 j  ?$ {" G; M5 r8 J6 K$ M7 c
  30.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;9 A0 s$ y9 e  L+ R% h) c5 V
  31.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  ]) [  W9 L# a0 y& f0 S
  32. 1 a) \( Y0 H7 B
  33.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)% x( _0 z2 R5 c5 Z' D7 \) x/ K+ G" D
  34.   {7 n9 A% O! K' Y5 Z
  35.     Error_Handler();
    2 u1 a. y( [) K' m* S2 [
  36.   }
    ; z" v- H9 s2 y; A% K) g- s
  37. }
复制代码
. i  p8 z* X+ R
这里可以看到对于mcu的时钟选择配置,完全对上刚开始创建工程时的选择。先简单将这个函数分隔下:
8 U8 F( }, w! r/ H( P' o7 ^第一步:配置内部主稳压器的输出电压
7 A1 x& H5 |& t. c第二步:初始化RCC振荡器。HAL_RCC_OscConfig,这里选择了MSI时钟,频率是4.194Mhz/ ?3 i# G7 U. C+ a6 t* y& [
第三步:初始化CPU,AHB和APB总线时钟,HAL_RCC_ClockConfig, H" C5 \3 @% g. E0 c5 ^
如图;% Z- _; l4 c+ u' I& B' P

2 F2 A+ j" ^8 V% l' e" M' P4 s# F
20191125103747351.png
* P% o5 a" }$ m$ b! g
+ e0 a) W5 E( i$ _( ]
ps:关于STM32l0的时钟相关,可以参考datasheet。也可以往官网下载(英文版)
+ w" y2 u4 y/ l& K- W: h9 E1 n% m2 T. G( o' u0 d
4. 话说在前面系列" M9 l  C: M" I6 ^, m+ `: P
在使用St’m32CubeMx生成代码的时候,后期单独修改代码的时候,需要注意:
+ k' O9 D& r# S, N- q1.stm32l0xx_hal_conf.h 头文件指定了哪些文件是否参与编译,文件内是按模块声明的。
0 F/ L9 {* q( \$ T% ~/ a) N2.第一次调试测试单独功能的时候,可以使用工具生成单独模块的代码进行单独测试。1 ?* M: T4 f4 u% |; h) _( b

2 `% j5 ~8 d& v& R% G6 m
0 K4 @# q( J, v- u9 u
* J+ r; T( k1 U' H" B: G
收藏 评论0 发布时间:2021-11-15 21:01

举报

0个回答

所属标签

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