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

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

[复制链接]
Bowen 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑 . \, a+ r# {9 u9 \5 [

! ^5 k1 N/ c5 B* _4 Z
编辑原因:上传代码不全,补齐代码。
7 d8 B5 d- z% L# g  d- R. |
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)
    , l& L5 I& b) Q) e' J9 c0 g: O
  2. {
    2 J+ x+ f' u% k9 \4 m
  3.   NVIC_InitTypeDef NVIC_InitStructure;% }; r: Q' }( z' J4 ~
  4.   /* 嵌套向量中断控制器组选择 */
    * w0 x- y4 u+ G6 ~
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    1 l/ h0 }! {3 C) G( `1 [  R$ j
  6.   /* 配置USART为中断源 */0 L! v' l, s) U# I. C, \
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    : @$ H9 M2 _: ]- J% @
  8.   /* 抢断优先级*/
    ' Y4 m+ X' E! ?& w5 o
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;2 G: t  u% \9 |3 g! _# @# l( y
  10.   /* 子优先级 */
    ! o# _1 R' ?; N0 M7 O
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    ! W( ^  z, R. d& J9 @5 F
  12.   /* 使能中断 */
    + y8 r: O/ ~4 p; S. t8 K
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;- l) W1 n0 r+ }! s0 c  c( a
  14.   /* 初始化配置NVIC */. A, Y* N2 _' f
  15.   NVIC_Init(&NVIC_InitStructure);
    3 [8 h5 j0 A% p9 P/ n9 G
  16. }
复制代码
二、DMA---直接存储器访问

0 L* b. U/ ]% Q( O* Z0 d0 B- w, M! V2 r
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)
    4 f- Z7 T1 V9 |/ v/ w" p
  2. {
    % ?3 G" o" k) n7 ]
  3.         DMA_InitTypeDef DMA_InitStructure;
    8 e3 S3 }$ C2 E! Q% `* |
  4.         // 开启DMA时钟( _7 S, R" P" v* C6 ]! Y; P
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);. g. e5 |  A7 P/ x
  6.         // 设置DMA源地址:串口数据寄存器地址*/
    4 b0 s7 X9 B$ \5 H2 b0 {8 Y% b8 c
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
    $ U3 F- c+ x: A0 ?, R' b
  8.         // 内存地址(要传输的变量的指针)7 z2 z, @+ W8 P
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    * v* a& c/ k5 H2 a  a& X+ w
  10.         // 方向:从内存到外设        
    7 V7 N  z: d5 ~+ ^
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    ) f  V, K8 U7 w( b
  12.         // 传输大小        0 Q8 W2 `! X% h6 Y/ Z! x# v
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    ! K) ~* w0 E1 x/ D
  14.         // 外设地址不增            6 Q2 V- [7 D  {3 q, M
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    % o- Y& l4 a1 n4 E
  16.         // 内存地址自增
    $ N% Y/ @4 j6 F/ b
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  u  N1 t5 U* X, o
  18.         // 外设数据单位        
    ) t( E0 G1 v) S) X
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    0 I" c0 k& _; P( f4 U  w* x: Y
  20.         // 内存数据单位+ r9 I* n, F4 Q1 M" k& `0 ?  F7 O3 T
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         
    * L6 H+ Z4 K- d
  22.         // DMA模式,一次或者循环模式
    7 G' j: O- s- Q  Q  y
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;3 Z/ w. W7 `8 h& V$ J
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
    8 P! K5 y8 o) A2 G0 d. q
  25.         // 优先级:中        & u: u2 U  U. m* X( I8 \
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 1 C/ f" R4 M: e
  27.         // 禁止内存到内存的传输; U# ~& f+ v5 L& W1 C! T
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    ! \- W7 F+ O& H+ h4 Y
  29.         // 配置DMA通道                   # V' i7 R  G8 u2 x; g! a
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);                , n9 Z' J5 w' n& a
  31.         // 使能DMA0 F& a  W( \5 W! G
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    5 e$ r6 E$ O$ C5 O
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
    0 s' I  R# C# x/ V* A& @& ^1 ?, c- B
  2. u16 After_filter[M]; //用来存放平均值之后的结果
    * _0 ?3 }) i; `, Y
  3.   [/ B) o$ P7 C. R
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口8 e' R( m& n7 U, `9 |  |
  5. static void ADC1_GPIO_Config(void)
    7 y, l! X& |( y; l" K$ t( y0 u
  6. {
    " ]( q( n' ?- j; K, ]. M# b8 S7 v; P
  7.         GPIO_InitTypeDef GPIO_InitStructure;
    ! ?. f8 A- W" x& G6 {
  8.         
    ' s, [; }  x) [; \4 E
  9.         /* Enable DMA clock */6 d) |- H" [% D7 Z! n/ h0 x
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);2 m) x+ N; U2 E5 a# ?. D; p9 C
  11.         * T1 A, f1 z! M$ k
  12.         /* Enable ADC1 and GPIOC clock */
    5 v1 o* C- R! t  B# y  c
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    + F: }4 B3 ~8 G# f. U# A
  14.         ! X5 x3 F+ Z+ M3 P8 J5 b, C9 H
  15.         //PC 作为模拟通道输入引脚                         6 s. ^0 t9 k- _3 n8 o& l( s
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    & n8 r- @! y; a  o: Z; f
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                : h' e2 Q2 D5 y1 E
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        
    * i4 @3 ~, }) _1 z. y0 B
  19. }" M, P" B; ]" D8 g$ n+ @

  20. ' M0 n/ g* S: D8 u' F" a
  21. //配置ADC1的工作模式为DMA模式' n9 y, T5 H8 w4 S9 f$ W/ A( C6 S
  22. static void ADC1_Mode_Config(void)
    * `8 m: j) I4 F
  23. {5 o2 X1 `/ }! K" r7 i8 D
  24.         DMA_InitTypeDef DMA_InitStructure;8 E% C& q/ c6 s+ d7 o+ n% I
  25.         ADC_InitTypeDef ADC_InitStructure;7 o3 K. ]& @% ?3 m+ s" l" Y
  26.         
    1 Z5 e( W% |9 Z( Y& t5 f+ e
  27.         /* DMA channel1 configuration */
    ( n2 T7 Q- ]5 b
  28.         DMA_DeInit(DMA1_Channel1);, \7 Z/ ?) y- p+ p' M; c6 ~
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;7 ?8 U8 R6 y2 k6 p) }2 m# W7 `3 D4 t
  30. 6 K* d6 Y4 G0 C3 w5 \8 R
  31.         //内存地址  
    , o% h" b" b. m' y' `
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];  b! n, Q. w% ~* j& p0 t" d
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;: Q7 Q! ]# T9 E, `
  34.         DMA_InitStructure.DMA_BufferSize =M*N;
    9 @; [  y5 w( _& ?
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;6 k5 R6 M" C+ o9 u; p
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;6 O" f  Y; V5 H8 I0 J  ?
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;' [1 K0 P4 N* Y3 y, _6 \
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    8 ], N" H% L' c+ L: s
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;1 {* \8 i: v$ R# X3 {& f! t, S4 I
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;  N: r: O5 x- X. R1 M1 o
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;8 n, h# l' ?, F7 ]* ^
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    ' f" o3 A, l. M/ W
  43.         
    & z3 C, |- x" ^  a7 I
  44.         /* Enable DMA channel1 */
    2 N1 B( ?  y4 f6 m- `% {
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);
      ~/ e# W4 {- U# y. j/ u
  46.         
    % _9 Z1 R) }! Q( d: m6 l
  47.         /* ADC1 configuration */        
    0 j+ E  m# ^) w; T
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    , {4 j2 z$ e5 e. Q! _9 T/ h5 [
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    $ ~% X9 b" e5 h, O9 O
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    , |5 f# b. n& i. L0 P; X* U
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    2 k/ S# _4 H, g$ L- t- r- `. u% ]
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;' f1 k/ A. L7 R% x" R
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;. T& F4 u2 ]! |
  54.         ADC_Init(ADC1, &ADC_InitStructure);
    # b  o3 H9 |* W# \
  55.         
    # w& a* |: ^! h2 ], I0 g
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/- J( C1 M. @. O, U2 S4 T( ]
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8); # |% g. p3 F4 ]( q; ~% u6 R
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */
    * y3 ^* Z+ e; K1 I
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5: o! s% Z3 n3 `1 |( `7 c0 V1 f* M
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);  g8 k( l' i- V' C, P
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    . {0 E- U/ R7 Z* R
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  
    " k, Y4 f. U6 l# \( Y
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);8 H' f- ]2 G3 M; F
  64.         7 R% b5 L; G4 E/ u
  65.         /* Enable ADC1 DMA */9 h/ w8 M6 O% q* P( P# |
  66.         ADC_DMACmd(ADC1, ENABLE);
    * V, t& y+ n& y2 U
  67.         
    # z3 f; F" d) _
  68.         /* Enable ADC1 */
    - p# ?; j$ y/ P" V- Q- Y+ S+ B* n
  69.         ADC_Cmd(ADC1, ENABLE);) `% _: D8 D" d* g7 w5 `) y+ @  M& I! y
  70.         ' M2 c, H8 p, B' [, X% H9 Y
  71.         /*复位校准寄存器 */   6 J9 \, b! U* B* s7 w: j
  72.         ADC_ResetCalibration(ADC1);+ }2 X3 F8 e# B- {6 B! g
  73.         /*等待校准寄存器复位完成*/
    + ~. E$ y# B5 b* T3 R" V- [* v
  74.         while(ADC_GetResetCalibrationStatus(ADC1));  O# m. _2 m5 T
  75.         & e2 h( z) |$ R; g/ c
  76.         /* ADC校准 */
    . P' T$ p" i0 [
  77.         ADC_StartCalibration(ADC1);
    1 b$ q: D6 g* @# F# ]
  78.         /* 等待校准完成*/
    ! ?: Z! i; \! R  M1 t3 N
  79.         while(ADC_GetCalibrationStatus(ADC1));
    ; t+ x/ o. r- u- z
  80.         - P+ o9 U% r$ I. h  `1 u+ h; [; d- S
  81.         /* 软件触发ADC转换 */
    2 P, r, o2 v  A) r$ X
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);7 T* q7 I# V) [; F4 {* A& \
  83. }$ ~5 N: k+ r) ^' l
  84. /* ADC1初始化*/   r. F- }# `% P; q8 B0 Y1 f  S+ b
  85. void ADC1_Init(void)5 U( G  F# ]! K1 m
  86. {" K4 ]0 V/ l% H7 M: S* j7 @
  87.         ADC1_GPIO_Config();
    ; D  A4 M/ K+ d
  88.         ADC1_Mode_Config();
    : o! g8 M6 ^: ~; e( s
  89. }
复制代码
  1. /*ADC滤波*/: X8 m: Z0 q1 h$ Q; l  g
  2. u16 MultiDMAGetAdcTest(u8 ch); x: m; ^' Z0 b1 l( b2 f8 D9 O  g
  3. {5 c1 R' \" ^* [- q
  4. u8 i;
    9 q- i9 ~: r- \
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
    ; w& W0 D9 L' k+ q- d4 |4 C
  6. volatile u32 ADC_Data;
    5 e" T% j9 `6 d' o
  7. , C  R5 r3 i% M0 a. I: B
  8. ADC_Data=0;
    % Q. d" T- W! o7 |& {
  9. . S* D( X: S2 C0 A0 p
  10. AdcMax=0;6 _( K& L4 \# f, F
  11. AdcMin=~0;6 X9 {# B' F' {& p% l" n5 A
  12. AdcSum = 0;6 a2 R% p- P( p% d+ j
  13. Adc_temp = 0;) g( v! V3 ?, n' c% a

  14. 6 ]8 Y! \: c2 q* q9 v5 g" }
  15. for(i=0;i<34;i++)
    ) [' u7 k" u' R2 r
  16. {
    ! t# s' Q4 n. j
  17. Adc_temp =AD_Value[i][ch];! p6 N9 K2 W( }3 `; |, r9 l
  18. if(Adc_temp>AdcMax)
    + S/ f, O4 \- Z2 ~& _$ b
  19. {
    ) g2 r1 ~8 _2 G
  20. AdcMax=Adc_temp;# y& `8 o( s6 E0 C4 X
  21. }
    ! R8 `7 R" j+ S* B9 J$ b. q" _
  22. if(Adc_temp<AdcMin)0 X* P4 `6 `( A
  23. {
    ( n. O/ K' x* `& I. z
  24. AdcMin=Adc_temp;
    # j2 {7 t( \: L
  25. }
    2 W0 a  q" C* H( T
  26. AdcSum+=Adc_temp;& d  |1 A( e4 O! I) u" u  z
  27. }: l% S6 R. B1 h! I1 q. M
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;* z3 D' L: n) `+ R6 E$ s
  29. After_filter[ch]=(u16)AdcResult;
    . ]4 r8 ~% b/ D, E' y: G' A: `! `0 a
  30. return(After_filter[ch]);
    ( X1 }8 [2 C- t( v
  31. } & c/ L0 z1 K- E5 W5 n# n& x2 M8 P
  32. /*获取ADC1通道0的值*/6 R- z0 r8 B5 H9 W# g
  33. uint16_t AD_Leach(void)
    5 F# Y- Q. L; e
  34. {
    5 f; m0 ^6 l/ D1 [9 q3 d
  35. uint16_t adcx1;
    4 S# V) E) C& H% X- L0 d
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);
    & R& c. |3 D. Q  F
  37. return(adcx1);
    3 \7 a5 h- a( v7 d( i  t
  38. }
    , [, |- ^$ e& h9 n
  39. /*获取ADC1通道1的值*/
    8 X, \. B& |" ]; a4 W7 r
  40. uint16_t AD_Leach_1(void)8 E# l3 q  [3 z, z$ w: ^) f- d
  41. {
    . _! W3 j: P+ e# T6 |8 n: O
  42. uint16_t adcx2;( s: W  x" e% T* E  t; W6 O* y4 x
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
    - v: s; B& C+ E
  44. return(adcx2);
    : B5 u" K. T* k2 q! v
  45. }
    $ R$ ]/ W8 `( j" T' A% p2 Z
  46. /*获取ADC1通道2的值*/0 P4 k& g) Q& }3 q
  47. uint16_t AD_Leach_2(void)7 e* M2 S- j1 [* Z$ L5 L# L
  48. {( i6 J% A3 }* ]+ o
  49. uint16_t adcx3;% \* j0 ~& j" q6 p3 E
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    & }6 i8 c( Z( F' d
  51. return(adcx3);- k; F; Q2 [2 C" C3 l4 r
  52. }$ C, g- X; A! y9 N  Q) \+ `2 R
  53. /*获取ADC1通道3的值*/
    3 I2 z. |8 C# C) ~! s6 D; K2 \/ K
  54. uint16_t AD_Leach_3(void)
    . d6 |4 b8 M) |3 }* ]4 U
  55. {
    1 Q! X6 o' c0 ^/ M0 W+ U
  56. uint16_t adcx4;
    % A  n( e+ l  ]# |' e# q9 x
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);5 W. R, r" N$ H6 E( _0 n- [
  58. return(adcx4);- U3 u$ L# y: A* U
  59. }
复制代码

4 |9 _+ ?( |/ f. g% n: F
& F- T2 e: R% P& @: [目前就学习到这里,后续再写!/ J3 L/ X! p0 a. B$ g
/ k$ o9 U' X1 m6 \3 w1 t
  W. o, q3 s5 T, ]& w

  n4 j$ h+ z& 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版