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

stm32f405/407的两重 ADC同步触发模式+DMA 配置

[复制链接]
sailor.wu 发布时间:2015-11-2 22:08
双重 ADC 模式:
: d! z& h* k5 C# z8 s9 v( a; Q( N在 ADC1 或 ADC2 转换事件结束时:6 I7 ^7 X3 ], ?9 T1 k  F
● 会生成一个 32 位 DMA 传输请求(如果 ADC_CCR 寄存器中的 DMA[1:0] 位等于
+ D# `) f/ f* P2 P: {0b10)。此请求会将存储在 ADC_CDR 32 位寄存器高位半字中的 ADC2 转换数据传输) z& i& b/ x% \4 C' ~
到 SRAM,然后将存储在 ADC_CCR 低位半字中的 ADC1 转换数据传输到 SRAM。; B' }, [9 j4 y" L4 K
● 当 ADC1/ADC2 的规则通道全部完成转换后,会生成一个 EOC 中断(如果已在两个 ADC
1 \: G6 Y& t* |- q) b; C: J! t接口中的一个接口上使能)。- S: @5 P: W2 a) P) a+ q
8 t! `) U  l2 W
转换示意图:
, r! h  \+ V# `. _/ @7 c: Q
& Q- w9 m6 S3 w8 p9 U5 H  l; g% [* B

转换示意图

转换示意图

: R0 G0 ]3 f4 b6 x7 N1 q, f; {! W+ O; ~
配置代码:4 D5 ?' ?) a& ]

+ S( Q5 c( {6 ^4 G0 o#define ADC_CDR_ADDRESS    ((uint32_t)0x40012308) //适用于双重和三重模式的 ADC 通用规则数据寄存器( ADC_CDR)7 V, L3 l9 u- F! A

$ o9 W9 G4 P  m& S( Y9 ]2 ]1 F
, o/ y/ a& B! p& s9 mvoid Init_ADC12(void)
8 [4 E0 ]/ ?* z0 A# R  R$ k# v{
/ u" s* x$ C0 @9 X) X  GPIO_InitTypeDef  GPIO_InitStructure;1 I% R: w1 E9 H4 N# `
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
! U' \" H+ [# c, z2 f  ADC_InitTypeDef       ADC_InitStructure;5 ?4 l3 h$ i, o9 Z0 }% B& u
   
6 C9 R7 B( H0 \7 @( b8 k# h# Y  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
5 S( U3 o) ~" }4 c- U  
. t$ H+ W3 O- T5 b  //先初始化ADC1通道 IO口. Z$ S, `( `# U9 X5 J  i  X: h. R
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;;' _3 m: \8 X. H' ^( E* u1 N6 N/ u& X
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入7 e) H/ @- e8 p( H6 L
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//不带上下拉6 \2 `, [2 y7 }9 t
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化  
/ ~# K# m  e( s- S# N; c7 e% i  0 F6 r$ B) x/ F- d/ s! l+ L/ w
0 R: e7 L( ^; H2 S/ o- Q, i" e
  /*****************************************************************
$ Q7 I) ]# K- F% i: m% y) [8 v  *************************** DMA Configuration  ******************
2 A; [2 B3 ~# c! @7 A8 |  *******************************************************************/
: T" m. c+ o7 I3 o5 |  # }' b* G7 o- i2 V  \
  
7 l+ L' G$ j9 B7 L7 J  ( T/ y5 ^! e7 @8 \" s& A3 A* [. u
    DMA_InitTypeDef DMA_InitStructure;; a7 |: x! o1 X% t" e, M) l
    /*首先开DMA2时钟,由407参考手册-RM0090-Reference manual
( T. y( C) k- x) S" _6 i7 m# e: \     *165页可知,ADC与DMA2映射,而且DMA2挂载在AHB1时钟总线上*/5 r7 e3 m* H+ k* u( w7 ]: R) Z
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
1 V) _' H. y( |. z& i: s    3 R$ T6 G# f5 Q' k9 [2 s. t4 h* Z
    DMA_DeInit(DMA2_Stream0);: Z! y7 O1 w% d: |7 z7 E
    DMA_StructInit( &DMA_InitStructure);2 t) B# l8 y& }* {
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;                     //选择Channel_0' ^5 m6 D4 Z7 x- z
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS; //数据传输的外设首地址,详解见上
+ {8 R" ~( a7 e5 @2 n    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&adc_result;   //自己定义待发送数组的首地址,要强制转换为32位  ^( {2 S/ c/ Z+ ^0 a9 h" y
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;       //数据传输方向选择为内存->外设+ N1 O" s$ U* Z, o- w, D* d+ X
    DMA_InitStructure.DMA_BufferSize = 2;                      //传输数据大小为16,单位由以下确定,大小要配合定义的数组类型和外设数据类型
2 ]! h3 s2 t7 o3 T# a    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器自动增加禁止,因为这里只用到了DR数据寄存器! ]5 M! p7 c5 ^/ c( @2 ]& {
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         //内存地址自增不允许,因为只存取一个数- ~; F1 p: l1 _
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设的数据大小
# K6 t0 |/ N9 S/ ~8 x    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;     //这里也选Byte
& \# _! a5 x" B: S' z/ ]    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;       //DMA传输模式为Normal,如果为Circular,将会循环传输* n' z3 g  ^7 m
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;   //优先级为VeryHigh
8 h8 a3 F8 I( @+ V- C    DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;
& L4 K8 K& ?" v8 T8 u7 B    DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;3 D" E5 W+ @2 A7 p. A2 K6 d
    DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
' H: O9 W- y8 i( v2 r) z6 f    DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
# S+ F0 |4 Z" Y' a/ s2 Y% I    DMA_Init(DMA2_Stream0, &DMA_InitStructure);
3 s8 E! X6 m/ ]; }* U# m, M    * p0 y$ a# ~9 ^0 q6 b7 @* F

% ]' W* T. I( x8 }* R% r6 V, C//    NVIC_InitTypeDef NVIC_InitStructure;
! l. t8 d6 [& ?& H4 A; o- \9 X" N$ K//    /* DMA中断配置 */) R2 s; H3 L7 y+ i
//    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;      //嵌套通道为DMA2_Stream0_IRQn5 {- ]8 w" z3 l0 @
//    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为 1
# J6 W" \/ K9 s, [$ f//    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          //响应优先级为 0, n; _$ w/ Y( t, Y% L; X
//    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //通道中断使能) O0 t+ |; N. H* Y8 W
//    NVIC_Init(&NVIC_InitStructure);6 F  h: I/ \* b: B% _- Y+ T
   
9 _& _8 c& q% J. O2 J   
% X8 j, e: t* v1 R2 `$ Z7 m  d    0 R1 M! p9 l; ]7 x
    //使能DMA2_Stream0通道$ C7 K" X9 k" X( Q
    DMA_Cmd(DMA2_Stream0, ENABLE);% r  a: i3 [* L) x3 i0 R2 `6 ]
   
/ }' V; T/ T& u6 c4 ^
' y1 T  z& ]' O+ r& U; G; J8 ~//    /* DMA中断开 */
  m+ g  u- K; }( ?1 S//    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
6 @. ?% k. E( Y5 ?/ T" C; H    ) r4 l* m. i3 R5 P* W2 f: X
  /*****************************************************************
0 H& P: D6 M7 g* W$ f  *************************** ADC Configuration  ******************
, `" Y  }( n" |. B" q  *******************************************************************/- M5 p/ F; o: _$ k- O2 _

' `, A( w/ k8 q- S  
- z. }/ ?2 j' @, u% c! J4 W  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟
. [* Q) b. p4 a4 h  I  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); //使能ADC2时钟; ?( J# K, O. b) O0 @9 Y: ~  l' x
# A$ Q- d) b4 H0 l/ F' `
  ADC_DeInit();0 G# T/ u& [3 U5 T
  //初始化ADC Common- ~: ?) O4 B5 ]4 K' ^9 y, R' m
  ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
1 J! h6 @+ i% |; i- A# F/ a* p  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟7 M* C5 s% L+ f, B) J
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; //DMA使能( H, X; ?7 W. [8 u3 F
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
* N& E5 q7 g5 ]1 f+ T2 F* o  ADC_CommonInit(&ADC_CommonInitStructure);//初始化
: @; k6 i. E" e5 W3 i8 Q: C    " w  `, ^! G5 x
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式  S4 g$ Z7 P; y  P2 Q( F
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式    % |( {9 H; E% ]- k8 O- v
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换& r" A# j% M$ n
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
: l+ W  P2 ^1 N$ _$ [$ o  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐    , c  s$ D  L% N" V- ~( a" B+ b8 @
  ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 3 E# F7 S* d! f
  
! J$ E% X# x7 ^: `4 g) }2 w  ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
+ T$ H8 ^' P% w+ b9 m  n$ R    2 c6 ?8 m7 D; W5 f; f
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式) U; s* J7 V, ^; ~- d4 t$ v2 j
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式   
6 F- K2 D9 x+ i+ o8 `  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
! B# N. {% ]0 s) s" H  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发6 S/ z" i' N- m) Q
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐    8 @' J  p  X9 b( L
  ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1
* [2 h6 J+ z  ]# O% @' A4 M  6 r7 t5 K$ ^+ r/ F) z/ y! e: H
  ADC_Init(ADC2, &ADC_InitStructure);//ADC初始化" S" N+ I2 B' _! Z0 Z: b5 {: |
  
2 I* H- y  m. p/ Z+ n- F- Z5 t  5 I: B8 j# [9 i& Q+ i; _
  ADC_RegularChannelConfig(ADC1, ADC_Channel_0 , 1, ADC_SampleTime_15Cycles);   
" _" j/ f( j. [9 \' w' \  ADC_RegularChannelConfig(ADC2, ADC_Channel_1 , 1, ADC_SampleTime_15Cycles); $ s3 ?6 B. F$ A2 F8 G' `; T5 c6 h
  
& i* \6 C' D! F5 J# ]  /* Enable ADC1 DMA */
, w9 t2 k( C: T5 Q  ADC_DMACmd(ADC1, ENABLE);
$ K  a7 w" M$ h3 }+ ^  
- S2 h$ u# z4 a1 l- k  I  G- J) v    ; M$ ~3 |# K. R: ]1 N% [
    /* Enable DMA request after last transfer (Multi-ADC mode)  */4 z  h) T$ [4 B7 w8 z$ j
  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);  m' h& m9 B' W/ b% J4 l4 G
  
6 K3 V/ @/ L, |* a7 T$ O6 w, K" h  9 [5 _' T7 r' _
  ADC_Cmd(ADC1, ENABLE);//开启AD1转换器   
3 }5 a) p4 {: r' Z4 [  ADC_Cmd(ADC2, ENABLE);//开启AD2转换器    % W0 ]% s. [: @9 B' C* o- O

3 W0 o( C* t) j" G/ Q# ^

转换示意图

转换示意图
收藏 4 评论12 发布时间:2015-11-2 22:08

举报

12个回答
disheng4688 回答时间:2015-11-3 08:36:56
谢谢分享         
dear祝子 回答时间:2015-11-3 08:50:24
给你32个赞!!!
me浩 回答时间:2015-11-3 09:03:20
谢谢分享啊
我是你的e 回答时间:2015-11-3 09:05:58
感觉你的头像很酷,内容也不错!所以给你一个赞
钊钊 回答时间:2015-11-3 09:28:38
看了下,楼主的思路还行,但是我不明白这么做的目的,或者说要实现的是什么,恕我看不懂呢,能稍微解释下吗?
sailor.wu 回答时间:2015-11-18 18:31:49
电机FOC控制,需要采两相电流,ADC采样时间短的话,调制度就可以放大。
wz002 回答时间:2015-11-20 15:55:16
:)
ataudio 回答时间:2015-11-20 17:01:41
与ADC 相关的都要关注。
‪931581159 回答时间:2017-4-7 13:43:17
本帖最后由 ‪931581159 于 2017-4-7 13:44 编辑
3 s% @4 F* S, S$ E+ S2 f! w7 ]
/ ~7 h0 w5 K6 S" q* v  t内存地址自增不允许,因为只存取一个数# M( s5 k+ w+ }) W, q9 n
这句注释错了吧,明明你设置的是DMA_MemoryInc_Enable
: p0 x  S9 {4 @0 X& Y9 |/ d虽然我也不知道到底是注释错了还是代码错了6 y) `4 g. F2 L# y8 Z1 @2 J
……& q: D) X, M+ z
多看了几段,为什么注释和代码都是自相矛盾?. o+ Y+ I( _: J( h" P
alisa123 回答时间:2018-12-16 23:51:18
楼主, 我看  你分享的代码中,把关于DAM的中断的部分注释掉了, 请问这一块开DMA中断的代码是OK的吗?你有测试过在DAM中断中收数据吗?
panze 回答时间:2018-12-25 16:33:07
谢谢分享啊
lxl8511 回答时间:2019-1-10 16:30:29
谢谢分享谢谢分享谢谢分享谢谢分享谢谢分享谢谢分享

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版