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

STM32库开发实战指南F103读后感和学习笔记

[复制链接]
Bowen1028 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑 1 ^& n# `9 s; O( h8 r3 S

, l! G- \8 Y/ W9 L4 m' L
编辑原因:上传代码不全,补齐代码。
3 x! C. x2 O( v0 ^
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)) c9 s$ K  Y9 F; F) }
  2. {
    9 ]7 U( d8 H" h7 b# y8 H+ @, @
  3.   NVIC_InitTypeDef NVIC_InitStructure;
    7 L8 F8 }: S/ m2 B3 `
  4.   /* 嵌套向量中断控制器组选择 */$ S! E  Y5 \7 [5 U& u
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    , K: m" V5 Q$ B" g  p  @2 u
  6.   /* 配置USART为中断源 */
    4 s- m3 g' D% \% d; X2 e' {2 c
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    , t3 z" K! i5 d3 U: p
  8.   /* 抢断优先级*/  M7 n- ^6 r4 x+ X
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    + ]. }- R1 [7 ~3 O$ ~) l. w( @
  10.   /* 子优先级 */( {7 L$ X" u5 B% ?0 l  Y
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;/ q* F! b) @7 E, y3 e% }
  12.   /* 使能中断 */
    ! e. l3 _5 t% h" }5 E
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    : Y+ ~  n, r: V
  14.   /* 初始化配置NVIC */
    1 W4 U, e' y: d2 G% d
  15.   NVIC_Init(&NVIC_InitStructure);
    9 q& s! O9 `7 R/ ]3 i! W
  16. }
复制代码
二、DMA---直接存储器访问

7 G& i# n( G: B  [, X! {9 N
DAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)5 |( L. C2 Q% }! G$ Q6 {  l0 a
  2. {0 x: d9 t6 y- H3 y
  3.         DMA_InitTypeDef DMA_InitStructure;2 X, e  O% {& S
  4.         // 开启DMA时钟
    7 o* v: n. r& e
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    7 `3 n# V' c$ }: m
  6.         // 设置DMA源地址:串口数据寄存器地址*/  n2 \: t+ k* o" p9 `7 A% D/ O
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;  ]* _# j( r. Y" Q' n
  8.         // 内存地址(要传输的变量的指针)
    7 K4 i7 N4 G, F  K
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    % A7 L6 t2 s& Z; \  ~+ q
  10.         // 方向:从内存到外设        
    0 P! |- \! k' R7 f
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;$ A+ W3 H/ x* T/ J- O
  12.         // 传输大小        0 [! Y1 s: k' Z! `8 y' L% U: ~
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    & j) C1 g1 f- u% x7 a
  14.         // 外设地址不增            
    2 U0 T- Z) {* p& J' j
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;& g& F0 s0 ~& o& K7 @4 P
  16.         // 内存地址自增9 v2 H2 N$ a0 V" C
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    1 y8 Q  q  Y0 ?% O- P8 R' B
  18.         // 外设数据单位        9 u: q" E, l- N+ b. ^
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;+ E$ m4 k+ l- Z0 c7 C5 E: g
  20.         // 内存数据单位
    " y+ F9 j- w- K4 X) q/ z" S
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         
    0 I7 H5 r$ V$ D0 ~. o
  22.         // DMA模式,一次或者循环模式
    7 d, b5 ?3 N, ]% o% \
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
    7 A' p' F4 H6 v; @; a2 @
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
    1 y+ ^- G0 H9 h4 @1 }
  25.         // 优先级:中        4 X& c+ J. x- c$ g
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; : m7 r* H! ?+ \, o
  27.         // 禁止内存到内存的传输: G/ g# w+ N- G2 T6 M& }+ @
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    , d8 N% ~9 J/ v- A7 S8 H
  29.         // 配置DMA通道                   3 y- \3 `( ^/ H* Y& B
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);               
    ( h- C- Z  G: _) V6 G
  31.         // 使能DMA/ Z; Y) n+ K, m+ \8 p9 o
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);1 K- W7 c7 f5 _. x
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
    " [  @& g# }! \% a! }8 t) T6 W
  2. u16 After_filter[M]; //用来存放平均值之后的结果
    6 L2 B: S0 W6 @9 J

  3. * S8 Z( p* m" i& \* S6 {
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
    ' F% Y( M  S$ w% J
  5. static void ADC1_GPIO_Config(void)( ], s- D0 A1 L: S
  6. {5 u0 w1 B- f1 ^: o8 B
  7.         GPIO_InitTypeDef GPIO_InitStructure;
    & f% |! }; r  ~
  8.         
    6 Z! `$ R* I* F& R7 [$ z+ J
  9.         /* Enable DMA clock */2 E, e' F0 v7 B* I+ F8 h% M% w
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    8 P% j5 ^: U3 j  v* _. ?" M! B& }0 E
  11.         $ \3 F0 Z3 d7 e
  12.         /* Enable ADC1 and GPIOC clock */
    . [) g$ ^/ L7 _* v- X4 Q; n
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);+ k) Q/ H5 R2 p8 [; G4 O
  14.         
    7 V" y; z& R/ m. b! s, q3 ^
  15.         //PC 作为模拟通道输入引脚                         1 S' @% Q. }: u' u- k1 e8 M* ]5 U7 @
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    0 A7 p  x' {/ K) [
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                ) _/ r& a# U1 s; _/ ^& M7 p
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        
    2 ]5 `, c0 R, l3 V
  19. }
    + j* m9 ?6 u/ b2 V3 a

  20.   T' u( Z! a( h, x4 N/ r
  21. //配置ADC1的工作模式为DMA模式- A8 J  {+ F8 m
  22. static void ADC1_Mode_Config(void)
    . p$ M( i( G8 J1 G# W
  23. {
    * c9 N. G+ x3 F- `  N1 J
  24.         DMA_InitTypeDef DMA_InitStructure;7 \2 H: z% E! w
  25.         ADC_InitTypeDef ADC_InitStructure;* N# C) \* |& w& P+ |$ B8 g
  26.         7 [/ Z/ n! o5 d) y4 Y
  27.         /* DMA channel1 configuration */3 O2 G$ J$ [6 H; h
  28.         DMA_DeInit(DMA1_Channel1);( Z2 D6 h! ]* q  I# F- ~: n
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
    " j! ^' M) k7 n; O: W4 U- y
  30. 2 _' v: F( T% n. a8 W3 y1 X2 K3 z) N
  31.         //内存地址  
    3 P1 ~( ^% z* H" K- s
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];! z: s7 K0 O* C
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;& x9 }0 C5 I% o( p
  34.         DMA_InitStructure.DMA_BufferSize =M*N;( p" P- ^) Q8 ~7 E0 O7 F: T8 m; B
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    . i( K' f6 \1 r# s1 e+ b
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    / c& K# U/ {7 M8 H  W$ Z% E
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    : z  W7 b8 J- m3 I4 }
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    " n8 _. U1 j/ p
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;+ s1 P6 T2 D& D" n  l
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;3 v7 Q. D4 O$ X; V$ o8 O) q
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;4 ~. q- E8 i6 i' L. T
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);+ _! _) ~# w6 @+ V% v9 e( S' q
  43.         
    + f1 `, }1 n" U. V
  44.         /* Enable DMA channel1 */: O$ `, F! L5 j% w! R  e  g
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);
    ( Y: G& ]; D) U) ]+ |5 w) {
  46.         
    ( p7 w4 \5 T8 f& x1 `
  47.         /* ADC1 configuration */        
    & _# Y# i% X- _
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    : E0 K7 A+ C$ {
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    " s. b& `, h( |/ M& T
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    - V5 |. p% Q( n5 v* S  n: b
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;1 J. S( F# t) S8 W( |
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;! u  p4 e3 x0 x5 r, |" I* t- `
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;
      h$ y5 }) t+ M3 M- H
  54.         ADC_Init(ADC1, &ADC_InitStructure);9 k. N* n1 |9 p- Z6 J! e' T
  55.         . J& O( O# g! d" T8 o
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/
    , }- y! X' L$ L+ ^# j6 L
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8); 7 j$ m5 m5 e% A* x' h4 X; q$ q! d) C
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */ ) S5 O! V. q6 j
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5
    1 |3 `: ^: O7 N
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    ; ?* G$ q: Y1 o7 r4 [8 W) S" K
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    # H$ M7 p# L8 ^& N# a2 E( z1 {
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  
    6 Y: L4 `: R0 d! p; g
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);
    5 z- B- x/ ^5 H! G8 M) R) i% _
  64.         
    9 Y# y: Y8 F  x& s: e- I* v5 }3 y
  65.         /* Enable ADC1 DMA */
    0 {0 e4 k: R4 j9 B0 \
  66.         ADC_DMACmd(ADC1, ENABLE);, l& }$ I- y- H# @# M( k: o
  67.           B, D; E2 e1 z( f& R1 U+ p
  68.         /* Enable ADC1 */6 U- O! J/ r9 [- ~9 G4 }
  69.         ADC_Cmd(ADC1, ENABLE);& Y* F# V0 ?& O- O3 N" p
  70.         
    ; }5 R6 A8 ^  Y3 W9 M" f; ~
  71.         /*复位校准寄存器 */   8 M2 H# o, r, n9 l, P+ W( D
  72.         ADC_ResetCalibration(ADC1);( ?4 c5 H- j0 N* C
  73.         /*等待校准寄存器复位完成*/! j3 C# G6 b: L; h' y0 e6 J- V  P
  74.         while(ADC_GetResetCalibrationStatus(ADC1));
    5 B1 c; G, P# @  Q7 r
  75.         6 I1 @+ Q( s( V/ `: @
  76.         /* ADC校准 */0 X7 P+ z  }$ C
  77.         ADC_StartCalibration(ADC1);0 r. }5 @0 `; G
  78.         /* 等待校准完成*/) e5 ^1 B0 b3 M3 J7 m/ d
  79.         while(ADC_GetCalibrationStatus(ADC1));
    7 B1 c2 f  ^% Y  Q! H4 L. w0 M
  80.         
    4 ~1 H; {2 R" I  e" \
  81.         /* 软件触发ADC转换 */ ) |; [% S( B; v; g7 m
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);" ~; `$ v6 n/ t3 a1 `0 y/ n
  83. }
    ) N5 D6 U+ s& f: h% N
  84. /* ADC1初始化*/
    & d( S% @, Q4 k) R; _$ o7 t( \1 e
  85. void ADC1_Init(void)
    8 l4 Q9 a# H: V+ O3 m: q
  86. {. i8 k. z2 K7 R7 E6 K
  87.         ADC1_GPIO_Config();! g& l! V3 u+ Y7 i
  88.         ADC1_Mode_Config();
    ( O; }! X; u+ y! ^- O1 v5 z; U
  89. }
复制代码
  1. /*ADC滤波*/5 B* g6 y, z. ?7 K( R
  2. u16 MultiDMAGetAdcTest(u8 ch)
    : G/ x. `% S% l$ r+ \1 X  b
  3. {
    3 d$ E9 Q  V& e+ U! f
  4. u8 i;
    # U* |& S! Y* U4 L/ a" a
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
    0 Q2 Y' N, X. Q! G- Q8 [9 _
  6. volatile u32 ADC_Data;
    & b4 w1 x/ ?6 E4 A  ]

  7. $ g- i" @! w$ a0 U( |  s0 y
  8. ADC_Data=0;
    + M' m3 E# D/ r$ ^6 N% Y
  9. % O: F" b8 V8 |# l1 B
  10. AdcMax=0;, F! B& k8 H0 |! |  G9 Y/ `; `
  11. AdcMin=~0;' G% X, K% I# W; O
  12. AdcSum = 0;
    / ?$ i* [/ [* B- z% C2 Q/ T
  13. Adc_temp = 0;7 N# ~6 S: b+ ?& X
  14. 3 K8 G) O7 D- B& e
  15. for(i=0;i<34;i++)% X, {9 h# S2 L: L* N  o
  16. {
    " ~/ {' c8 u, _( |2 ^
  17. Adc_temp =AD_Value[i][ch];
    ; \: R$ O) F# z( |7 c5 G* [  h1 F
  18. if(Adc_temp>AdcMax) ' P  K$ c. o1 f* [* g- [
  19. {7 {$ I5 @7 S3 X
  20. AdcMax=Adc_temp;
    $ Z' E3 Y2 r% d( K1 C+ b5 f
  21. }
    $ V* \8 n) e: f' h& O! p, A6 f
  22. if(Adc_temp<AdcMin)# {, H( z) r  u" T: C
  23. {, }, P: a9 t$ J8 s! P# j8 u
  24. AdcMin=Adc_temp;& R& J& K( s, N+ B2 J. D1 G
  25. }
    2 V0 @/ g9 h! o: W) V5 W
  26. AdcSum+=Adc_temp;/ j5 K% w  o) l3 m+ j
  27. }
    % v2 k8 S1 d* ~
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
    8 a; n* }+ M, q# P3 }- N3 G
  29. After_filter[ch]=(u16)AdcResult;
    ! x3 r0 ?" \% }3 t+ \
  30. return(After_filter[ch]);' R! V  i, t- G/ ^. H1 O
  31. }   \8 ]& y( ~4 B/ E' Y5 }  E
  32. /*获取ADC1通道0的值*/
    # r  ?" J0 j' l( |
  33. uint16_t AD_Leach(void)4 K1 ^* Q  F, W3 Z: F' W
  34. {7 M7 I: s* M) P( |* ~& `
  35. uint16_t adcx1;! R4 \% S% W+ M3 {, k
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);! _  Y/ R3 F- S
  37. return(adcx1);
    ! y" y9 Q# N% J6 w2 W4 z# z
  38. }0 P  ]4 Q, n! y& [9 a) l6 ]
  39. /*获取ADC1通道1的值*/
    * X0 s( a7 Z' m" @! g( ?! u+ I" |# P
  40. uint16_t AD_Leach_1(void)
    , K! e7 C2 U0 G
  41. {( {+ H5 S) W9 v+ P7 A- B
  42. uint16_t adcx2;
    6 o% t# i* B; ^
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
    7 ~" W5 `! ^, {* ^8 V
  44. return(adcx2);
    8 m9 U- I  T& k  O
  45. }; I+ X% |) v8 t$ @
  46. /*获取ADC1通道2的值*/
    ! M3 ^4 j+ [/ M/ x, @. C  d
  47. uint16_t AD_Leach_2(void)8 I6 T9 N* [% @" Z8 w9 n# G
  48. {
    5 m7 B, k% l) O8 @' `9 j; C
  49. uint16_t adcx3;
    6 @- G1 c9 n/ i* J
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);3 c! F7 z7 {6 B6 j- x" s6 J
  51. return(adcx3);% B  s( l0 }1 |0 `3 H; I, Q7 o+ M
  52. }4 Q! A: T7 i0 x# t3 U
  53. /*获取ADC1通道3的值*/! u. `9 r3 ^% J$ A
  54. uint16_t AD_Leach_3(void)
    ! j4 l1 F1 Z7 S0 v  e) X
  55. {
    % d1 @% N% B4 w  y
  56. uint16_t adcx4;2 D6 |% u- M) h6 m; {6 Z' @. ~
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);0 L7 |8 y6 ?9 x' V' k' e
  58. return(adcx4);
    9 _  P+ C8 d+ z; m3 C* L9 N" x0 Q
  59. }
复制代码

6 H, V) G' I- r8 P' R$ d0 p5 A: i' r* Q
目前就学习到这里,后续再写!7 ?4 ^3 z. I* _& l- ?- ~' {/ ~
. c+ J7 i7 @- |0 R7 _7 u* C- N
8 c9 D* k- I7 {' ], {  S  W9 e5 {

, r" v2 D6 y. ~1 h9 h4 d1 g2 A) V( E
赞 收藏 评论3 发布时间:2018-12-12 15:38

举报

3个回答
dianlu89 回答时间:2018-12-12 16:37:21
加油,一起学习
qingfeinglingsa 回答时间:2018-12-12 17:12:34
最近才开始学习
sincomaster 回答时间:2018-12-12 23:54:32
哎,这差距,我才刚点亮一个LED灯

所属标签

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