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

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

[复制链接]
STMCU小助手 发布时间:2021-11-15 21:01
1.前言  H, l$ [$ J& O6 o
一直没有正经从完全无知开始去接触了解一款新的stm型号芯片。趁着这次11月份的新项目的开端需要用到stm32L0系列的单片机,搭载lora模块进行项目开发。这里开个系列博客记录下学习过程和调试过程。
" W, G3 k9 r$ U1 ^6 R( D% `0 k) C, n
2.开发工具
+ S7 V8 [6 E. r  S  }以前做stm32的开发都是基本用的stm32F系列,代码结构也是套用的公司以前的模板。
' I# k8 V* f- v3 y& ?本次L0系列采用了st公司提供的一个新的(对笔者来说是新的,之前没用过,其实以前出来比较久了)开发代码生成工具-STMCubeMx。: o3 E' f  ~3 q, g1 Q% g4 c

/ a; M8 D1 ^4 p
20191125101556652.png

. y! i; N% J8 y+ o, J& S# @2 w, U0 r' T6 z3 _, H0 {1 \5 ^
这个就是安装完后的工具图标。具体安装下载过程这里不做赘述,不了解的朋友可自行百度。/ [" q0 ]1 g$ I
* ~, e- N- a0 o- p" J
3.简述开发工具生成的代码结构

6 X! @4 z$ T' O2 _5 IStm32CubeMx自动用户所选的IC型号以及需要用到的mcu资源,外设等自动生成相应的代码,生成的代码使用HAL库。其代码结构基本不需要进行什么修改(用户所选所设置皆正确的情况下),仅仅需要对一些HAL中的回调进行重写(如果你需要)。4 W9 ?5 w4 a  R) v! O& K
20191125102002856.png

# N1 J6 J5 l; N& X! D7 s6 C( i- o1 L( \4 `! s4 J& C
如图,代码编译工具还是使用keil软件,根据图中代码结构可以很清晰的看到整个代码分为
7 B: a0 h$ R+ u* H! w( wApplication和Drivers(附加CMSIS)( G7 R0 w8 J& q$ u9 ^
Application里分为MDK-ARM和User。
- b, j' [- u7 o* m. X' d! V2 kMDK-ARM是代码工程的一个目录(基于编译,比如编译生成文件,中间文件.o之类的)
( g! N8 k: F9 h1 K# N( tUser是用户程序的主入口,如main.c等。8 \  ]: B5 X: w  c
需要注意的是User中还包含除main.c之外的两个文件,其中一个msp文件是工具自动生成的,后面分析。ic文件则是和中断回调相关的,这个相比都比较清楚。
. R' P5 P+ L* \! W+ H6 ]( ?5 o2 s8 R5 R# B7 r: i- j8 u
20191125102405305.png

& ?: x/ W' h1 F3 D5 m- ^5 j3 }& c% E0 {2 @( [# @
在Drivers中包含HAL_Driver和CMSIS.
+ P  a# x3 h$ DCMSIS则是和内核相关的,如M0,M3等之类的内核。# a/ \/ X# q# l; ?. n
HAL_Driver则是st给用户提供一些接口,如flash,rtc等的操作接口。
2 u+ }. b! C$ _# j% R& E: h+ J/ [6 f& x7 e
3.1 main.c简析
$ w  c/ `9 i5 M0 o0 E' Y最简单main.c里面的代码至少包括三部分:HAL_Init,SystemClock_Config,while(1);9 h) _- x, d' V* F5 {
% y8 ?! m; b" r, Y) D
  1. int main(void); ^' L0 F; f( `
  2. {
    3 m3 [4 ?. |8 o6 u
  3.         HAL_Init(); //HAL库的初始化( G* K! P# ]7 D- Q
  4.         SystemClock_Config();//系统时钟配置初始化. o. ~% @  V4 u+ W, z
  5.         while(1)//主程序的运行
    ' x9 l3 F  ^( b  {3 t+ u
  6.         {5 K8 t/ u$ K- f9 |1 R' M6 ^
  7.         }
    ' G% |" o( z$ N2 s% a7 P
  8. }
复制代码

; g; d) H$ u+ k# m. c+ U- l3.2 代码运行流程以及HAL库的调用结构6 v- e9 E2 |, J
3.2.1 HAL_Init()
. s6 k1 O) L, X4 t
  1. /**
    # ^1 u* _" T) P& h; R  W
  2.   * @brief This function configures the Flash prefetch, Flash preread and Buffer cache,* ?5 Y3 ^" F  ~
  3.   *        Configures time base source, NVIC and Low level hardware6 P0 A0 N' ]- ~) O. y
  4.   * @note This function is called at the beginning of program after reset and before# t2 _8 ]9 k' f1 L
  5.   *       the clock configuration
    . I2 z) r, |# I
  6.   * @note The time base configuration is based on MSI clock when exiting from Reset.
    # U1 C) x4 f) `) O) @7 ?
  7.   *       Once done, time base tick start incrementing.
    & Q8 \+ j, v% V* G) s7 p
  8.   *        In the default implementation,Systick is used as source of time base.
    ) l) l: K0 ]1 j  [5 F. L
  9.   *        the tick variable is incremented each 1ms in its ISR.
    " [% ^2 v) p$ a  y) H9 X. h6 x
  10.   * @retval HAL status
    $ `; M- I3 ~: A6 G" ?
  11.   */! W" R3 |% U$ ]2 X- u9 }
  12. HAL_StatusTypeDef HAL_Init(void)
    % Y/ b2 H0 R# G% b
  13. {  i% e+ e- r, \2 U# P) J$ F$ z5 s
  14.   HAL_StatusTypeDef  status = HAL_OK;) z2 m9 T& g6 J9 j7 `' h

  15. ) C3 L% v+ k$ K7 i# g$ ~
  16.   /* Configure Buffer cache, Flash prefetch,  Flash preread */, L* u. b0 y9 t* ~$ S7 U- Q- T
  17. #if (BUFFER_CACHE_DISABLE != 0)% d' q1 Q$ w4 E0 ^, V& b
  18.   __HAL_FLASH_BUFFER_CACHE_DISABLE();
    5 i/ C6 V8 f* p% [' v' m5 P0 n7 l0 `5 Q
  19. #endif /* BUFFER_CACHE_DISABLE */- N/ h, i) l! F2 u5 r- h4 j
  20. 2 n/ Z: g4 T) K; a* ~5 ~
  21. #if (PREREAD_ENABLE != 0)
    5 r  I8 ?4 _0 @1 T) A
  22.   __HAL_FLASH_PREREAD_BUFFER_ENABLE();
    9 X( v' G4 S3 I  y3 g+ S
  23. #endif /* PREREAD_ENABLE */. `, d' b; Y+ O1 W# R4 [

  24. ! F. U5 s! e3 n
  25. #if (PREFETCH_ENABLE != 0)* }' r) c! i: K$ Y- [) Y5 \
  26.   __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
    # R; i, m# H* r/ U& y7 u4 ~
  27. #endif /* PREFETCH_ENABLE */
    ' b* i) d: m/ c. t" e5 C

  28. 9 F( W( _' \9 y3 H& o" F6 |/ U
  29.   /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
    4 g: T( z! B1 Z! g4 l
  30.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
      b! b, w1 `3 @4 M5 @0 d
  31.   {7 i, c  o) q2 S" a' A
  32.     status = HAL_ERROR;" ]8 ~6 v* C: I& ]% J
  33.   }
    8 q) x" @: r. \; ?
  34.   else: I  N. ~7 r0 ?4 F
  35.   {) W4 Z. r% d, I0 o; {
  36.     /* Init the low level hardware */
    , I7 `; K9 _, E5 F9 n
  37.     HAL_MspInit();
    ) `  q. m3 B7 c" a
  38.   }2 c6 J. w2 b+ n9 g
  39. 0 s4 x5 k/ r# P7 v) K# Z7 N
  40.   /* Return function status */
    4 q- H& L' L9 [& d0 ]! |
  41.   return status;
    7 N( `. U) n2 A8 }: A
  42. }
复制代码
2 ^  u* t! G8 J
这里抽出2个关键函数:
4 f9 R# O" r% m) UHAL_InitTick,HAL_MspInit
2 n. J5 `& ~) P, A1 s; S可以看到mcu一启动则调用HAL_InitTick,它的功能是使用SysTick作为时基源并配置1ms刻度(复位后的默认时钟为MSI)$ h) E7 n. B4 D0 J, G# M/ Q" I
如果该函数出错,则调用HAL_MspInit。( m% T$ Z4 p# K6 d  r) c/ h; S
这里提下该函数HAL_MspInit是被__weak修饰,叫做弱函数。被这种修饰的函数,通常需要用户自己去实现。实现的位置在哪里?还记得前面提到msp文件吗,就在那里面,当然你也可以写到你想写的地方,msp这个文件只是为了方面管理整个代码工程中的需要重写的函数。- [# F* r2 _9 `5 i

) O  y; y6 {$ U  O0 x3.2.2 SystemClock_Config()* Y- F& G1 I' T2 L7 a
  1. /**9 A& O. H* ^" o4 y  y
  2.   * @brief System Clock Configuration
    - p6 Y1 G" i! X. N. J6 \9 G6 c
  3.   * @retval None& c# p* Z' o3 ?  V* N" ~, Z+ I0 a
  4.   */* j* t+ \( [- r
  5. void SystemClock_Config(void)$ ]- T5 ^2 O7 P* p: r+ M
  6. {( J3 _3 q* O3 D+ h" s
  7.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    2 T" y. n" i5 q: a3 Y
  8.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    2 @, g3 q  j- i. K: W' A8 X

  9. - A8 o! N1 ?; u* V  b
  10.   /** Configure the main internal regulator output voltage ; n+ W. E$ @6 Q9 Z( ~! T7 Z. n+ b
  11.   */0 W1 i: W6 R  R: `
  12.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);) g9 x$ s& o4 W$ [) ^' t
  13.   /** Initializes the CPU, AHB and APB busses clocks
    3 D; L: Y9 D5 n" `
  14.   */
      j: x6 h- z* h  j  w
  15.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
    ' S' f/ @/ W  R3 e( d2 R
  16.   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
    # G& o& |4 B/ v$ }
  17.   RCC_OscInitStruct.MSICalibrationValue = 0;, v: ^5 p  F1 B5 i
  18.   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
    $ \% u& A+ M: R! A9 L" N  \& p
  19.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;# `! J. d# {/ B* f* `
  20.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    : b. Y" J3 T# C9 b. W& N
  21.   {) k4 T8 W8 M- {% D3 o/ G9 n& z
  22.     Error_Handler();( P- e! _; F! E" b1 O
  23.   }: F, W4 ]) M0 a6 S
  24.   /** Initializes the CPU, AHB and APB busses clocks
    : k, _; c" m# F' Y0 Y" z& M$ K
  25.   */
    2 I- C9 ^$ x  q) i
  26.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK9 z5 c. X8 ~. N# v/ N3 w6 f0 ?2 r
  27.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    & N. O1 U% n% d0 s
  28.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
    1 v. y9 Z. l  z9 H  p3 ?
  29.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    1 q% T) Y* q' I; l5 x9 |, U  O
  30.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
      W. d4 S  e1 |9 |
  31.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    9 _+ A; O& l6 z: t* L/ Z8 D: R
  32. 4 y* a. w) ~8 [6 W
  33.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)  l  s$ S6 L6 W7 O
  34.   {
    ; |! W: f1 d0 p# I2 C0 {/ n2 X
  35.     Error_Handler();
    " U  s& J% L& P
  36.   }! }. T7 r! h6 d- _  N: `
  37. }
复制代码

. B- r) ^7 E- Q; M* Z1 ^5 d& M/ s& k% d这里可以看到对于mcu的时钟选择配置,完全对上刚开始创建工程时的选择。先简单将这个函数分隔下:
+ e$ u) e3 `5 n1 s4 O第一步:配置内部主稳压器的输出电压) m8 g0 a8 Z& K3 Z8 s
第二步:初始化RCC振荡器。HAL_RCC_OscConfig,这里选择了MSI时钟,频率是4.194Mhz
3 s8 q% |, w4 y) v. h第三步:初始化CPU,AHB和APB总线时钟,HAL_RCC_ClockConfig
# g9 G" {' P" C3 W7 S如图;
) ]& E5 U6 `6 I! w7 `$ w3 Q5 r3 M$ c3 c
20191125103747351.png
1 K2 n5 ~& V0 w' j5 Q) f7 |
7 G9 P1 o/ X- G. J5 X
ps:关于STM32l0的时钟相关,可以参考datasheet。也可以往官网下载(英文版)5 o" Q9 L& A# }# s4 q; a  q

# n. T/ U. q- D$ `4. 话说在前面系列- e4 N3 X' G/ \1 s; l
在使用St’m32CubeMx生成代码的时候,后期单独修改代码的时候,需要注意:
& M5 X$ @* s- I1.stm32l0xx_hal_conf.h 头文件指定了哪些文件是否参与编译,文件内是按模块声明的。
- G. n8 S1 K9 G1 |6 [2 i, \2.第一次调试测试单独功能的时候,可以使用工具生成单独模块的代码进行单独测试。
( e) z5 n) t! q* Q; s+ }: m$ w0 ]! x2 L* I% V& ?
* u, s3 _9 Z" X6 h% \

3 T# I9 _& u7 ~, p2 K: @2 q
收藏 评论0 发布时间:2021-11-15 21:01

举报

0个回答

所属标签

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