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

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

[复制链接]
Bowen 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑
9 |& [/ [* P! Y9 ~* I2 x8 f- Q% X# F" ?1 q( Y
编辑原因:上传代码不全,补齐代码。
+ `, q$ W8 `; W
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)0 d7 N) ~* O( R! s. D' L% ]
  2. {
    / X/ F* k1 d' ~4 g( M
  3.   NVIC_InitTypeDef NVIC_InitStructure;  j) Q# k8 r( ^) i* s7 H% L
  4.   /* 嵌套向量中断控制器组选择 */
    ( }% c  B; h" |0 u. o
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);9 ]! S$ K) g2 F% l5 c
  6.   /* 配置USART为中断源 */
    8 J5 ]6 u3 q* I8 i* a6 D7 o
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    0 a5 i. f0 R/ ^* F9 N
  8.   /* 抢断优先级*/" M3 M+ k/ f8 t. w/ R1 B
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/ X! f# e1 B- g8 ^! F/ F) f5 C
  10.   /* 子优先级 */
    2 {# C7 o) s4 Q* K" z
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;2 w- m8 l. k& C1 d9 A
  12.   /* 使能中断 */
    1 w, o$ y8 \' }- k4 H
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;8 x1 W8 k6 N4 o. T' C8 z; w$ p
  14.   /* 初始化配置NVIC */) H9 f" B$ [3 T+ h, k
  15.   NVIC_Init(&NVIC_InitStructure);! N6 E, l* x" e) }
  16. }
复制代码
二、DMA---直接存储器访问

! ~9 V: {- K. m3 F0 }5 m7 z. a" K+ h
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void), e* g5 ?7 t3 s* ]
  2. {
    1 I( C( x% D8 J6 |2 Z( ^6 i  t
  3.         DMA_InitTypeDef DMA_InitStructure;5 J& S& E, D4 S
  4.         // 开启DMA时钟& g" H/ ~( O4 ~; k1 {. Q6 ^5 \- t
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);6 O$ i+ A( t" Y5 Z
  6.         // 设置DMA源地址:串口数据寄存器地址*/
    # c6 a4 {" m) I; h. M
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
    % ]! E0 \1 W) `" `% e1 e8 x4 b
  8.         // 内存地址(要传输的变量的指针)
    8 [* y3 R$ \0 ^5 D
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    6 C3 w) W" N' E! |7 v% l1 a" m
  10.         // 方向:从内存到外设        # A+ ]" \( s1 X1 w7 O/ Q" U/ Z
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;0 S, V( K# d( W( k5 [
  12.         // 传输大小        - `6 I/ n5 w( n
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;6 N$ t  ?  g4 h( X1 G  K8 P
  14.         // 外设地址不增            
    3 ~- E6 B- l6 m, L" W6 a
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    , e/ A/ e1 ~8 D2 |$ t3 Y7 ^/ O3 e
  16.         // 内存地址自增9 d4 u; b5 D# v; M+ P) X7 U# n
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;2 Z, `' U. x8 d0 B0 |4 _# s9 j
  18.         // 外设数据单位        ) _' i$ U: u1 T
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;" a7 e6 `; _- r+ z  Q$ v
  20.         // 内存数据单位
    3 G1 g5 O# B0 N& p" Q- {
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         , ]# H" S+ a, W
  22.         // DMA模式,一次或者循环模式6 d: R8 w- E5 ]! I; l
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;! H; `3 j7 r  }8 }. H6 j3 x
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        % J3 h# b1 ?+ [% W4 m
  25.         // 优先级:中        4 U- j" J+ D7 G0 m) r# x
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; $ Z: K& c* y- j
  27.         // 禁止内存到内存的传输8 [9 d8 Q6 b" f
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  F: p9 ?7 \( K5 Y0 B% R
  29.         // 配置DMA通道                  
    3 g. @% {/ s' M8 g  l
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);                - h+ c- E* }+ j* _9 k/ r  U5 s
  31.         // 使能DMA1 z( P( f  U. j: x- N3 ~% Y
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    $ [& s  \% m2 o
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址+ V. w( _/ ]: r; D$ @
  2. u16 After_filter[M]; //用来存放平均值之后的结果, S* L" I: `5 @  C
  3. 2 k  d, l/ M( g6 A7 n+ _* Z
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口2 y1 A# g6 e- m' Q& @
  5. static void ADC1_GPIO_Config(void): q" F2 u* T' ^4 |& [3 R- p9 I
  6. {1 ]% A: r0 |- W( d) G) y0 m6 F- D8 i$ n
  7.         GPIO_InitTypeDef GPIO_InitStructure;, T) Z* L1 O& _: p0 F/ P! Y' [
  8.         8 e5 k4 W. Y$ ?4 u+ ~6 M
  9.         /* Enable DMA clock */
    2 \' M3 p  w6 E4 D, j
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    2 ~* I7 ~1 n, _% u" [  W8 n1 y
  11.         , i) |* {4 o% o: c* w
  12.         /* Enable ADC1 and GPIOC clock */# V7 K, n& k2 X% Q
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    , G3 {5 Q' ~4 ~2 `) H9 K
  14.         / d' o- F" g! X
  15.         //PC 作为模拟通道输入引脚                         7 Q$ b7 W: j2 z: K
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;/ p- E5 |/ F8 G. m" g& b: F
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;               
    " b8 e' N0 @3 G/ C) o2 c
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        1 y1 a" e1 {" W* ^
  19. }% k, Z, E5 M5 H; c3 Y7 U0 b
  20. & X1 @6 N7 S- S4 i5 x7 |& ~* k) \
  21. //配置ADC1的工作模式为DMA模式! l4 U4 K+ m2 U# C5 x8 m
  22. static void ADC1_Mode_Config(void)  q* r- c' v3 [' H4 M6 d* |/ w
  23. {
    5 z; Z3 z- \- ~# R! Y/ }, u( I
  24.         DMA_InitTypeDef DMA_InitStructure;  `" S* ]' B" Q0 G4 D0 o' D% G
  25.         ADC_InitTypeDef ADC_InitStructure;
    0 G! Y9 ?4 k7 @$ r! }" @
  26.         9 T- J; U7 S- Z
  27.         /* DMA channel1 configuration */
    0 D/ b" u' z) @2 i6 T
  28.         DMA_DeInit(DMA1_Channel1);
    ! _/ f! U4 r2 N* y' k$ h
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;2 |  O* _2 I/ J- R% _% n
  30. . T7 c; \( R) z6 a$ G0 ]+ v$ c
  31.         //内存地址  
    $ z+ r: {, `! W, L% E) K
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];( z: N( c  u) @* A
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    4 p, o0 H7 N7 f
  34.         DMA_InitStructure.DMA_BufferSize =M*N;# j3 D* _1 x; V2 x
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    : v; X3 i1 w0 u" w4 \$ o
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;! U) y+ J  R$ T
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    9 o$ n+ a7 [+ A0 y$ p$ _
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;( {/ W9 ?' C5 }) u1 Z( a1 \
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;: _/ f* w. \" J
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;( {$ x4 F3 v3 j+ w) f
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    3 W3 ^9 T9 }: }
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    ! G* \$ j. g- w) R. O1 k* y& D: R
  43.         
    ' f: X7 D2 i- t/ U* V% f! Z* c; w: W
  44.         /* Enable DMA channel1 */6 Q( [, [% A2 D* Q2 \
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);
    " P, S" t% @6 J) k: P- }% x
  46.         
    5 H* u9 ]2 D: ^' E# t
  47.         /* ADC1 configuration */        
    / Q( g3 u  ]6 B) D
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;5 J8 ?4 Q$ N# p
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;" j. M7 E+ ?! @% p  ^
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;1 [8 h4 k# R* v  l' c, L
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;- s% {" }7 N& {5 C/ H9 `
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;9 f" ]! ^: `( {6 j- f! Q. |- Q
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;: I) D; B6 J5 s# P/ n6 |$ Y/ c  I4 y
  54.         ADC_Init(ADC1, &ADC_InitStructure);
    3 K' _5 T% c3 I/ F
  55.         ! ^% [% A6 @8 Y5 ]% }1 c# |
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/6 k: b' b1 N/ `
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8); . G' m8 v6 D; f$ m# I: H. I
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */
    & d9 W* `; d# r0 n4 ~; j0 p& V) |
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles58 s- D. \" t" |9 x
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);; f: m- S1 t2 \8 j
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);. [9 H8 t5 G1 M4 S$ e. x
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  1 ?% c( W9 V$ v% O2 u
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);/ p) |( b, ^" o/ ~
  64.         
    8 w0 N' A/ Q$ ?/ P3 q8 @/ w$ i
  65.         /* Enable ADC1 DMA */+ m" H) [5 i/ T; f( v
  66.         ADC_DMACmd(ADC1, ENABLE);
    - H! C; S* R, |+ |
  67.         
    3 e3 Q# Y) i! \8 s
  68.         /* Enable ADC1 */6 Q  [! G9 R" }* @
  69.         ADC_Cmd(ADC1, ENABLE);2 M1 Y# g6 s: f4 H# a/ ]
  70.         
    8 m0 e, g3 P& n! e3 @6 w4 c1 g
  71.         /*复位校准寄存器 */   
    # {5 e* x' p1 r' q
  72.         ADC_ResetCalibration(ADC1);  Q! k( i6 e7 C8 P0 t0 S
  73.         /*等待校准寄存器复位完成*/
    ; M, Y+ ]0 a5 b9 i8 G& o4 N) S
  74.         while(ADC_GetResetCalibrationStatus(ADC1));! p8 H7 }9 K( r" E$ u3 _! W
  75.         
    % c$ o# Q' w- |2 U# Y( K$ p
  76.         /* ADC校准 */' b/ c$ L2 t. \- f) S
  77.         ADC_StartCalibration(ADC1);, P/ m( [6 T- ?  ]' v7 x
  78.         /* 等待校准完成*/) d0 ?. m6 {7 F5 ~/ L
  79.         while(ADC_GetCalibrationStatus(ADC1));
    / Y" L* M. x. A; O9 Q( B" o
  80.         
    - L; i- m" D$ u$ V
  81.         /* 软件触发ADC转换 */ / q$ m2 o* N4 Q" v% W" z, J- I4 F
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);9 P! B' A. Y" C7 l7 S# v
  83. }3 u* C4 ?+ Y$ R$ D
  84. /* ADC1初始化*/
    + h% }+ C7 K1 ]5 x! Z; J( [
  85. void ADC1_Init(void)+ l. m0 M6 b$ r0 O
  86. {
    4 y) d8 f+ T4 u$ t7 e
  87.         ADC1_GPIO_Config();0 Y- C0 d3 X2 s' f( O& B
  88.         ADC1_Mode_Config();
    ( S( s' i: O) D. d* H2 Z, z0 d6 Q
  89. }
复制代码
  1. /*ADC滤波*/. s& A* d9 P5 D% N$ n- Z  \9 z
  2. u16 MultiDMAGetAdcTest(u8 ch)$ @# G0 q% b% i. y1 T3 o
  3. {: q$ y2 M' y/ |. z$ }' ?" v  {  `
  4. u8 i;% F4 \; s% M. q( b& P/ }% I
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;/ t1 S$ t' i- n
  6. volatile u32 ADC_Data;
    4 L, [. T+ x1 f7 E! J) F) }0 o7 R
  7. ; W) V, s5 g, L6 D8 Q9 U& E
  8. ADC_Data=0;+ ~/ ?# z" B* U1 R" L/ K! ~
  9. ; t/ [. V) Q" s& i- m6 Q2 ?/ S4 M
  10. AdcMax=0;
    " F3 ^2 E  w3 a0 p3 a" |. W
  11. AdcMin=~0;
    ) D9 P% X# o) Z" A7 n
  12. AdcSum = 0;) V% \6 x6 q9 N& z: C/ {/ u
  13. Adc_temp = 0;
      K2 Q. X0 V5 ]: G' m- d6 t7 e! A
  14. % A& ^5 _! m  p; A: a) k
  15. for(i=0;i<34;i++)
    3 u4 ~, W' p4 k, f
  16. {4 q* o1 Q) _8 A+ I
  17. Adc_temp =AD_Value[i][ch];+ R- v+ t7 [% S& w) d
  18. if(Adc_temp>AdcMax) + [+ `5 }1 g+ x# o3 T+ ]  s
  19. {" o' N/ I: y5 r8 @& J) u
  20. AdcMax=Adc_temp;# ~7 B2 D4 c: [% z$ m# X. E6 p( U2 E
  21. }) Q4 c. E0 @, N* Y" w2 n, l3 K
  22. if(Adc_temp<AdcMin)
    1 [- c/ A( L+ l* i0 e
  23. {. [8 b8 h2 }1 |+ t" W# I  z; q
  24. AdcMin=Adc_temp;
    5 }7 S4 ^+ q: \. ^* y- \
  25. }
    , U& o2 a& g) N9 r3 l" |
  26. AdcSum+=Adc_temp;1 Y& `$ ^3 b' v! Z1 Z
  27. }
    0 s0 l5 Q# @- u- Q1 b/ C
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
    ' K4 B/ r& I5 D) \! O
  29. After_filter[ch]=(u16)AdcResult;
    7 h5 D  h5 ?6 [$ X9 W3 _) A
  30. return(After_filter[ch]);' m. l; P& X! G$ B% [
  31. }
    & V6 r( Z. @' T5 \
  32. /*获取ADC1通道0的值*/7 G2 d! d6 ]7 v  H( A9 B1 N5 k8 @+ q
  33. uint16_t AD_Leach(void)
      a0 o" j+ q7 o. u9 K0 k& f; u- C
  34. {- {: s% M7 K1 }+ o5 J/ i  j' y( {
  35. uint16_t adcx1;
    7 v' ]7 t7 c. g2 d  j& _; b/ D
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);
    * ^  C9 `& F4 s
  37. return(adcx1);
    % M) y8 y5 H5 A! z9 X7 u
  38. }* `3 z2 h' A3 L) D: h
  39. /*获取ADC1通道1的值*/
    8 p/ t3 e: P, e: S# W
  40. uint16_t AD_Leach_1(void)
    - K/ s4 G' p* x1 [8 h6 k' l$ |$ t% h
  41. {
    1 F' c' f+ j. p9 g" Q- o
  42. uint16_t adcx2;
    0 b* |' G; f& O  _$ J% w2 D
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
    # v# v/ R, E" C% H8 v. s: H
  44. return(adcx2);) T% G" @6 U/ v; i" R. t4 o
  45. }) Q9 C$ w! Y# F9 K+ k. |$ p3 e
  46. /*获取ADC1通道2的值*/
    & Q, |+ L4 P: T1 o; e
  47. uint16_t AD_Leach_2(void); U1 M% p4 N1 B5 s- [
  48. {2 k( L% H) c+ @1 k5 Y& g# M
  49. uint16_t adcx3;$ ~$ o8 E8 e3 I8 l' e9 b
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    ! s8 q" G* Z9 A4 C' w* E
  51. return(adcx3);2 K" R( G# ?1 X/ J4 r$ {
  52. }0 t, o" l6 V) y  ^. S
  53. /*获取ADC1通道3的值*/! q3 E! T) G4 J5 G
  54. uint16_t AD_Leach_3(void)( @/ d* {; O9 ^, o% i& P0 o
  55. {
    3 X' b( W8 L0 ?+ }3 O, w
  56. uint16_t adcx4;% l0 J* S3 ~4 I2 d/ }5 l0 t5 j
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);! T" S9 g$ z, n$ c- W9 j
  58. return(adcx4);$ a  O6 K7 B0 u. V9 o# C
  59. }
复制代码

* Y5 O, W) M9 u+ ~
+ N1 K9 ^# i( k* }) Z  }: r目前就学习到这里,后续再写!
4 U8 D, G% s- K) G8 B! u
/ a6 M; {$ _# j: ?
$ x) _$ v6 P. H+ c/ T1 `- t8 [- G3 ~/ F  K9 r, s5 K) Q
收藏 评论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 手机版