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

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

[复制链接]
Bowen 发布时间:2018-12-12 15:38
本帖最后由 strang 于 2018-12-12 16:08 编辑
! W0 d% }+ N/ y7 s) p8 `( t4 t8 [. Y, e/ F7 a
编辑原因:上传代码不全,补齐代码。
! g# z3 i7 C( m4 j0 E
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员!
一、NVIC中断优先级
NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。
NVIC.jpg
下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法:
  1. static void NVIC_Configuration(void)
    6 _& m: c& \: @4 L
  2. {! a/ H1 t7 Z$ e3 w9 a" T% t- k
  3.   NVIC_InitTypeDef NVIC_InitStructure;3 {; D1 |1 W, o" e
  4.   /* 嵌套向量中断控制器组选择 */! P- j# O: P! k) v/ q/ Q: n3 a  z0 x
  5.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    $ f) x+ k8 M7 [2 ^
  6.   /* 配置USART为中断源 */, {6 Y% S- r! K7 d0 r
  7.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
    * ~+ w( m7 |) a! e
  8.   /* 抢断优先级*/2 c* P+ o) e* w! N* A* b/ ?$ |
  9.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;. o% c; L  x& ]" \! H* Z
  10.   /* 子优先级 */: K" ?/ ]7 p( K& d, O
  11.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    1 c4 D+ ^' }7 @$ O( h
  12.   /* 使能中断 */$ G5 d/ R% K1 C: V, t9 J: t9 e
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    2 \% T2 |; B; k% o( h! g
  14.   /* 初始化配置NVIC */
    / ^0 r8 x, [2 h$ Q
  15.   NVIC_Init(&NVIC_InitStructure);
    ; n, n# M8 W2 p6 N4 E! h
  16. }
复制代码
二、DMA---直接存储器访问
0 Z( K! R1 b% b6 E& C0 j/ J
DAMDAM1DMA2两个控制器,DMA17个通道,DMA25个通道。
DMA.jpg
DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。
1. 串口DMA配置:(从存储器到外设)
  1. void USARTx_DMA_Config(void)
    1 y. U: a# i9 [8 I6 U) g8 N' D$ _0 w
  2. {
    / |3 y8 ~, s0 v$ I; g4 h+ R: j
  3.         DMA_InitTypeDef DMA_InitStructure;5 F$ a; m  Y3 \& _% y
  4.         // 开启DMA时钟
    ! b0 g. D) H6 s
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    8 \2 e6 C# U7 Z3 Z7 _2 ?
  6.         // 设置DMA源地址:串口数据寄存器地址*/. l) `% E+ [4 Y" s# v
  7.     DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;5 W6 C6 z( j7 B% x" f# H) r
  8.         // 内存地址(要传输的变量的指针)# |9 l5 a3 e/ w, Y. y8 m0 D$ z
  9.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
    ( _4 Q( G" Y5 z& ^
  10.         // 方向:从内存到外设        6 N; I# U" @5 o2 ^3 `$ E5 a& V
  11.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;" w8 G! r3 P$ @
  12.         // 传输大小        / o6 A% [: r8 ]- u7 R) [% z4 X
  13.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
    ( J4 V! @) `+ W
  14.         // 外设地址不增            - l2 `& l* G/ U; J
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;% |7 ~5 d; P4 V) `7 I$ ]* z
  16.         // 内存地址自增5 ^( C' g3 c/ E% u6 n9 f+ u
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;6 [# r8 F. h6 S) g; i
  18.         // 外设数据单位        * b% v3 c1 Y4 v2 ?$ U5 _; N, S4 f
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;# B% _, }/ w+ o
  20.         // 内存数据单位
    1 o6 ~+ L6 Q5 N# @8 i) ^! H
  21.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         . G6 z; O, M: U  f6 {
  22.         // DMA模式,一次或者循环模式
    6 A: V& [' o- x2 a+ s, l
  23.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;( E8 j& Q) t( b* l# [* o+ K) W- y
  24.         //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
    , F8 D6 i+ b6 F8 z& g4 k
  25.         // 优先级:中        , d8 D& g$ r- `
  26.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 8 v' G$ Z* \! u) A8 r
  27.         // 禁止内存到内存的传输0 f. ?9 w* ~6 f: k
  28.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    ) _" f/ A3 a2 F
  29.         // 配置DMA通道                   ( b& I9 }: R1 u0 ]+ @
  30.         DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);                ! j9 h6 k- |" S: R5 s# u' J2 C; b
  31.         // 使能DMA4 v/ t; d9 G  Y% K2 d% X3 t+ [9 \0 e3 m
  32.         DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
    2 G" Q+ S* Y# ^0 L9 Z
  33. }
复制代码
2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC
  1. u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址- U/ `% @8 e- d( t
  2. u16 After_filter[M]; //用来存放平均值之后的结果2 Z( N- d& t3 s  v7 B/ r$ A" n" n2 X
  3. 9 M; r* L: n: ]
  4. //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
    3 _1 X8 W$ ?) O
  5. static void ADC1_GPIO_Config(void)9 f5 W5 x6 J6 {- @3 w+ L
  6. {4 A4 N3 `1 _" {* r
  7.         GPIO_InitTypeDef GPIO_InitStructure;' M$ M! W' f+ A  I. w
  8.         
    . E" [" o& @( T* L
  9.         /* Enable DMA clock */6 Q( s3 p8 D/ m/ X
  10.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
      [' v6 j9 z7 M/ X' W
  11.         ! M- M( @; J! Z2 Z
  12.         /* Enable ADC1 and GPIOC clock */+ a6 b4 }" g) o4 l' w: W
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    ' E' S- a0 h! ]& A, B* I$ u
  14.         
    8 _( v* X5 ^* N- R! t" D
  15.         //PC 作为模拟通道输入引脚                        
    ( ^9 I4 `5 S, f  a! Y  R- N8 }
  16.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    6 k% A, i, K/ T) L; i& A5 o
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                ; C6 Y# S  f% @1 V4 o# q
  18.         GPIO_Init(GPIOC, &GPIO_InitStructure);        9 b( `+ v3 x& _+ ]
  19. }+ R# t3 p8 `( R" y7 y2 _, `
  20. ; E( l: K# m1 W- N( F/ m
  21. //配置ADC1的工作模式为DMA模式
    ' X1 j0 r5 x: f: I6 b
  22. static void ADC1_Mode_Config(void)5 o( R: j8 I3 f4 I% Y, l8 p
  23. {" A3 \- t: V$ a$ P5 T
  24.         DMA_InitTypeDef DMA_InitStructure;5 M) w6 {* s& Z) V" ~$ {
  25.         ADC_InitTypeDef ADC_InitStructure;# R; b7 W# ?5 V) g
  26.         
    8 P) _. m) \! D, ^; f% @
  27.         /* DMA channel1 configuration */3 ^9 x, k) |3 c( u/ E$ r. ?
  28.         DMA_DeInit(DMA1_Channel1);9 |% E7 v. h7 P: W; x
  29.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
    % `4 g! b' I! D
  30.   l1 g5 ?% G& S( J; o
  31.         //内存地址  
    + {& g. c/ ]" s6 c. I( q" r
  32.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];% [" i1 R1 @% J, ]# }4 e5 V
  33.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    + |! v! y0 v1 u8 [
  34.         DMA_InitStructure.DMA_BufferSize =M*N;
    : k( F9 Q8 F8 |9 ^' _' W& U( c
  35.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    . ?, @+ }" n" E: W( N
  36.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    / X2 }5 q9 i4 H( W
  37.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;+ b4 U0 W: z; x$ F1 j
  38.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;( P8 w' C  ?/ H* C' M
  39.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;' j8 L) V6 G# b" ~
  40.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    . e$ y$ C, V5 Q  j
  41.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;4 ~3 t" f0 W- F" `5 f9 |0 T
  42.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);# D( [: y8 K2 l: {# p- r7 x2 w
  43.         + V5 A: ~& G' F% T
  44.         /* Enable DMA channel1 */& \9 p4 z/ `  s' `
  45.         DMA_Cmd(DMA1_Channel1, ENABLE);2 f/ ~& _: _- b+ S" R) U. b# C
  46.         
    5 M8 P& n& Y* w: U5 @
  47.         /* ADC1 configuration */        
    " J+ a; Z! x5 L1 D" H2 B- ~
  48.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    9 I! `( b% D6 }( k& u0 Y& r: f% J
  49.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;; w5 h! p' W7 i" O- w' k" G
  50.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    % D5 T6 Q4 c3 h, ~3 ~
  51.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    + a4 }* h  w9 }$ c# X$ S
  52.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;: h7 t+ t: Y2 p2 U8 O
  53.         ADC_InitStructure.ADC_NbrOfChannel = M;
    ! \$ k' |  k3 t9 c  F0 P0 S9 i
  54.         ADC_Init(ADC1, &ADC_InitStructure);  R2 R+ P9 H& I) h7 h( D
  55.         ( @- S* D/ r* m8 ~3 b6 L3 j+ k
  56.         /*配置ADC时钟,为PCLK2的8分频,即9Hz*/
    ) e$ I7 I& e/ w) Y" |' b
  57.         RCC_ADCCLKConfig(RCC_PCLK2_Div8);
    * m* F) x/ K$ u/ g* z
  58.         /*配置ADC1的通道11为55.        5个采样周期,序列为1 */
    # U5 V+ Y# R1 |+ v' j5 o* ^
  59.         ///ADC_SampleTime_239Cycles5     ADC_SampleTime_55Cycles5
    0 ?2 Y! W$ A! c  k6 u
  60.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);4 Q* R* \- Q; i. N- O2 y
  61.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
    3 Y+ M; d+ F; b% K. h* h: b% T1 Y
  62.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);  
    3 ^' V/ x9 X" y: x  @" \
  63.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);
    , W3 [+ {7 g9 h8 Z4 z9 n
  64.         9 O9 n- C4 }) j. z4 @9 a# c
  65.         /* Enable ADC1 DMA */4 F3 Q1 |5 y0 l" J
  66.         ADC_DMACmd(ADC1, ENABLE);
      A0 Q# x/ k2 y6 h, U1 r$ j
  67.         
    ; u/ ~/ @/ l+ C! J& g7 W9 c
  68.         /* Enable ADC1 */' h! O& v4 k8 r
  69.         ADC_Cmd(ADC1, ENABLE);/ \! n% `( h+ r
  70.         & }) T4 W& F  _) J: ]8 z
  71.         /*复位校准寄存器 */   
    5 g- v) S3 u+ W
  72.         ADC_ResetCalibration(ADC1);. K1 ], c  }6 @" e0 C2 B6 i5 E
  73.         /*等待校准寄存器复位完成*/4 A1 l4 Y6 q) M) t5 s4 x; ~
  74.         while(ADC_GetResetCalibrationStatus(ADC1));
    ; R3 l# p* C1 N' u9 b
  75.         
    9 `& s) c6 s5 L
  76.         /* ADC校准 */7 R' k6 a$ E6 R+ V& Z! U
  77.         ADC_StartCalibration(ADC1);
    + g& W- D: d& g% S# N% Z0 Z
  78.         /* 等待校准完成*/
    9 B9 j" P& g7 I8 _
  79.         while(ADC_GetCalibrationStatus(ADC1));
    0 Z' H& e+ r  V
  80.         
    , r* m! m% U& W; e! L; g+ D
  81.         /* 软件触发ADC转换 */
    $ X' h. @4 l; ~7 @
  82.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    . I+ m. u# ^6 u& X! z+ x
  83. }0 L' v0 b0 r! ~' q; d
  84. /* ADC1初始化*/
    % c5 j3 Z9 D" L8 A6 x/ U1 O; M( j2 w% J
  85. void ADC1_Init(void)
    7 {2 R: `# |9 ?5 P
  86. {& e( Z# h- C7 Q. f& ]$ l, j  j5 k
  87.         ADC1_GPIO_Config();
    % t. b) [: x  m; t
  88.         ADC1_Mode_Config();
    3 o0 i  h# ^1 I' s+ l
  89. }
复制代码
  1. /*ADC滤波*/7 f' x7 \" {2 u! B( Q4 g  v
  2. u16 MultiDMAGetAdcTest(u8 ch)6 [1 D# L$ W7 L% A+ b4 V
  3. {
    + h# r2 M+ l. W/ f
  4. u8 i;+ ]3 E3 y/ v% k( C) E* J
  5. u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;1 T: Y* G# |  \
  6. volatile u32 ADC_Data;1 e9 L0 j+ I" v2 D6 {8 C+ k
  7. * B9 D$ C2 I8 B5 z( D
  8. ADC_Data=0;
    ' ?" w* Q! D7 }' J5 G5 F
  9. - _: {$ g& k6 c; p: ?
  10. AdcMax=0;
    / _+ ]3 s3 h0 f* S8 ^2 \
  11. AdcMin=~0;* A" ~) ]* I$ U- Z/ d! n
  12. AdcSum = 0;. a% G+ y- L2 n; H3 N
  13. Adc_temp = 0;  r* Y# D; b* ^; c0 q& J

  14. 2 q1 }$ O: A8 P
  15. for(i=0;i<34;i++)9 \( e# F$ @, ]6 N8 b+ n
  16. {
    5 |) Y# ?1 q" j  z, C: _- @( Q
  17. Adc_temp =AD_Value[i][ch];' i+ t0 |" c/ C$ M
  18. if(Adc_temp>AdcMax)
    ! l1 L. [( `3 Z5 j$ O2 {  D! |8 B7 \2 e
  19. {
    8 d) w  j2 A- A
  20. AdcMax=Adc_temp;% G8 Y6 K% Q  \$ W" K
  21. }& H; O0 p' i2 C9 H
  22. if(Adc_temp<AdcMin), t4 _: ]" j  f; T
  23. {
    * m' H5 m. k& ~$ u- f0 P( c* f
  24. AdcMin=Adc_temp;
    ' K. r9 {+ d5 [' w/ k7 }0 N
  25. }6 i6 g4 v; S$ p# ]  _0 P' i- |$ b
  26. AdcSum+=Adc_temp;6 J, j8 u) R4 F% G8 _3 [
  27. }
    % U& n) N- |, R, ~1 y  o
  28. AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
    7 [0 I, o2 ]5 n9 q. H" ?3 k
  29. After_filter[ch]=(u16)AdcResult;7 g  O9 F1 h- @/ e4 b8 ?
  30. return(After_filter[ch]);
    1 R1 I* b& G# g1 R& K3 a  C: O
  31. } 6 l8 V  U, M1 V% I% |* K( y1 Z( W8 }5 G
  32. /*获取ADC1通道0的值*/
    & }. [9 R+ E) }7 q5 W% T
  33. uint16_t AD_Leach(void)  w* c: D. d/ _
  34. {+ w0 c% M, v- u$ y+ B
  35. uint16_t adcx1;- P- ?; d' F2 k+ J; @
  36. adcx1=MultiDMAGetAdcTest(ADC_Channel_0);$ q+ B9 J! |6 h* N
  37. return(adcx1);  _- S" C% H" F8 c( d; b
  38. }
    5 b4 t( L1 j( p2 S" d6 f
  39. /*获取ADC1通道1的值*/
    ! Y6 q1 _7 T, s( V' V7 f8 V( h
  40. uint16_t AD_Leach_1(void)
    4 o: z. t5 C. o' L" O2 `) J) K# ]
  41. {1 D, C7 D  g. K  \
  42. uint16_t adcx2;. j1 f, F. E) v; N- q
  43. adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
    ) ]! R/ P; N' D& L( U
  44. return(adcx2);
    2 d  J, k  i5 @: S4 V" M
  45. }9 x6 G( p3 T" ~% f7 @+ n
  46. /*获取ADC1通道2的值*/
    . v6 c. S. x' y1 ~3 ?- p8 N/ n
  47. uint16_t AD_Leach_2(void)3 O" }1 i( D' Y3 u
  48. {
    ( z, x; g7 D* i7 ^# |: n
  49. uint16_t adcx3;! {. p0 M" B* F; z/ ^$ n  I# e
  50. adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
    1 W! R$ t& b. X' ~% y( i: t1 E
  51. return(adcx3);
    2 v$ P0 W1 ~6 B+ j# n) j
  52. }$ t1 G& U; A6 A" R& D$ j. x
  53. /*获取ADC1通道3的值*/9 S7 D2 I/ @! L# H  `8 o9 p, L, T2 `
  54. uint16_t AD_Leach_3(void)& O  I& P- M3 ^: q& @7 ?1 j
  55. {
    ( l' p# |+ R2 Z1 r) |( Z
  56. uint16_t adcx4;) x6 _" l# r* C7 V, v
  57. adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
    ) W7 a$ v( n3 }. {' Z" v
  58. return(adcx4);8 p, J# o' F4 j' g
  59. }
复制代码
1 z3 f' p) W# o7 l

! g9 h& X& ~( e* k2 a5 {" [+ m: @目前就学习到这里,后续再写!) T$ ^& w5 j* e5 c& b: g
. V9 q4 [5 w% _* q# O; [
7 R  I( G7 x; I, E

2 q9 p% D7 s3 Z/ \. [# 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 手机版