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

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

[复制链接]
Bowen 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑
+ |# z4 n5 N8 i% X6 l7 Y) q
4 b4 {& A6 \; P2 `# U7 g: x) X
编辑原因:上传代码不全,补齐代码。
( E! H" T4 @, M. s6 T; ~; u0 q
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)
    % M( n; y3 L: |6 l) {9 T5 c
  2. {
    ; H4 u8 l, Z0 j4 L1 b
  3.   NVIC_InitTypeDef NVIC_InitStructure;
    7 t, j& W0 m; e/ f- q
  4.   /* 嵌套向量中断控制器组选择 */
    " @  E! e; q& @0 a+ A- B
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    ) ~. v6 _( H+ v7 e7 y
  6.   /* 配置USART为中断源 */1 j8 e& n$ R- X( |
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    + S6 t) W$ f; [# \( N
  8.   /* 抢断优先级*/
    3 U& M& e) [9 \  e' ?
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;2 ?8 u% J+ M2 \. J( X5 W* v5 M
  10.   /* 子优先级 */
    + {/ J! N! Y/ n" F$ x, {0 F0 Q/ `
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;4 k0 J4 y' _  k# q/ r) N
  12.   /* 使能中断 */4 D+ [/ Y; {# `) ~- m( X
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;% u" x. E  Z. }( u. v* ^; I
  14.   /* 初始化配置NVIC */
    ; c' k* l" a" a9 P. |; E7 G
  15.   NVIC_Init(&NVIC_InitStructure);8 q9 r/ a1 N7 H$ q" ]
  16. }
复制代码
二、DMA---直接存储器访问
& R# }+ a6 }5 {( \
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)
    0 W  B+ C! T' L$ M( D$ n: @3 h( n* m
  2. {
    - n8 Y2 ]- V& C4 I0 D- {1 g  J
  3.         DMA_InitTypeDef DMA_InitStructure;3 G- f" \( r+ f1 l3 W: X
  4.         // 开启DMA时钟/ n8 K  P9 v% H) L
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);- n" K7 Z2 c9 w; O
  6.         // 设置DMA源地址:串口数据寄存器地址*/: y  ]/ a0 q; |9 q1 ~
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;, H/ H' x- r% Z# N
  8.         // 内存地址(要传输的变量的指针)
    ( g/ j, J3 H7 p7 M- f: F
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    " N# d/ ]) P& I3 D4 M5 x9 d
  10.         // 方向:从内存到外设        9 B  U! C0 w2 V8 C- f
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    % U. y9 |: }5 R; W6 P: P1 a% o
  12.         // 传输大小        
    % X7 f8 ?9 U+ F5 I
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;0 [: K- _# M3 P4 d2 m9 ~
  14.         // 外设地址不增            
    ( r, h; t2 I% `, Y- t/ |
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    5 Z( z3 T  _' `6 w
  16.         // 内存地址自增
    " u4 r6 r! H" ?
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    # `6 B' {/ y: O3 C) [+ X& P  A
  18.         // 外设数据单位        
    ; f8 W/ B1 N% N, A
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    # y! g/ B( W% c
  20.         // 内存数据单位
    + \  }5 r4 _. S/ J8 H
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         
    + s' z# \( e, N$ F4 ^
  22.         // DMA模式,一次或者循环模式' u2 L- b2 R0 o3 ~$ X9 ^
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;3 d& U5 s* x- X
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
    4 _0 w, E/ F% [$ T2 V4 M" D) ^
  25.         // 优先级:中        
    4 B5 i" q- E! @- r1 _
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    1 ~* f1 J/ L! [8 S% T6 P- b. Y
  27.         // 禁止内存到内存的传输/ I& |; D! U5 A5 _6 m
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    ! j( J' S; m; A( H1 j* Y
  29.         // 配置DMA通道                  
    , ^" N. P. _; s7 w9 X' b: Q1 ]" ?8 b
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);               
    ) i' `  D. V/ U+ p
  31.         // 使能DMA* d6 ^; f  B5 V
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    ) A. c! y! E% Z- j# Q' w% g$ y
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址( p8 q* o& o8 H; ^+ Y- L
  2. u16 After_filter[M]; //用来存放平均值之后的结果
    * C2 j; i$ K5 `+ s7 M
  3. 3 Q$ ^( e9 c# @' T' {6 E5 e
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
    + o: \/ }% X. M1 L9 p+ q+ s
  5. static void ADC1_GPIO_Config(void)
    1 S0 u& Q( q2 Z- G
  6. {
      ^6 m6 D2 f$ L  ?' a1 a$ D
  7.         GPIO_InitTypeDef GPIO_InitStructure;
    ' b: f2 U! B0 I. p  z
  8.         
    7 x6 A' ]1 p, K, `+ U. V: g
  9.         /* Enable DMA clock */' a  O4 j' ?& w, ~
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);3 L: Q+ a6 i  t& S' }
  11.         
    / P( T  l! z! [, ^. A1 T
  12.         /* Enable ADC1 and GPIOC clock */0 g$ F8 Y* Y" E7 u8 [) ~
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    & \  g( p3 i) g# I9 P# w
  14.         % f. o! ]7 A+ C8 [' J- Q
  15.         //PC 作为模拟通道输入引脚                        
    & a" t! X$ v* o! Q% T
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;0 g2 `5 H! }! x0 Q) H  ?3 J
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;               
    3 G% K+ P3 v( u! L7 R: t  }9 ?
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        ' f0 ~# ~4 F3 f/ N
  19. }
    4 q  {$ U9 s8 D; `: \1 Y. y' l+ e
  20. 2 s  v5 Y" z* A2 \: ?! Q1 S/ l
  21. //配置ADC1的工作模式为DMA模式1 R9 X" ^1 Y; u
  22. static void ADC1_Mode_Config(void)
    # h' g5 H: Z; w* U% I2 q
  23. {
      d  T+ e( G" u
  24.         DMA_InitTypeDef DMA_InitStructure;- B6 J! l- y) c) y+ ^" o
  25.         ADC_InitTypeDef ADC_InitStructure;
    & U9 A# `  k7 y1 j0 c
  26.         
      I% k1 Z* @, m  k
  27.         /* DMA channel1 configuration */
    ) ^3 ~' ~( E% F0 S% h- m6 A
  28.         DMA_DeInit(DMA1_Channel1);, c7 C0 h4 e" T
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;4 L: C8 P! n, o  v

  30. 3 `' W3 P( F+ X1 w2 ?/ G
  31.         //内存地址  
    ) t- g7 l) r1 I, w
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];
    " O1 a6 P) |: W8 E
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    6 l' p$ ]  j2 N2 J8 K5 H* U5 s
  34.         DMA_InitStructure.DMA_BufferSize =M*N;
    9 S& n7 q3 e' W6 t- Q4 [7 C& b+ ]
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;- L7 u& `( X, ]$ l' r% H
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;! x0 g( r4 ?5 a2 f1 t" P
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;9 H# J' G% B) p  ^- E$ w$ C3 e
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    9 ?( E0 P6 x3 B% X
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    9 X$ r+ x. A( O0 Z2 y% u0 q; \
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    + c; v: V& ]' q" g- h
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    # q8 i& U! ]' ], U8 F
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    ) t+ A; u* q' E/ o% c& ?8 ~+ a9 ~
  43.         , }* ], u2 A, s8 }3 N/ m
  44.         /* Enable DMA channel1 */( p3 I! m6 |5 Q4 p. z4 w; P- y
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);; V4 K$ M* v- [$ _8 `. B
  46.         ! s% |# d2 I& Q9 o0 r: _9 J. b0 X
  47.         /* ADC1 configuration */        . q; v( H6 N! T! u
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ! W' `2 ^' }) ]* e* c' t& {7 p% D
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    $ B0 \9 {! E$ p9 H+ X% F: Z
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
      a3 L; b. Z& o' o7 M& H; i
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    & ?. h/ A, [' R7 w% G- [" T, d( v) z
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;* @  N5 d; B: q. w
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;' V" d- s, y+ y1 R$ X0 Y  z  J
  54.         ADC_Init(ADC1, &ADC_InitStructure);
    7 w$ h; ?0 I7 W' Y" q' ^9 t# I
  55.         
    7 |% O7 \" U1 k
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/7 g8 r' B. ~9 z; L
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8); 7 W: V4 _5 l' Q4 n; P  H+ k
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */
    ) v# ^+ ~* u8 E( h# n% K' J
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5
    3 p. G1 U6 j7 W/ ~  ]/ ]( l- ~0 b0 e
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    5 i$ V# |6 C) S9 Z) o
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    / C& A# J/ m: G8 P/ N$ I9 l/ }
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  - {# f: B4 I. m* W  S$ P5 [  m1 v
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);/ O' t9 h+ d5 [$ }+ m$ D% K4 y
  64.         ! b# \  A# O; P% ^
  65.         /* Enable ADC1 DMA */
    7 x5 H, o2 @3 a: M
  66.         ADC_DMACmd(ADC1, ENABLE);
    6 `. e. r- t2 E! Y9 k" y
  67.         
    * q" L6 M: ]- T$ }, `8 l) }" _; {% O
  68.         /* Enable ADC1 */
    0 j8 ~2 _$ r/ ~4 n+ q; V
  69.         ADC_Cmd(ADC1, ENABLE);
    5 S: ?) j/ v& v9 l" H
  70.         ' B1 t7 U; p. k
  71.         /*复位校准寄存器 */   
    ) z" R) O0 @- y; S9 l1 a1 l
  72.         ADC_ResetCalibration(ADC1);
    ! X8 ~& D( E( c
  73.         /*等待校准寄存器复位完成*/
    8 q8 D$ }& `' O6 ]8 W4 c' w
  74.         while(ADC_GetResetCalibrationStatus(ADC1));5 ?8 J% M- C- J! K" M
  75.         . e! n, f0 D1 y7 C/ x, V7 H# ~
  76.         /* ADC校准 */
    8 m& i- _) ^# R. b$ l3 o
  77.         ADC_StartCalibration(ADC1);
    / B5 F4 [. v  J
  78.         /* 等待校准完成*/: d( l. A* q& g# L3 H; j/ d* }
  79.         while(ADC_GetCalibrationStatus(ADC1));
    3 g1 a& b: L% ^  E4 E0 _$ |9 v- q; I! O
  80.         
    & p) C* x7 V6 l% Q& [
  81.         /* 软件触发ADC转换 */ / q( }+ Z' J  u, z
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);8 M/ G! z: \0 z* e  ~: `, M
  83. }9 h, c- H# C( A$ F2 [6 x4 R
  84. /* ADC1初始化*/ $ P7 B8 X- `% L4 q+ N* m8 |6 ~
  85. void ADC1_Init(void)
    : g3 Q2 Y! ?+ _' P1 q1 @
  86. {8 ?! O/ _& V2 b, F+ o2 B& _& R
  87.         ADC1_GPIO_Config();
    * s8 M# r$ M  V3 H% b! w) e
  88.         ADC1_Mode_Config();* |. I7 ]7 _! Y2 P2 R% v+ X) ]6 J
  89. }
复制代码
  1. /*ADC滤波*/
    0 \! X' x# X5 p+ W
  2. u16 MultiDMAGetAdcTest(u8 ch)3 t4 a' Q3 O) M: y3 t' q
  3. {
    9 d# p1 _3 Y: Q* c) o' W; z
  4. u8 i;
    0 T0 q2 j* U2 A2 u) C7 }  z
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;! H& f' x, ^7 B. [
  6. volatile u32 ADC_Data;
    ' O3 r; @$ L" U# }( o5 Y$ d
  7. ' W$ i! \; w* \3 \. q# N
  8. ADC_Data=0;
    & i" \9 F4 }) b: O  U
  9. 3 s. S% b: r- h
  10. AdcMax=0;) ?* V* k+ h7 [" J9 H) V: Q
  11. AdcMin=~0;) e- o; g1 M! R1 h0 t% I. f
  12. AdcSum = 0;
    ; E- E+ m4 }$ e1 ^% a+ O0 x. t! _! A$ F
  13. Adc_temp = 0;
    ! k- w- b" Y* d; ^) J2 C

  14. ! Z' Q0 q* e# ^% W( h3 g
  15. for(i=0;i<34;i++)- x4 l) y( y7 G
  16. {6 o( e- f" x2 l# F. ?7 W1 ]
  17. Adc_temp =AD_Value[i][ch];; n) t7 N6 m8 L+ X& W
  18. if(Adc_temp>AdcMax) $ s& @0 s0 i$ i0 ]/ R  O( ~
  19. {. n! J& c9 [" `. M& H! s  F  |
  20. AdcMax=Adc_temp;
    % ?) @- ?( @, y9 ~0 z6 ~) K
  21. }
    + s, H$ p$ `0 Q2 r' w
  22. if(Adc_temp<AdcMin)) Y9 S& v" S' F) p
  23. {
    9 v, t* Z! B- k! g' y8 S2 O" k4 M
  24. AdcMin=Adc_temp;. B6 b# A" t4 |* x
  25. }
    $ V: I" g& u8 ]6 C
  26. AdcSum+=Adc_temp;5 R( b& v5 E( ~4 R, c6 t
  27. }
    " K4 w) D3 z" ~9 o! R2 [6 {7 x
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;' O8 j% a& v2 |( a% i$ L0 S6 `' \" v
  29. After_filter[ch]=(u16)AdcResult;
    9 a4 ]% M' E, m9 J7 ^$ ?7 K
  30. return(After_filter[ch]);
    ' v: d4 Y% @; T
  31. }
    8 r4 Z9 @  k6 F
  32. /*获取ADC1通道0的值*/7 A3 R; g( s9 d! E% Z
  33. uint16_t AD_Leach(void), H: \2 ^) n5 ~2 p
  34. {
    / y5 }& U* g/ l0 W  U$ m9 }
  35. uint16_t adcx1;
    5 U& K6 J4 v/ R2 t. B
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);5 R, ?, P9 p5 O8 H; h! Q/ |9 d
  37. return(adcx1);) |# t: J8 G% v: z- `. |
  38. }
    1 y0 v( a9 j9 f/ P( \/ K) {
  39. /*获取ADC1通道1的值*/
    0 F7 x% o, ^) v' Y: h" y) m2 V
  40. uint16_t AD_Leach_1(void)
    7 S9 ]% J1 W: r4 _
  41. {  f9 M- @6 O+ b7 T- w% M) e+ n
  42. uint16_t adcx2;
    ! z- f% Q" K5 V- ]7 Z
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);: I: x' O3 z. {8 B. m
  44. return(adcx2);/ j/ Y9 e3 B; F$ g8 `2 n8 P
  45. }
    & k4 k: ?* V3 X0 L
  46. /*获取ADC1通道2的值*/
    & z% l( ]! }9 Y3 ^& k
  47. uint16_t AD_Leach_2(void)/ K8 a* R4 @- w) j3 D; D
  48. {! b8 U8 k  Y) Z* B6 H- |, y
  49. uint16_t adcx3;
    1 c; q* F* n5 j4 _8 D1 n3 H
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);6 |/ ^# P" Q$ A- W) P3 L+ D1 i
  51. return(adcx3);- _9 t  Q% ~, b9 S/ s& h$ j. i
  52. }* N' {/ O1 {% V! E" _0 f
  53. /*获取ADC1通道3的值*/& y% A3 C) Y9 a
  54. uint16_t AD_Leach_3(void)  {7 }6 i0 J" n/ R$ C. \# o' i
  55. {. _% f. q7 W4 r+ |$ s( S
  56. uint16_t adcx4;8 n3 Q1 V+ O" o' G  H
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
    : f* G% D8 j, Z& d
  58. return(adcx4);/ g& r. B) w- @/ |* z
  59. }
复制代码

8 H* K9 O" H6 D% A7 {
0 S' s6 h8 g, J' e3 M2 n目前就学习到这里,后续再写!6 n! E' Y. D# c( ?, ]2 R8 G# v
$ V9 O! T' W' K2 n

$ l' T* i& F+ b& p$ a
/ g- T, f( E: n9 H! ~
收藏 评论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 手机版