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

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

[复制链接]
Bowen1028 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑 " C$ d' s! _/ _1 U  G
0 [; I. P4 ?" H3 [5 b
编辑原因:上传代码不全,补齐代码。
% q4 s8 f3 }8 U4 y( H+ S
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)
    , s# @$ ^, _3 u6 @5 U4 Y
  2. {6 O) i: I' h! l6 w; _3 N' D
  3.   NVIC_InitTypeDef NVIC_InitStructure;
    ; S- q# q  p% r: q3 ~
  4.   /* 嵌套向量中断控制器组选择 */
    " ?) D4 _3 K) G, p- X
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    ) Z& z" k7 w# n% p
  6.   /* 配置USART为中断源 */
    - x5 f, x4 r% m0 `# J
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    $ S0 l! `9 A5 Z) h- F* L# O2 V% \. w
  8.   /* 抢断优先级*/! V! o; r/ y5 z) S5 |
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    0 F3 B! {+ H$ g: F& Y
  10.   /* 子优先级 */
    ( U8 @/ I+ D( i+ V4 t" M: j
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;# B2 `3 x# l- T) a! Z# }
  12.   /* 使能中断 */6 o( N: d0 _( G
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;! m0 T7 c: b$ t* U- C/ l* d
  14.   /* 初始化配置NVIC */( A0 c* }  w! D+ {* ^+ Z; r
  15.   NVIC_Init(&NVIC_InitStructure);
    ; J, P) H2 C' k2 l8 n
  16. }
复制代码
二、DMA---直接存储器访问

- a: H% r+ P7 c) l4 k+ Z  H
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)
    ' v, O: D0 m, k
  2. {
    % D, Q) T. I9 d( G2 c7 i" `
  3.         DMA_InitTypeDef DMA_InitStructure;+ @+ z# o* A% `; o5 n: q
  4.         // 开启DMA时钟# r5 K5 h8 S. V* H( e% u7 [
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);, t" J6 f& U: F% x( p
  6.         // 设置DMA源地址:串口数据寄存器地址*/
    ! }" h+ _8 N, R- _' q
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;6 I3 m5 F! T( M5 m8 \6 d
  8.         // 内存地址(要传输的变量的指针)
    1 H8 g: H' Q5 i- ~1 \/ p) ^$ Y
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;9 [. t1 t# v1 _. z. a# U
  10.         // 方向:从内存到外设        
    ! r2 T/ n. p0 Y# t
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;2 g, ]1 K( e& j& O& {: S
  12.         // 传输大小        # E; @% Q) c: {0 ^, {
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    ; k; x6 z" p# _0 L: E6 k- q
  14.         // 外设地址不增            
    . V. y& H2 l( {2 l" v
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;% ^0 Y3 K" ]/ i
  16.         // 内存地址自增
    1 l7 U: |$ C7 u& U( i' V
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;! _1 I$ H# h7 Y3 A; Q; M8 B
  18.         // 外设数据单位        : T" {! g8 z. e# p: x
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    + f8 n) M$ n8 l! a1 O4 n7 y
  20.         // 内存数据单位8 T3 v& T6 `. s# R7 u. v$ o  e
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         
    ! O9 z# R1 ]. M" o  S4 D
  22.         // DMA模式,一次或者循环模式0 \. s6 }5 F  s. q1 B2 X# K0 Y4 H
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
    , r( O* l/ ~* Y
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
    ; Y  l) y4 X1 [5 U* E' H& ^
  25.         // 优先级:中        
    7 g) T. u  E8 k9 h8 p
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    & |1 b+ C' v* u  Q$ U, Z  O% b
  27.         // 禁止内存到内存的传输3 ^, l; m7 R- f2 C0 x# \, @5 \
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    . c7 o, K( w( g0 n- P, n
  29.         // 配置DMA通道                  
    + }$ I  C5 }( h; o
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);               
    ! ]2 B4 X$ d. ]" M% I" D
  31.         // 使能DMA' M1 `4 A9 d2 k+ o
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    * s- O- x$ {1 |- F8 d$ t
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
    : \  D  C5 I- w$ z& {) Y
  2. u16 After_filter[M]; //用来存放平均值之后的结果4 v; f# B0 f- r2 i
  3. 5 H5 I. {. |- H
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
    7 [) F$ T1 m4 s- q
  5. static void ADC1_GPIO_Config(void)
    $ C/ P1 `0 t, h
  6. {
    6 V0 s, m( h' h! D
  7.         GPIO_InitTypeDef GPIO_InitStructure;  ]" V+ Z# J$ k6 K! h; \
  8.         3 G- U2 c3 b. t# Z
  9.         /* Enable DMA clock */5 `" v: S! a: M8 ~8 A0 i9 E
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    ) T- b0 \. U9 {) y( o* F
  11.         
    + n, W5 S! W7 ~, _5 n
  12.         /* Enable ADC1 and GPIOC clock */# r2 A# I& K6 \& y
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    / K& l  |1 `7 A0 |& }1 R- W, ]- r7 ~
  14.         " m* `5 y* m# J) j# u
  15.         //PC 作为模拟通道输入引脚                         % ?* \- p6 T5 V, c- r3 r
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    , }3 r" f8 q8 i! G( f
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;               
    # F5 K* w* Q9 ~* X4 I! ~
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        ' g$ {) [. H+ S; q% |$ [1 v
  19. }
    - N# j0 S, r# \$ `/ W

  20. 4 E& ]. q' A1 [* E
  21. //配置ADC1的工作模式为DMA模式8 K5 n( N- }4 a% [! A+ W* w! a8 A
  22. static void ADC1_Mode_Config(void)( v! ^/ a6 Z+ t* F. b' t# V
  23. {3 U* W, B0 `  ]8 Q
  24.         DMA_InitTypeDef DMA_InitStructure;
    , ~1 [# [/ C+ }  P6 C
  25.         ADC_InitTypeDef ADC_InitStructure;+ e) Y  @8 Z% l7 A2 {' n$ T
  26.         0 T1 r- l& m2 N0 z
  27.         /* DMA channel1 configuration */. ]6 v" T$ E; P  z
  28.         DMA_DeInit(DMA1_Channel1);
    ' C. ]# Q* h6 w; U* P) W8 o9 B
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;" J1 ?6 u: ?& H- M* O2 G0 n; \

  30. 3 c9 _+ Y' W3 T
  31.         //内存地址  
    3 I) M2 V/ w  w$ S7 ^+ T
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];
    ) }9 F3 i. O- R$ t/ T
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    0 t( p) k5 p& r6 W  o
  34.         DMA_InitStructure.DMA_BufferSize =M*N;
    ( q: n5 {# |7 U6 ^- G1 ]1 }
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;2 B) l4 \! F) W
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;7 \5 D/ q+ @4 q
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;1 A4 P9 v1 Y( Y- F
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;- D0 m0 v# i6 B1 ~1 t2 ]
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    & J0 E, f% j" v  u" o0 O7 ^
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    0 Z; s& H. I' n7 M
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    % X/ U1 \' p" F+ X! ~6 I+ o
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    1 {5 y) k& W% z& T" o
  43.         
    , r% V% R9 }3 Y9 J4 r
  44.         /* Enable DMA channel1 */
    1 i# v; }: C) y# i. T
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);" T# b6 Z% f& I, z
  46.         0 ?! L' f# a( ^3 P2 C% M
  47.         /* ADC1 configuration */        
    6 O9 O0 g0 E7 x: k% D
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;1 c8 i0 y# N. e4 j- A
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    : o. j* O! I% X
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;- X3 Q3 [  X3 G8 ~
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;+ u4 C6 ?7 ^. ~  X! U+ a, P
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;$ h+ C; b8 q- Z7 w, h; Q
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;
    8 h$ l, w0 ~& O) x6 a2 E( g% ]
  54.         ADC_Init(ADC1, &ADC_InitStructure);
    ( e* N) g8 E; q$ q5 u7 @5 b
  55.         ; ?7 K) |. w  b" H6 {6 c
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/; V0 p/ v$ R; R! r7 M/ c* p
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8);
    ' e" f" ^2 \9 l( ~2 m/ h* ~! G9 P! t
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */ , M) p+ V: X" v) C8 q7 T6 q
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles58 T! {+ C. H' Q: x+ w  o
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    5 m" z( p% \/ k0 u) b! B6 ~
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    ' x% X8 @6 ^  B: B+ e
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  
    3 G5 T8 _$ X& n
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);; M9 m  j6 |) f( B  c
  64.         ; t) _1 \3 {! {% O* i
  65.         /* Enable ADC1 DMA */% K! ?  M3 Q$ }
  66.         ADC_DMACmd(ADC1, ENABLE);# t) H) @1 Z. T6 g3 F
  67.         
    4 d( T; e/ [, ]; u
  68.         /* Enable ADC1 */. Y2 I& d. r2 ~- E
  69.         ADC_Cmd(ADC1, ENABLE);8 M& X; C2 R6 c$ X
  70.         
    & T/ j( X& E: b, D$ I
  71.         /*复位校准寄存器 */   / W& q& a1 U9 N: }. L
  72.         ADC_ResetCalibration(ADC1);; m3 [0 l: E* O, P# y* E. K
  73.         /*等待校准寄存器复位完成*/' Z; a8 R& }# \! N
  74.         while(ADC_GetResetCalibrationStatus(ADC1));2 `* \1 z8 ?# I. t8 E# x4 L0 `
  75.         
    9 T, Z9 J" E- r; V
  76.         /* ADC校准 */- {* Z& b! p* j$ }0 V- u( K1 k- Z5 \
  77.         ADC_StartCalibration(ADC1);
    ) D- G/ U: W* h5 f4 a
  78.         /* 等待校准完成*/
    ! V% t0 e# f$ b6 U6 z3 M- N' m2 r
  79.         while(ADC_GetCalibrationStatus(ADC1));) ~9 k6 ]% ^+ ?! J# n. Q; B
  80.         
    ' Q3 @* ?. f. D8 B
  81.         /* 软件触发ADC转换 */
    6 A% T! l6 K; r/ S: b6 |/ o
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);9 D3 i$ h) e7 b- W' L- H8 ^
  83. }2 s9 V2 @% M6 b' P/ O
  84. /* ADC1初始化*/
    & \$ n* R8 o4 g8 _3 h
  85. void ADC1_Init(void)
    2 e% ]" @) ^! m
  86. {
    ) ~( j( Q+ f( ?$ |
  87.         ADC1_GPIO_Config();
      z2 y1 H2 g* W0 \
  88.         ADC1_Mode_Config();0 T. N2 i: W) v* F( C' h6 Z
  89. }
复制代码
  1. /*ADC滤波*/
    1 o  [6 t1 f1 ?0 {, P  ~! Q" ^) P
  2. u16 MultiDMAGetAdcTest(u8 ch)
    1 G& p! |% T/ f  ]& G. G; \
  3. {
    , \% {, y8 o9 |, P5 A. ]
  4. u8 i;6 B, N: ]) J3 @7 ~8 M9 H( U6 U* s
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
    6 ]- x/ R' P# v
  6. volatile u32 ADC_Data;' v; R6 M: D. w8 r: |

  7. ( x3 H; g. h& g1 Z1 }7 J# r- B
  8. ADC_Data=0;* b; c0 O5 a, f5 T5 L0 B4 W( r$ y5 K0 h
  9.   o/ t4 ?0 \& A, r& i4 A
  10. AdcMax=0;2 F% x, t4 I8 n
  11. AdcMin=~0;2 j& C1 b( T# c$ i& d
  12. AdcSum = 0;
    / b9 v& a* g4 N2 \
  13. Adc_temp = 0;
    7 o! x# w. L# T
  14. % O$ e; ~8 `5 `' i
  15. for(i=0;i<34;i++)
      H4 E; i1 z2 U, M" ?. ?' l
  16. {- y& O6 n2 }% o+ M' q
  17. Adc_temp =AD_Value[i][ch];* ?* f% V0 A) z- U! h) m2 N
  18. if(Adc_temp>AdcMax)
    , A; T: b5 E8 R
  19. {& X( y; I  y8 N1 v& k4 c; R4 x
  20. AdcMax=Adc_temp;
    1 _6 [4 C# m% P  r" q! w
  21. }
    2 Z1 L$ c# P# a. G
  22. if(Adc_temp<AdcMin)
    4 k; b3 R& P# p" y
  23. {# a2 [$ s7 c0 d/ t* m9 _
  24. AdcMin=Adc_temp;
    9 _  {6 ?5 F4 C4 a: l8 Y  u
  25. }
    . l1 j# k) v' H% n7 ?! [; q
  26. AdcSum+=Adc_temp;
    ) z: T  s) Q3 L3 O
  27. }% _3 W+ X8 s! P8 ?5 [' i1 P- ]/ L
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;7 _: ^9 Y7 n2 _$ ]2 Y) B
  29. After_filter[ch]=(u16)AdcResult;1 Y' m( K, J& H: v( w& g
  30. return(After_filter[ch]);
    ' v. R: Q* j; b5 ^7 t
  31. } / Y  v+ @9 @  M. i8 _  u7 J3 e' h
  32. /*获取ADC1通道0的值*/
    ' Q& A5 {, L+ }0 m
  33. uint16_t AD_Leach(void)
    5 `6 o3 E' R  s1 _: U
  34. {
    " @# b: }% A" y/ T
  35. uint16_t adcx1;
    . j" ~' ^/ M* B4 [* c, W) T( u
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);5 Z$ H9 J8 D, W2 z5 S
  37. return(adcx1);
    9 p5 Z& J5 D; N# q4 k- o$ }( X
  38. }5 F* F8 F3 E: |# L. r4 B
  39. /*获取ADC1通道1的值*/
    % ]& o0 g- X5 h( s
  40. uint16_t AD_Leach_1(void)8 s: W/ K  j* l) t: C3 @7 @
  41. {  Z- c9 B6 Y3 W
  42. uint16_t adcx2;
    2 ?4 M9 ?& H- K9 |: ]" V
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);! l8 w* y/ S" r# O
  44. return(adcx2);
    5 b. a! p* Q" ^1 M& g
  45. }
    5 ?" t; X# ]& V/ [* G
  46. /*获取ADC1通道2的值*/# n& A! b* d* m! K8 l# B
  47. uint16_t AD_Leach_2(void)
    ) {, |4 K1 T- k; L
  48. {
    & S0 `' t. r0 X
  49. uint16_t adcx3;
    ' z. w- Y- t& F) r0 B" ]: ?
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    ; p% _) f/ u0 J& U0 g* t
  51. return(adcx3);
    3 W* L9 n$ q+ d+ \7 }- M2 `  v
  52. }- _: }+ O1 x( I. Q' W7 A5 }- d4 N
  53. /*获取ADC1通道3的值*/1 B* B" ]) j5 O( q/ d5 t% h1 T0 z
  54. uint16_t AD_Leach_3(void)
    ! e: T' ~9 ~/ T7 P* K' p: F
  55. {
    - C9 z2 }" e& w
  56. uint16_t adcx4;" v! j5 i% L5 C+ N! G: q" H9 C
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
    * _$ @. N4 z# T6 ~' Y5 Y
  58. return(adcx4);  f* T  N9 Q) W
  59. }
复制代码
5 m2 _3 H, K' o5 U5 v6 g; ^/ n+ b2 ]
. G- i0 D. v4 G1 ~3 Q. J* c3 k
目前就学习到这里,后续再写!' @5 l% |+ a) f5 B4 o$ p

& O' \# a! s6 W1 S- E8 p
8 `% L9 ^) q/ H. M2 o( S  N- H( X( I( Q1 K. T- S9 |4 i
收藏 评论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 手机版