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

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

[复制链接]
Bowen 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑
" y9 c0 M- t/ [, [9 ^9 V
( n% W. l! e6 i" L1 ]) w  r! H" Y
编辑原因:上传代码不全,补齐代码。
& \  D* N. I; D4 L
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)$ V: f" X4 k3 h9 p- `
  2. {
    5 X$ x: p9 \1 L3 `+ l6 u3 ~
  3.   NVIC_InitTypeDef NVIC_InitStructure;
    / L) \3 M+ l, }
  4.   /* 嵌套向量中断控制器组选择 */" Z* A- P3 g+ u9 \- o1 X4 B
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);: k/ G5 ?8 T. R4 n1 p+ q/ k. z
  6.   /* 配置USART为中断源 */
    ' q0 f7 p; U" s$ K
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    ' s' J" y- o3 y/ ~* c6 ?9 M/ g. x( e& C
  8.   /* 抢断优先级*/7 |! x9 a: |5 h" v% L# A4 L0 m
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;' t8 ]! w( h/ J" h/ I/ T
  10.   /* 子优先级 */# q# C" L7 {: j% q; q5 M
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    4 X! }! h0 o6 l. E) i3 Q5 D& n
  12.   /* 使能中断 */
    . F+ }: V6 f+ l, A9 L6 ]
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;1 w7 `* _" T4 C$ D
  14.   /* 初始化配置NVIC */
    ; h5 N+ i4 [$ \: U  p: a
  15.   NVIC_Init(&NVIC_InitStructure);$ Z$ }8 \# |& V0 [/ R3 @
  16. }
复制代码
二、DMA---直接存储器访问

( ]& l5 j& |- E7 V/ o5 J) g) J
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void), Q: N& Q) G( K$ Y3 M
  2. {
    6 r% \& i5 J: r! i" M5 ?; U9 V, L
  3.         DMA_InitTypeDef DMA_InitStructure;+ w5 ^# I* b- _! _- r, L  ^
  4.         // 开启DMA时钟
    # `0 ^. f% r! A+ W% _* H9 b
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    0 O  I$ F# m! Z/ U7 }0 T) M
  6.         // 设置DMA源地址:串口数据寄存器地址*/+ S6 G9 d, B5 {) a6 t, G
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;3 O. S) D. h/ ~4 @% e8 |
  8.         // 内存地址(要传输的变量的指针)
    0 E, g" F1 |6 }5 N, r
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;/ h, b# ~; [5 x$ [9 u" ^
  10.         // 方向:从内存到外设        
    ) {3 j  J7 M* d! E+ L1 c7 t
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;1 \$ ]: h) Q- n
  12.         // 传输大小        3 y0 `: |: K. \1 Y
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    9 `: a( v) k2 U9 Z3 ^. T
  14.         // 外设地址不增            1 }4 m4 e, f  p( c7 v( J+ w
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    1 v2 I) N( }2 ]; z+ i) D, r, G/ k3 t
  16.         // 内存地址自增3 l7 l# G* n  F% ]
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    % K# U* i; l+ T$ }2 N+ G
  18.         // 外设数据单位        
    5 v$ q0 |$ m; P4 C6 \
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    . o7 {& }/ x: z1 Q0 W9 Y
  20.         // 内存数据单位
    4 l% e8 l  t+ Q1 E% S+ R! C; t
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         4 F8 a% ^7 f" H8 I, T3 M
  22.         // DMA模式,一次或者循环模式5 u* @2 ]; U" x# i0 \+ Y6 v
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
    ! D( w9 s+ Q" ]3 k6 n8 M* H: h
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        . v$ I7 ^2 x9 {: N* \: g
  25.         // 优先级:中        - s5 C( k# L/ p0 q
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    0 I% d% j4 z( a# H( G- y+ @
  27.         // 禁止内存到内存的传输
    $ M6 o# R5 h) M/ x+ [. D" x
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;# i) g2 \; z$ S; n1 ~
  29.         // 配置DMA通道                  
    : X$ G) p9 [  q( S3 a- @- W
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);               
    4 q+ v0 ]: B; G; t
  31.         // 使能DMA  t' Z' F. S( K" V# d+ C
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);* [4 i5 O/ ]+ t5 |$ f  P  K: z
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址& `: j, O7 A6 }" B
  2. u16 After_filter[M]; //用来存放平均值之后的结果; n9 u+ _& [1 I# K2 [& R

  3. ; O: ~$ L! _4 l% n0 \& e
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口+ q# |  ]% q  y( J% Z6 y
  5. static void ADC1_GPIO_Config(void)
    / {, U" }- [( g: f4 N
  6. {" E( o. E$ X4 S5 q$ `7 ~: ]3 r
  7.         GPIO_InitTypeDef GPIO_InitStructure;& n+ o: |' _, V$ L
  8.         
    * k- c+ W" G( C% M
  9.         /* Enable DMA clock */
    $ \2 I4 L! e! Z/ h( R6 n
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);; v3 n! X2 O* F, M8 v3 l0 z
  11.         9 G2 _3 i) F! e; z1 _
  12.         /* Enable ADC1 and GPIOC clock */) b$ `% [7 E% n5 ~
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    * m' o+ D- A& Y3 A3 {
  14.         
    * {# Q7 H, b7 ?( }7 z
  15.         //PC 作为模拟通道输入引脚                        
    1 i* @. Q, B& B0 B; V$ _" o
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    . w; |2 R$ H! M; {& G8 W: K
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;               
    1 ?9 t: C. K! m4 f$ Q* O5 I
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        
    + V+ j0 t4 H% T5 C3 w* C# i8 \2 Q
  19. }
    ' K5 D6 a! o6 `, f8 L# }' j

  20. 6 m; v$ F' q% h+ V# l, C3 B
  21. //配置ADC1的工作模式为DMA模式& ?9 z2 W$ |9 v( T+ b: _- t
  22. static void ADC1_Mode_Config(void)
      W% Z; x/ D/ }/ k
  23. {
    4 N8 q( d) g. C
  24.         DMA_InitTypeDef DMA_InitStructure;4 I5 O* a7 r: O' }5 y
  25.         ADC_InitTypeDef ADC_InitStructure;
    1 v- M% Y3 X( r+ _8 I
  26.         
    7 k. l: {3 u# _
  27.         /* DMA channel1 configuration */
    % [' \: X5 ?% m1 _
  28.         DMA_DeInit(DMA1_Channel1);: S! W! b; N+ }7 S+ g: Q) v
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;5 R9 O3 v7 M6 h" l! t

  30. ; b+ B) n- n$ t; L/ w
  31.         //内存地址  
    ) D( I, Z" W& N  \. L( F5 F
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];4 ?, r/ |; l# o$ U. i
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    ; |1 M% O! g% P' P* S' }! a" K
  34.         DMA_InitStructure.DMA_BufferSize =M*N;
    : P2 h$ a: g0 f% `4 i" Z; N
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    $ A9 V" k7 ?% X' a$ i
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    " ?- T: X: n6 P
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    , f  v, k& R- X
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;7 v1 Q& ^" m+ y2 x5 V( U
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;- W: P, L6 w6 l* o, c7 I- D
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;' ?! R' ]) N! d5 z
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    " j% I- k7 [; P" x4 J2 q  i- |- d
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);2 n  z* b+ D2 A6 c% K& @
  43.         
    : o. ]. a- g, b3 A3 }7 j
  44.         /* Enable DMA channel1 */
    " y4 D$ d' E0 l, D
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);3 ]$ Z5 \  v, s# z% V& O2 l1 P
  46.         ' y' I2 q1 X9 F
  47.         /* ADC1 configuration */        
    9 v$ Z6 r7 t5 e3 H7 _0 T! A9 {3 r$ r" p
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;) {$ s/ ^4 D) O2 O
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;! P) M9 D2 V/ p- U: }
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ( i: ]6 W+ c9 Z9 M
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;4 s& I4 E( ]  e
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ( [2 }4 m& V+ n* C' H$ K2 ^
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;, J+ u5 j' D$ y9 W% i
  54.         ADC_Init(ADC1, &ADC_InitStructure);
    ; ~' G3 o% C3 h6 O- n3 v. a, K& m
  55.         
    . h+ I- `9 g: @6 J" l
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/3 i/ b* q' a6 G9 k( R# x% N2 g9 s* w
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8);
    - H* T9 j1 O; s  B* `3 E' u* d
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */
    9 t+ [0 U7 w$ y: ?& w/ O
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5
    ' h% W9 R% @4 i: q
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);& D3 I& F+ T" y
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    5 b. d/ {& c8 [' U- U
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);    y" J2 V$ [+ b% n2 t- p
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);6 L; W, U; h6 x' @- Q% B
  64.         0 _+ s2 j6 N$ D! a- j2 A( }
  65.         /* Enable ADC1 DMA *// J8 D3 K# r' A. [* p0 f
  66.         ADC_DMACmd(ADC1, ENABLE);
    5 X9 R8 ~2 \: u8 p6 e$ n9 S6 U
  67.         . T$ p  j6 U1 j' M' r
  68.         /* Enable ADC1 */
    2 V7 L) X! v' w! x9 `
  69.         ADC_Cmd(ADC1, ENABLE);
    ; N/ m# e. ]8 C  ?1 J% J- w
  70.         % R9 K5 |% \$ H' k; c4 I4 e7 j
  71.         /*复位校准寄存器 */   4 E5 ^4 J) Z& D% d! \: }$ `1 Y+ x
  72.         ADC_ResetCalibration(ADC1);( ^3 S7 O4 m. L' D9 O# \
  73.         /*等待校准寄存器复位完成*/
    * h2 _. E, q6 y9 O/ R3 z0 w& M% W
  74.         while(ADC_GetResetCalibrationStatus(ADC1));+ y# h( F3 a  g' y/ M) [
  75.         & R, I( p' v) k3 T! U  z# y9 {
  76.         /* ADC校准 */
    % s/ }8 y8 V+ Q# @9 y
  77.         ADC_StartCalibration(ADC1);
    " g: ?. O2 E" p# j2 V
  78.         /* 等待校准完成*/
    + r) `( Z( v9 k( `( |  {1 b
  79.         while(ADC_GetCalibrationStatus(ADC1));" \1 ~; m8 \/ P% C
  80.         
    5 b3 d+ f( o* T% U/ t, E0 Y
  81.         /* 软件触发ADC转换 */
    4 s+ e( M8 l% |
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    % ?: [4 P+ \1 r# e8 [; A- G, e# a' L
  83. }
    3 V7 e3 ]5 P# j$ _
  84. /* ADC1初始化*/ . m+ |5 ^  S% F" n/ K
  85. void ADC1_Init(void)& P/ A- N& T. k- E7 c5 W
  86. {
    ' F# n9 b; u% J5 Y: e1 p! H. v- o
  87.         ADC1_GPIO_Config();, g# o+ c4 X+ O  k9 q
  88.         ADC1_Mode_Config();
    1 ^# y' Q. s; h" h% ~
  89. }
复制代码
  1. /*ADC滤波*/
    , k+ B/ H4 ?, r) M, K  f" y8 `2 [
  2. u16 MultiDMAGetAdcTest(u8 ch)1 U& F1 o" i7 b/ Q& I2 S
  3. {0 z5 W6 c5 r$ u& j/ I  X
  4. u8 i;/ u- y9 R& P# K8 d; Z* G8 @; L: g% W
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
    2 A/ Q6 n5 u: c# c
  6. volatile u32 ADC_Data;
    * ?2 ?: t8 U8 Y
  7. ( h  y( K: H5 O! M
  8. ADC_Data=0;
    # d2 _& c& J4 m

  9. / b0 o! j8 t; Q( G9 X
  10. AdcMax=0;" {- V% v1 x$ m' Y3 r5 o
  11. AdcMin=~0;4 \; D* p, Q/ H; O
  12. AdcSum = 0;
    ! \; v9 u# F; v5 x
  13. Adc_temp = 0;
    " d8 h# K% @+ |# ]: S; z

  14. 2 i7 z0 X8 W# |$ L6 Q" I
  15. for(i=0;i<34;i++)  v& ^1 `* M( P0 l- i6 @
  16. {
    8 t+ u4 q, R) g! c
  17. Adc_temp =AD_Value[i][ch];0 F0 K3 G9 u- l1 E& }9 f% t
  18. if(Adc_temp>AdcMax)
    7 h$ V6 [) h4 t7 q0 y; ]3 o  j
  19. {
    : o. z7 ?% U) `
  20. AdcMax=Adc_temp;
    ! w& \3 ?+ q4 i- C4 T3 `
  21. }
    ) M4 r7 F/ y* f4 x4 U
  22. if(Adc_temp<AdcMin)
    $ f/ S% [. F0 n8 u: K
  23. {
    / ~2 m: k4 u! y" g
  24. AdcMin=Adc_temp;3 ?8 s, _1 F9 i5 E
  25. }
    9 f/ _* k1 D! [( E' ~& {' ?
  26. AdcSum+=Adc_temp;) N- X$ ?; {  c
  27. }
    # z% o0 D8 y3 b. }0 [
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
    , F0 r2 {% v; X8 A4 ]
  29. After_filter[ch]=(u16)AdcResult;
    / b* b. V1 ^  S% ]/ F$ }# D
  30. return(After_filter[ch]);
    ' T" ~! }7 u& U5 }' o* @
  31. } & j% U0 p9 N' ^9 P  M9 r
  32. /*获取ADC1通道0的值*/
    8 o! M+ n; S" Y. ^) X( T
  33. uint16_t AD_Leach(void)
    $ V4 ~* W4 g- ?9 Y1 U
  34. {
    . S" Q" {; f+ B' s- v& s4 u7 R, `+ {
  35. uint16_t adcx1;
    & }# D( [" r" \  W
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);
      n. J( f/ t' ]6 D
  37. return(adcx1);6 b( E) \, Y& U8 X! S
  38. }- x; C7 b  b& u) p2 D2 Q) N
  39. /*获取ADC1通道1的值*/) |4 A1 S1 V! Y/ u/ p
  40. uint16_t AD_Leach_1(void); O8 o# ?. ?( m" n* k( X
  41. {- }2 n* h( P; ]
  42. uint16_t adcx2;+ K; l* ^8 _/ N7 @* _
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
    ( r0 `( S) s' M* B' |5 j% X
  44. return(adcx2);/ _5 q4 @# _, |
  45. }
    8 m$ c7 E% ]. t
  46. /*获取ADC1通道2的值*/
    / I2 F( d2 r. l  d
  47. uint16_t AD_Leach_2(void)$ H1 x+ I( x$ a" C
  48. {
    ! D0 x1 y2 ]  y9 Q: ]! o
  49. uint16_t adcx3;6 g, Z+ K+ M8 l& P( E8 X- q
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    ) @+ u# ?: v% x9 E# y
  51. return(adcx3);
    0 }! u  ^. Z, b" l( m
  52. }
    # t% V9 P; ?# ^- b7 Q% {. Q
  53. /*获取ADC1通道3的值*/: l# [' N% o8 F
  54. uint16_t AD_Leach_3(void)
    , j5 d/ q) g1 _1 M
  55. {/ m4 B) i% z! _& ~& L$ z4 p( A
  56. uint16_t adcx4;
    + x8 q$ U/ G- g/ i* N5 o
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);0 f1 E1 w* }& ]! a) Z* H
  58. return(adcx4);0 k. l! K1 D5 ]7 g9 C
  59. }
复制代码
, h* h" `* w6 }

) m9 o0 n- t! N3 |) w8 Y目前就学习到这里,后续再写!7 O8 B) c0 p4 V

8 K0 [# [# P! Q/ g1 k& k1 k0 U% u9 q5 a/ v1 s  m6 }

/ C. i- f" I) b1 D5 h3 ?0 D$ 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 手机版