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

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

[复制链接]
Bowen 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑 7 Y( c4 B' B) Y" Z

9 z6 M; b0 d3 q0 a0 D: q* M" t4 |
编辑原因:上传代码不全,补齐代码。
1 C( Y' N' h( [. L4 E* T
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void), m& ^; ]( S7 V
  2. {
    ! E/ I$ l( k  l2 u; J' J+ }
  3.   NVIC_InitTypeDef NVIC_InitStructure;  T* \5 |, H  e
  4.   /* 嵌套向量中断控制器组选择 */
    6 I- B% P! P' [/ m* J( P/ M
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);! F2 m$ i, G" }" d! [6 B
  6.   /* 配置USART为中断源 */, g8 o  o, u1 m; w( }
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;/ \4 \# m/ O, m1 ^9 y' Q( H, M
  8.   /* 抢断优先级*/
    ) O( O  {5 c. E
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    + P* g' ]. G9 F" i- S1 S
  10.   /* 子优先级 */
    6 c1 l" [- Y4 q! \. }2 I' U: w
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;( z% Q7 f4 Z9 X4 q7 R5 @
  12.   /* 使能中断 */
    / Q6 p! [* @0 W3 M+ e. e
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    4 @8 O  Y5 y2 R) |
  14.   /* 初始化配置NVIC */
    ' R  i1 K/ J/ `1 e4 M! H1 L
  15.   NVIC_Init(&NVIC_InitStructure);
    ! Z( j; J, t4 T) ?# ]* X' X( i3 X" ~
  16. }
复制代码
二、DMA---直接存储器访问

# L& T  U3 m3 L( h4 s
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)( ]" E, `3 B0 k# H* V3 t
  2. {5 G3 G; e2 n. P! \- A$ j
  3.         DMA_InitTypeDef DMA_InitStructure;9 n. `6 {6 Z4 t: e; T1 B
  4.         // 开启DMA时钟; S, c  h  |/ p  |: ^8 Y
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);) G6 Z2 i" g/ E0 j
  6.         // 设置DMA源地址:串口数据寄存器地址*/
      ]! y6 Z  m' P( n. R9 ?
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;0 u3 [, l2 M% G  Q' [) n
  8.         // 内存地址(要传输的变量的指针)
    6 o; n( ]% p7 G9 r% q0 s4 [
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    1 y. P9 y( [" [
  10.         // 方向:从内存到外设        
    2 E' n: D* M' B3 L/ [
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    8 A: x7 D% F; s
  12.         // 传输大小        8 A+ ]. }; N! J) D% {8 H
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    5 b1 F9 Q% o. N) n( [# u" h
  14.         // 外设地址不增            
    % s" H; c- t8 T2 o/ S  a
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;; P* s  K2 p" k/ x: r4 K  z
  16.         // 内存地址自增5 b; R$ P5 ?' @2 ^4 s* h3 Y, ?
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    & I, c# K8 h0 R! F5 m
  18.         // 外设数据单位        
    1 s2 D7 w& \. r
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;6 v% v! U1 ^" z* E( c
  20.         // 内存数据单位
    " c/ Z2 ?7 G) k7 D6 c/ _0 q' }/ I: I
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;           k$ ^& M  N: u, s
  22.         // DMA模式,一次或者循环模式2 d2 T' \! p' ^# q, O9 Z6 }
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;- v7 y8 g& h9 ?- Z7 C+ G, b2 `1 h" F' }
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        * q) c4 e' n- u$ p% A3 E7 E
  25.         // 优先级:中        9 T2 d8 r  X# m, }6 d0 u) @
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    . @" E. [/ b; P' V
  27.         // 禁止内存到内存的传输& ~# ]) `1 _1 d. p+ |' c% o! D. ~
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;& y) |4 s1 ?5 ^( S! k# K0 q! y2 P
  29.         // 配置DMA通道                  
    6 {2 B$ t8 O; D1 j
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);                3 D: e/ A  d6 J- M2 D
  31.         // 使能DMA
    / m0 I! |: I/ w2 ]. @4 r
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    - f8 j' X0 b- X/ _
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址$ U+ ~/ p8 c/ K6 L
  2. u16 After_filter[M]; //用来存放平均值之后的结果  C1 [/ B5 L% @- O
  3. ( F7 s) `2 g! s$ ?; ?& N
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口9 E# |* x! k3 F4 f# u
  5. static void ADC1_GPIO_Config(void)/ f8 a: _- U7 ]* B9 M
  6. {5 p2 r6 p6 v6 j9 e5 o
  7.         GPIO_InitTypeDef GPIO_InitStructure;# o+ T2 `4 K' }+ Q+ y
  8.         
    $ q/ s' Y3 e7 [
  9.         /* Enable DMA clock */, `6 O6 _" p) K9 r3 u3 b* b
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    . i5 E$ _# o4 B! N; L3 ?
  11.         
    % h8 o+ O0 j# ?; j  `
  12.         /* Enable ADC1 and GPIOC clock */# P8 i1 Q9 q2 ^5 I. c3 p
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    ! i7 y7 W5 u) B2 ?8 \9 B% O
  14.         
    ) @9 B* I; _0 x% y7 |
  15.         //PC 作为模拟通道输入引脚                        
    . n( u, G7 ]  ?- y! n0 W' z
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    8 ~$ d8 C  L/ J/ s/ W" o7 s
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;               
      L% s* K" _1 U
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        
    & h4 A. \6 m( k6 M* i" l2 e. G
  19. }1 J4 a3 A  g( c. Z

  20. . r% x9 {3 M. c: k6 s0 Q# I
  21. //配置ADC1的工作模式为DMA模式2 G1 v3 |( v) c& Y- {0 z/ Y
  22. static void ADC1_Mode_Config(void)5 R7 s# Z( f! L0 R: L, F6 Z
  23. {
      ^$ ?9 N+ K/ H  J
  24.         DMA_InitTypeDef DMA_InitStructure;) u) N& i& `' F
  25.         ADC_InitTypeDef ADC_InitStructure;0 n: [( J; I, c
  26.         
    6 l; [9 ^! }3 S' f( Y: _
  27.         /* DMA channel1 configuration */
    $ e. }# m/ v. Q5 t, T1 _
  28.         DMA_DeInit(DMA1_Channel1);1 u" l: V# ~! Q5 ^$ [# m. h8 ]* x2 W
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;* A& @$ X5 g$ \. P% T1 J5 E

  30. 6 h# d! ^2 v; e6 X! S/ g# J
  31.         //内存地址  7 ?/ C+ V0 E( p
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];6 o% z/ i7 j3 b/ U9 Q
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    2 ]" s1 ?6 y3 C4 N
  34.         DMA_InitStructure.DMA_BufferSize =M*N;
    * `! k& f) X4 ]/ C
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    ' ~6 i( W3 T9 }$ `0 w& {& ^
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;6 D$ `4 g: h4 d  T
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;/ i& B5 S% Z0 B8 j, m
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;! N4 P1 {" \3 r, w8 v
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    8 D4 @; |  I( J  A0 n( O
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;( y. i) y# ~( v  I! F
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    - \0 m  C; m" Q; {
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    2 h3 S7 K4 k1 l! c
  43.         6 m2 H% R( [9 Y# z3 E; B$ l/ S
  44.         /* Enable DMA channel1 */) z9 C  Q* m5 K! O2 Y# t: D: ^
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);( u. g6 Q6 i( k8 e5 w: F3 s+ x
  46.         " ?9 j; |5 w7 r, U
  47.         /* ADC1 configuration */        
    9 ^3 X0 o; I( l4 @7 V
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;' B& K7 p1 K. I1 Y. n9 b
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;( C- Z+ A( S1 _
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    # x9 i1 N& u- L7 N; `
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;6 Y7 h! U6 s. a+ M/ s. i/ L4 B
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ! i' z: I3 m- I$ E) H9 X- m
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;% m* W' q% L" p$ j$ d0 P! c' |
  54.         ADC_Init(ADC1, &ADC_InitStructure);# a' V" `9 \% }6 i; F8 X" V% m6 |
  55.         . L: |9 |5 @- U. k( J# T6 @
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/
    : K+ j- P% P, Q
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8); & I6 e* O; h+ o' j0 X. m
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */ : ]  ]; i- j3 F* [  j9 o  W+ h
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5" j) M' d( d! D- K9 Q. {
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    2 _- L: M9 Q! e5 t, G
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    - R  c+ n6 ^2 b9 |# f4 C
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  
    ) v# d2 V1 @' y- a: B! G0 m
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);, Y/ w" q0 o/ Y3 O
  64.         
    * h# J, n. O% S# h" A  ?
  65.         /* Enable ADC1 DMA */
    6 Y8 N2 t2 ^! N, T
  66.         ADC_DMACmd(ADC1, ENABLE);
    " t& z. v1 c7 I
  67.         4 H- p7 h) C4 b" W  o( @- H; e
  68.         /* Enable ADC1 */
    , y/ O" t$ u5 s* i/ Z
  69.         ADC_Cmd(ADC1, ENABLE);/ z) p0 O5 W: d9 }- O! P6 n
  70.         " V: O$ l9 u. i3 q6 N
  71.         /*复位校准寄存器 */   2 E" i9 E$ q9 ^5 F% j+ V5 Z8 v
  72.         ADC_ResetCalibration(ADC1);
    ; w# h# _0 z0 q$ f
  73.         /*等待校准寄存器复位完成*/$ P0 R/ E' x2 N+ {; s! ^9 K. g
  74.         while(ADC_GetResetCalibrationStatus(ADC1));7 C) K# K: v; Z7 h6 T# @
  75.           g! V+ e# P3 r4 c$ t7 a
  76.         /* ADC校准 */
    3 i' f3 L2 L9 V+ V5 O  p& H2 c  T
  77.         ADC_StartCalibration(ADC1);
    ) S$ e7 ]& x, O! z" K
  78.         /* 等待校准完成*/
    5 e# ?9 ^) h+ m) j% v; P8 S% Q' K4 s
  79.         while(ADC_GetCalibrationStatus(ADC1));
    ( [2 Y0 _) l% e- Z, b) u
  80.         + l: r& z" N  R. F
  81.         /* 软件触发ADC转换 */ 5 P" g  O! r9 v# d, ?1 E
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);
      U3 @! e6 \6 E5 u5 t
  83. }
    ' C2 l2 ]$ A, d3 G0 q: n
  84. /* ADC1初始化*/
    % w' q4 l4 G. E2 q1 |! `, w1 G
  85. void ADC1_Init(void)
    1 u/ h, N- `- r, V  w. l6 R( w
  86. {2 G+ |) `$ T" c- w; `7 O# T
  87.         ADC1_GPIO_Config();
    5 G' m6 o/ b( ?& ?+ I
  88.         ADC1_Mode_Config();1 _: X3 e# N/ o: G
  89. }
复制代码
  1. /*ADC滤波*/3 K3 U. t, b# j
  2. u16 MultiDMAGetAdcTest(u8 ch)
    0 ]+ J1 A8 e: ]: ]- ~' e. x  x
  3. {
    & R" H1 j; Q% P- l: V1 E! s
  4. u8 i;
      w; E9 w( Q/ c  A3 j
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;# I7 S3 T* _: @* a! N7 C) S7 \6 ~& D
  6. volatile u32 ADC_Data;8 }6 O$ z4 t4 G5 O- I7 L/ B
  7.   i9 C/ N/ J+ ~: l7 Z! b, S1 y( K
  8. ADC_Data=0;
    ' a) W# }$ V8 C4 y2 B2 }
  9. , F+ q. n' B7 F, |5 {, B0 F3 v  a: V' H
  10. AdcMax=0;) [$ v+ h. G  n# X1 m. z- f# X) ~
  11. AdcMin=~0;
    7 x" O$ v9 e5 {" y, ]7 w# Z
  12. AdcSum = 0;
    7 H$ y& M1 ~* d: Z" P6 z
  13. Adc_temp = 0;; n1 E" ~7 C) N& j/ s6 a! f
  14. - t0 M9 E6 X& d( j
  15. for(i=0;i<34;i++)! k9 s* h% v2 [8 B! [; @( r
  16. {
    & H' Y3 F' w  ^
  17. Adc_temp =AD_Value[i][ch];
    & a% w9 ~' G  K! w& N* d2 W
  18. if(Adc_temp>AdcMax)
    % A' I7 z+ h. _, F9 |6 F
  19. {7 x  {: y9 \0 L
  20. AdcMax=Adc_temp;; t2 `  o; W+ T3 L
  21. }
    7 c/ c" ~) z0 P8 j2 n
  22. if(Adc_temp<AdcMin)
    8 @3 Z* \8 i1 m- j" e# w
  23. {
    . U& y% r- Z  _( Y7 o5 O. o  s  j
  24. AdcMin=Adc_temp;# z) g# ~7 R: O! O% g
  25. }4 p( L/ C4 a3 I
  26. AdcSum+=Adc_temp;
    ) h7 n9 I" Z! r, c" B1 I& U: Z% R. ]
  27. }2 t# k- b( W* p. B8 h2 j
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
    2 `( p( f# n4 M8 L5 j+ R3 b6 [
  29. After_filter[ch]=(u16)AdcResult;( g% R" B. x: G/ T' F
  30. return(After_filter[ch]);
    & X9 e/ \7 [# j
  31. } ! x$ X+ u: H0 s" L9 q# R) T
  32. /*获取ADC1通道0的值*/; k5 O/ |6 `/ E% Y3 x3 `  q
  33. uint16_t AD_Leach(void)1 i8 f$ d) A8 @, F, @: b% _
  34. {; R) N9 y  I- C# x5 Q
  35. uint16_t adcx1;  ?$ h& Q* a+ ]! H0 e
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);1 n. J7 S8 {9 s( b: v7 c
  37. return(adcx1);
    2 \- M$ u! ?5 ~, o& o) s) y9 h9 `* J  Q
  38. }3 W$ k7 S6 Q0 u4 Y0 X) x; X
  39. /*获取ADC1通道1的值*/
    - Z: ^% O- N# w- J) l' U' @
  40. uint16_t AD_Leach_1(void)' `' |1 ~; R4 u2 J- u
  41. {4 {+ W' L, d+ I; x$ y0 K, l
  42. uint16_t adcx2;
    4 }5 o6 H) m/ c9 V
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
    % ?6 E& r3 z* g8 K; N2 R! A! K
  44. return(adcx2);
    0 N) `. R3 }- [6 N; s% t- j
  45. }
    * r! L! Z" ], O- ^, G* J
  46. /*获取ADC1通道2的值*/  j; `% F  f- v) D
  47. uint16_t AD_Leach_2(void)
    # s/ g4 {' e( R
  48. {; F* C$ T: |: {% {5 {  d
  49. uint16_t adcx3;  a0 ]( ?5 j6 ^8 ~" [4 ]- J, R6 A
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    6 X. I# @0 C$ v, G- \3 W9 W5 k/ Q
  51. return(adcx3);
    3 f2 s; B' Y: ]( ~2 B4 u
  52. }
    $ a- x; g* ]5 b0 M. x7 O0 V
  53. /*获取ADC1通道3的值*/
      b1 n" y$ G& I, |4 o
  54. uint16_t AD_Leach_3(void)6 D, M# P% ?! y+ m0 q; e& v) ~
  55. {
    ) c% X% C4 j: R, Y. X" D5 z
  56. uint16_t adcx4;
    8 X2 b1 c6 Q  j0 H/ o" A
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
    9 L) v/ I  A# a% Z1 P
  58. return(adcx4);: Z4 R, v: ^# k; \! Y) q: M
  59. }
复制代码
5 p" n. P6 t, r
& u3 R. Z6 j$ |5 U  H3 ~4 z/ Q
目前就学习到这里,后续再写!" b+ L; S/ V- @5 V& B# t

* |5 g; b" N; o  p; s0 S( _
5 @- ]! S+ `. e4 O) z/ n: U& F( b( _( [7 T
收藏 评论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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版