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

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

[复制链接]
Bowen1028 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑
" S* X+ N! C9 W) A9 ?; N  f9 T6 ?
编辑原因:上传代码不全,补齐代码。

2 L, e( n3 _/ E. D' G
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)
    9 O  v% P" S7 E# `6 K% M
  2. {
    7 z1 o, P5 ~5 ?0 ?
  3.   NVIC_InitTypeDef NVIC_InitStructure;- G7 [+ b1 ~  R: L4 T2 c! p
  4.   /* 嵌套向量中断控制器组选择 */
    2 M- l7 R6 j+ `4 s+ s5 p
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);) f0 T+ X. \/ `
  6.   /* 配置USART为中断源 */) Y/ J2 C1 t, y! q
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;& O8 H2 `1 U9 Z+ g) y3 q9 Q" e
  8.   /* 抢断优先级*/+ G/ j$ |% h  ~2 E
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    2 h2 T0 T+ }5 B  _8 {/ n
  10.   /* 子优先级 */4 k' W) g6 x2 g/ R0 }' M
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;3 e: m4 e/ r7 W, U8 ^
  12.   /* 使能中断 */% V7 S" u5 H' h7 R3 m1 Q
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;1 B# S9 h- |- A" w8 l
  14.   /* 初始化配置NVIC */
    ( v1 W% p& [  h# s3 D& ?, ^
  15.   NVIC_Init(&NVIC_InitStructure);
    4 ?3 w; i8 @$ O: z/ B+ T
  16. }
复制代码
二、DMA---直接存储器访问
9 Y; A) _- W. Z# }
DAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)
    / e$ U( _0 i0 T8 G9 w, K8 s
  2. {0 [- q) x2 I3 p: C
  3.         DMA_InitTypeDef DMA_InitStructure;9 u) F3 V2 x/ B4 A/ |& A
  4.         // 开启DMA时钟1 T6 @8 G; q4 @- ^" [6 @1 e3 J
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/ T3 f( o* v. t5 i. Q& I
  6.         // 设置DMA源地址:串口数据寄存器地址*/
    0 z, G/ o/ j( b0 Z- R7 w/ \
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;  P. B' a  _. ?. m# x
  8.         // 内存地址(要传输的变量的指针)3 ~3 Z/ U% F- m/ B% ]
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    6 w4 F1 I+ e. I, A
  10.         // 方向:从内存到外设        
      u" `; r2 D8 W, ^8 h
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    8 @5 {; K- T: l) k# [0 H) o
  12.         // 传输大小        
    " w( N% F: }/ }; v3 n
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    + b5 |" @) [' X1 j% E
  14.         // 外设地址不增            ! q  \; A+ k. g0 @% V
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    4 C3 B* M& J: d1 N- ~$ H
  16.         // 内存地址自增+ _: T. L" \/ h+ `# B' r5 B
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    % K8 N8 ]* I+ A7 Y
  18.         // 外设数据单位        
    $ u0 j: M2 L9 s! ?  _: A9 ?; v* E6 E
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    ( ?) p) d; G2 f" `/ J& t# ?
  20.         // 内存数据单位
    9 ]$ j3 _& d" \( V9 n5 S
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         ) g5 {1 C% T3 o$ \: I
  22.         // DMA模式,一次或者循环模式
    ! p& {  }5 I' q1 e( m9 w
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;* C4 X+ [* T4 \/ A) [- A
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
    * }- P1 C6 U; ~: g- I
  25.         // 优先级:中        
    ) v8 q! o# _2 {' ]4 k! L
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    + _! @, [" d8 `: E/ B8 r9 F
  27.         // 禁止内存到内存的传输
    ) F9 t- t& T0 H* ?; o7 L- V5 k+ R
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;; g% s' a& r/ V  U  d4 q/ C
  29.         // 配置DMA通道                   ' P4 Y8 N$ W  R0 J
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);                ' G! _) _: [) W
  31.         // 使能DMA" p9 l$ \3 x: r+ A/ r8 D2 Q+ N
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    0 n8 i6 S/ z4 d
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
    9 W9 f% {9 {( ?4 N
  2. u16 After_filter[M]; //用来存放平均值之后的结果+ @  m5 O2 y0 s6 y9 P0 `

  3. - P6 }% H0 P. }4 I' q6 {. s
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口8 g' k+ w& k( t% Q$ }
  5. static void ADC1_GPIO_Config(void)
    ( z3 a% Q% M" ?  Y! o3 s7 Y( b7 G
  6. {
    3 P) d5 C; A4 z- C. A+ x8 b
  7.         GPIO_InitTypeDef GPIO_InitStructure;/ f: y& r, k, ?# n0 I' c
  8.         2 s8 j9 u5 V' m0 R& N
  9.         /* Enable DMA clock */
    9 Z3 Z" o, k8 x" ?+ g
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);, i5 e; Y3 p) [: v% z0 b
  11.         
    9 U, |9 P( P: u* j  E' ^+ u* a
  12.         /* Enable ADC1 and GPIOC clock */7 M. z9 s' h1 h1 p* F8 |5 `% c
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);" z* E. d1 s3 Y6 X( r% k; m
  14.         ; O8 m2 Z5 L: U& \6 h5 }
  15.         //PC 作为模拟通道输入引脚                         " [9 h  A/ }0 P& r4 G" c! i' J9 F
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    # |% _6 D) I2 `) J) R6 O# i
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                , _' F: ]2 k5 ^2 P1 B
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        & w, F' Z1 Z7 C3 e. k
  19. }( ]# V( u0 i  b& L( y7 R

  20. + P) n3 x: M6 M3 \/ X( [: W9 ^3 |8 z
  21. //配置ADC1的工作模式为DMA模式
    % M% @' A" \7 e, r* @5 o
  22. static void ADC1_Mode_Config(void)1 h* d& |8 y$ h9 v$ t# C
  23. {, Q" J% T/ `* V) Q. q
  24.         DMA_InitTypeDef DMA_InitStructure;/ W6 Y$ T& b2 G7 e
  25.         ADC_InitTypeDef ADC_InitStructure;1 T: z9 |1 |( j( W
  26.         
    ; q' A; l7 m, ]  J) ~0 l5 J6 l- k5 ^
  27.         /* DMA channel1 configuration */; e5 K9 C8 c' B/ u
  28.         DMA_DeInit(DMA1_Channel1);
    / k9 ]1 X( G9 J8 N# u) V7 M
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
    5 I$ X4 Z* Q' m! q7 s- f4 z9 W
  30. 5 p0 t- P0 U  [: q5 [8 Z7 W
  31.         //内存地址  - i9 W6 I: T; V) A2 K0 D
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];, I; }! W2 F, k. M
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    5 U+ Q) s% p2 M; i5 F
  34.         DMA_InitStructure.DMA_BufferSize =M*N;; W4 P( _. b2 d; |
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    $ l( k) V. P- K2 {8 W- x5 p
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    $ B5 Q& }" t$ n8 u! X- l& y
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;/ |+ M4 C/ z7 j  e- X
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;( N) d3 Q8 V8 n/ k7 U! c
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;! [" C2 W6 r" |1 \6 G: q
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    9 c1 X/ ~( C3 ]/ T1 d
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;* c, t! K& i# F& x
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    $ O$ A9 R: d6 X( `, W: a9 K
  43.         
    , J0 ^1 R& b- Q' [3 M
  44.         /* Enable DMA channel1 */
    : N( S) I7 K. S
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);8 t$ p. i  `$ E. q
  46.         ' {* y% R1 A, i& J- M
  47.         /* ADC1 configuration */        : F( e5 {4 }) l6 z9 u
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;8 J0 B; y  A2 m3 w
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ; T& A9 ?- R6 a/ N7 _
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;6 F+ ^8 g( w# r7 F* s- s* V5 J5 F
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;3 e: v5 S3 @1 w
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;2 x# J0 {3 O6 [$ ^$ A' w
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;
    3 ?) r- d4 c/ C; C& w( T
  54.         ADC_Init(ADC1, &ADC_InitStructure);) Q8 |6 c/ e' T9 E; O1 k3 f. C
  55.         ) ], A1 `' f2 O, o+ C
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/
    7 j) l7 }5 A7 b( G# r
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8); 9 J( R& w5 R& @2 e# j( M
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */
    1 [0 n# Z, M( I- i  u$ P8 b  |
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5& u1 k1 T2 |0 ^4 }- n- u; d, Y- S
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);1 l% f: [7 u: Y+ }2 B; l
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);" U5 s$ w3 Q' l2 G& g! c/ l
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  
    # p' p4 _0 _3 c7 p& l+ y9 N/ z
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);# A4 P/ b$ k% z" k% Q5 P: u# G2 U( V
  64.           E( S( ^) g2 I' ?  |9 e. a
  65.         /* Enable ADC1 DMA */9 R& |/ p  i, r* F2 u- R7 \
  66.         ADC_DMACmd(ADC1, ENABLE);
      t! l. h2 M- V) c( Y7 U
  67.         
    ) G5 m: |9 C8 R- m
  68.         /* Enable ADC1 */
    $ @  _" o+ n! o! V) N( B8 ?
  69.         ADC_Cmd(ADC1, ENABLE);! H' t) a: I& W% D
  70.         
    - J  Q+ y. u9 P: w9 Y
  71.         /*复位校准寄存器 */   
    $ I: x" D/ J% p' U- F$ [; v% D8 z
  72.         ADC_ResetCalibration(ADC1);9 a& m( m: F: f( l# E, [
  73.         /*等待校准寄存器复位完成*/2 C/ }- Z6 K: k
  74.         while(ADC_GetResetCalibrationStatus(ADC1));
    $ Q! e% A1 c8 l+ V) P
  75.           G) W5 n$ f; o7 l+ B1 r: D
  76.         /* ADC校准 */
    ' S/ R3 @+ w3 m/ _+ L6 ]
  77.         ADC_StartCalibration(ADC1);
    3 Y9 E- P3 o* R' b5 Y
  78.         /* 等待校准完成*/
    . V8 `( G( H0 S* [3 K+ ?* g; Z
  79.         while(ADC_GetCalibrationStatus(ADC1));( Z2 S: w+ A$ B% Q4 K
  80.         
    * I: k7 w0 A1 A& ?' _
  81.         /* 软件触发ADC转换 */ ; U' u" G, N9 P: [! V
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);- X5 ?: a# w# @* a# `5 w
  83. }
    ' V5 P' W( R5 E$ r- T# l
  84. /* ADC1初始化*/ 9 w0 d1 a0 |: _- Y2 u4 e
  85. void ADC1_Init(void)
    ! ]' S0 z) i0 m! n- J/ g
  86. {* k/ c4 ~7 Q  r% n  N$ B9 t
  87.         ADC1_GPIO_Config();% F  Q4 ~, d* d
  88.         ADC1_Mode_Config();
    4 {  C2 G  S/ ^; a
  89. }
复制代码
  1. /*ADC滤波*/) h6 v8 N9 R) q. Z( ^
  2. u16 MultiDMAGetAdcTest(u8 ch)
    * F/ x, i7 L* f& b& x
  3. {9 A) N0 X5 w6 Y# s& m
  4. u8 i;* a: w3 r+ `' M5 y' I5 n
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
    6 C( I8 S9 c" S' x
  6. volatile u32 ADC_Data;
    9 B' ^+ @, X- Z
  7. 8 b# B" k  F2 a# x" q# k: a2 Q
  8. ADC_Data=0;
    $ T8 s% z0 t$ s6 e
  9. ! g; c( n0 I8 G- Z' V/ C0 n
  10. AdcMax=0;: f4 X( ~/ j, x  p" Q6 P
  11. AdcMin=~0;
    3 X; ~9 H, B* y3 u6 b, K6 j
  12. AdcSum = 0;
      i3 L% V- p# l* F! D5 W; @
  13. Adc_temp = 0;) x2 V1 d) [& i  n) b6 y2 J

  14. & b, N. R4 r2 Z& v$ L
  15. for(i=0;i<34;i++)
    " Z& X, T9 m. b
  16. {
    " Y, G) ]+ J' X# P  n/ G
  17. Adc_temp =AD_Value[i][ch];/ y% n% z1 Y3 I. x
  18. if(Adc_temp>AdcMax)
    & c9 c/ L  o. G2 c1 f+ v
  19. {
    8 D8 K& T, z: q! z' [+ E
  20. AdcMax=Adc_temp;
    $ ^) r+ u" y8 o- t* v# V- C- E
  21. }
    8 f- y/ N: R# h2 P5 c1 }
  22. if(Adc_temp<AdcMin)
    + S6 e/ z5 y/ m% g" H/ O
  23. {
    . [$ l9 q& N! u2 e) \/ P1 D9 ~8 s
  24. AdcMin=Adc_temp;
    % m/ y: a3 _7 k& Y* F# z6 d8 B
  25. }. ?2 A- T- ~! e" Z8 u, j+ x% D
  26. AdcSum+=Adc_temp;6 V# B; l! i. {8 y% F, ~3 M. O
  27. }
    3 i! O4 W3 M1 V0 o( Q
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
    4 t' L! T: z0 A' M6 k6 @
  29. After_filter[ch]=(u16)AdcResult;+ u( i% I! x9 \; D) j
  30. return(After_filter[ch]);' s1 y: s6 ?, H
  31. }
    : h0 ~2 {/ I# e, [1 v7 y. w
  32. /*获取ADC1通道0的值*/9 ~6 m! ]- ]; I- w. O# t( `
  33. uint16_t AD_Leach(void)
    1 C0 M4 o6 S. k( ]
  34. {
    - D" k; t  I3 n9 x
  35. uint16_t adcx1;/ b7 T% p" p6 y8 u( F6 h
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);  i7 Z( i. }) R' x5 n( }- Y' C! W& M5 x0 b
  37. return(adcx1);# q( Z) T/ D% @4 Z6 n. c
  38. }0 b: w4 K9 Z; `+ s  n; J. S
  39. /*获取ADC1通道1的值*/3 C7 b6 ?4 r) A7 t) g! E
  40. uint16_t AD_Leach_1(void)
    , q+ Y. W, p( {+ ?2 _6 d1 b6 z' x4 u
  41. {+ D7 U+ ]- `  Y- b4 W3 E
  42. uint16_t adcx2;- P/ R) V8 l  e6 Z! w! g
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
      l- [6 X% a4 q, X
  44. return(adcx2);8 k1 B) w! J3 t9 k$ B
  45. }. b7 M% I- j3 h% @$ Q/ j8 t0 |# W8 \9 C
  46. /*获取ADC1通道2的值*/  T, q- o+ q7 [4 S& e
  47. uint16_t AD_Leach_2(void)/ D4 U" [6 R! R2 E9 d
  48. {/ M! E2 h" Y* V" X6 ^+ i# n4 \
  49. uint16_t adcx3;
    + K- N8 S) m. A+ d3 Q, H) }
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    $ W* Z; `8 u) s) G+ I* t
  51. return(adcx3);0 w0 x: \! M6 e6 ]
  52. }( v8 ~6 ]4 i- B/ h" w
  53. /*获取ADC1通道3的值*/; Z) C2 s8 U+ B( G: ?( g* _1 a
  54. uint16_t AD_Leach_3(void)* |: b- o/ u" Q) i  b
  55. {4 r8 T9 v! E5 i' u/ _
  56. uint16_t adcx4;, D" a- E2 `( G7 ]0 ?2 k2 |& q
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
    # A, ]( l' ^, ]3 e  W, z, M9 O
  58. return(adcx4);
    3 J1 _0 `. X2 i5 x  e/ C2 S
  59. }
复制代码
. D' C$ _5 A: r
0 Q. ~5 T4 m4 R0 ]" ]) A
目前就学习到这里,后续再写!
( N) F; ]0 g1 T1 K4 h5 }- k" P2 L
% ^/ L; ^$ V8 c" w: Y
: q/ @; F5 I- D. i# b3 \9 O- w
赞 收藏 评论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 手机版