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

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

[复制链接]
sailor.wu 发布时间:2015-11-2 22:08
双重 ADC 模式:
' @$ Z" @' |# u/ U- o/ N& u在 ADC1 或 ADC2 转换事件结束时:
  @) P8 i+ \6 h' C) x; g● 会生成一个 32 位 DMA 传输请求(如果 ADC_CCR 寄存器中的 DMA[1:0] 位等于& L- y7 C( z, j, C) h
0b10)。此请求会将存储在 ADC_CDR 32 位寄存器高位半字中的 ADC2 转换数据传输
* K; h# o) W7 C4 s) c6 `0 F到 SRAM,然后将存储在 ADC_CCR 低位半字中的 ADC1 转换数据传输到 SRAM。) r# g" r2 }. k
● 当 ADC1/ADC2 的规则通道全部完成转换后,会生成一个 EOC 中断(如果已在两个 ADC+ l  w6 x) c# B. k/ w
接口中的一个接口上使能)。
9 v- o7 U+ w  ]5 v# y
0 _) R* R0 `! S( i& ]% }, Q转换示意图:0 k! f5 q0 \2 l  C* m( W
  i* s4 R# G; U" B9 H2 p6 d" x

转换示意图

转换示意图

$ }. I6 @" X: F3 b# w, |6 [/ E, Z- b2 E& b( P
配置代码:
+ y! K$ c4 X* Z$ m% e0 c" V# W4 P8 S
#define ADC_CDR_ADDRESS    ((uint32_t)0x40012308) //适用于双重和三重模式的 ADC 通用规则数据寄存器( ADC_CDR), y% I9 X; q7 p( o5 j& ~
4 D5 p" [+ e% m; ^: Y
% K/ B) _2 N+ `
void Init_ADC12(void)6 a" h5 V* p9 W6 ?9 q2 L. z; ~- a
{8 y" r; V& v& \2 U2 W
  GPIO_InitTypeDef  GPIO_InitStructure;2 \/ N6 z4 y1 @8 i; ~& d
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
' ?' ?( O$ k' |' |+ F: c& a  ADC_InitTypeDef       ADC_InitStructure;
3 J3 v% I0 R# I& }! M( f8 @1 S   
! z9 O3 B1 g. J  w! U  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟* ?8 T5 J4 U8 Y7 o+ p( I
  2 f6 R' N6 B9 O% l5 G0 O
  //先初始化ADC1通道 IO口2 `* X: R4 D  p- r
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;;
6 G" T: _/ ^# N' i; I0 k  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
+ [2 `$ Y# x: u4 Q  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//不带上下拉& A& K: d3 Y% _
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化  5 D7 I6 L7 k* r5 O# q. o* o
  
6 y3 X/ N3 W2 l# d' d$ n& _* r" ]; Y
  /*****************************************************************5 e- l4 o- v' Q6 s
  *************************** DMA Configuration  ******************( M2 P% W. R) o/ k, P% G( p
  *******************************************************************/  `. L6 r8 k6 X7 B
  
) Q* c$ D% D% c  9 i! Z3 i( c' ]( G( _( k" P
  . o1 p4 E. U3 w
    DMA_InitTypeDef DMA_InitStructure;# j+ I( u6 a8 B5 J6 M/ ~
    /*首先开DMA2时钟,由407参考手册-RM0090-Reference manual% ?, ?! h' U: B
     *165页可知,ADC与DMA2映射,而且DMA2挂载在AHB1时钟总线上*/
6 Z. v6 A1 |% |, B/ u8 D% X: P* k    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
7 J! p7 ~# O( H2 t. w0 N3 x    0 t& c3 |! F, N4 Q: w
    DMA_DeInit(DMA2_Stream0);
# a8 N/ Y: @5 w* x5 X) p: c. ]6 V    DMA_StructInit( &DMA_InitStructure);' F/ j, b4 _5 P# _6 G
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;                     //选择Channel_08 S6 y- t( x* {1 f2 V5 B& Y
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS; //数据传输的外设首地址,详解见上8 U' E9 Q' L% M  n+ J6 a
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&adc_result;   //自己定义待发送数组的首地址,要强制转换为32位
( t$ ^4 h! L* M    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;       //数据传输方向选择为内存->外设' y. B+ u  j1 o+ S7 F3 x7 Q, V
    DMA_InitStructure.DMA_BufferSize = 2;                      //传输数据大小为16,单位由以下确定,大小要配合定义的数组类型和外设数据类型% _9 ~$ ^( ~* i; C0 T. v2 k
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器自动增加禁止,因为这里只用到了DR数据寄存器
: x1 ~/ p  w! b; ^    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         //内存地址自增不允许,因为只存取一个数! }1 P) }0 }# a7 y6 E& ]
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设的数据大小& g7 v! E) k+ _3 b9 j
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;     //这里也选Byte) B. V) O: o4 M' ]8 R8 n
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;       //DMA传输模式为Normal,如果为Circular,将会循环传输
- R& h' K3 S9 D    DMA_InitStructure.DMA_Priority = DMA_Priority_High;   //优先级为VeryHigh
! L, G7 E- E, {: x1 d    DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;; l* f; x. N2 d; f* O
    DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;9 y" }7 k& \: _% [! r, ]1 m
    DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
+ X1 s* g7 N8 D: B. U    DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
7 U2 R2 d9 D/ V" U. v; \0 z' ?    DMA_Init(DMA2_Stream0, &DMA_InitStructure);6 E: V( I: A7 W1 P
    1 A# V1 X* l7 A% j

3 B5 I0 X  Q. o: u//    NVIC_InitTypeDef NVIC_InitStructure;
, n* V1 x: |- x, D//    /* DMA中断配置 */3 c! n% M+ i1 }& I
//    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;      //嵌套通道为DMA2_Stream0_IRQn$ b1 d1 \' Y( D7 t
//    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为 1; A3 K1 `5 [$ E0 d: _" [& t
//    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          //响应优先级为 08 E- M1 A, E" s: e& O  q
//    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //通道中断使能
3 [4 v* H5 ]+ |6 A  s' B//    NVIC_Init(&NVIC_InitStructure);
4 ^+ ]' p1 X! n& L( R9 x; w- t4 S   
4 n- t) ~% B7 `* U0 v! M" {$ [    " y9 C6 M0 ?. ?
   
1 t/ A7 Q/ W' L2 N    //使能DMA2_Stream0通道, u" t" d% l3 b" z- Y! d. M
    DMA_Cmd(DMA2_Stream0, ENABLE);# E2 R6 D! I# g+ H7 k5 p
    8 V* e4 G4 e2 ^

1 x$ ]9 ]7 X1 A& T- i7 @) A//    /* DMA中断开 */
# K% ~, v( W! F1 X5 ]$ U( F1 Z//    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);8 |6 `+ c& {4 e
    * X( B# [2 h+ C: v% N- ?
  /*****************************************************************
9 d5 z6 q5 c0 o. A5 N/ H' ?% }  *************************** ADC Configuration  ******************1 J: b0 |* W2 a2 f
  *******************************************************************/1 }9 \5 d( X. K9 W

0 F8 P+ U% t. Z# d7 T  6 {6 N) i& ^- V8 Z, Y
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟
1 g. v' z, H% {# Z  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); //使能ADC2时钟2 N1 g- z/ x, b3 d* [' k
5 z, Y% |+ j' t  j* p7 C
  ADC_DeInit();7 F% v1 [" D- g* W( d
  //初始化ADC Common
1 N: H6 C) B/ B2 N7 ^; C' v  ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
, ^# `5 X; _' _  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟) ~2 o( O( n9 u! ^2 f
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; //DMA使能
6 b9 P$ y# c. l, |  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz % a4 C" U/ U1 D  y5 x
  ADC_CommonInit(&ADC_CommonInitStructure);//初始化/ s: }$ g3 A( f7 d. y
    # t  E; P0 v6 G
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式+ i. Y  v: V/ J0 z2 e, ?. o& s
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式    # r% g3 M& E% t* @* Z2 l' [
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
, `3 z; ?2 H1 ^7 H! Y& N  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发  d8 p7 H, T0 Q& L3 x
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐    : `# q3 U+ X* g$ F' h
  ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1
, }3 l, K, k9 ]  x  
- a2 a; `7 g' h- `/ V: t& W  ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化, |; X. c% b& U( @% B
   
/ v6 E7 b7 P! C8 D  P; j  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式& B0 ~8 \4 }: q( y+ D% F* m: Q9 `
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式    ( Y. }1 v) z$ u7 [5 q  m  i
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
4 P" i/ P1 z- T6 V  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
7 l  U/ \% S1 F0 h  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐   
+ v- Z+ X$ Y$ A. w% o. v7 B  A  ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 : a/ I$ ^6 j9 H( L! Z7 K) t
  
7 |8 K& H; y# i, P7 `  ADC_Init(ADC2, &ADC_InitStructure);//ADC初始化4 p: h3 w* i. T  i: P
  + d: f1 `7 Q" g/ W
  " N, g! Y% q1 G/ z" p: X# s
  ADC_RegularChannelConfig(ADC1, ADC_Channel_0 , 1, ADC_SampleTime_15Cycles);    ! ~0 K# `& C% H. W; Y
  ADC_RegularChannelConfig(ADC2, ADC_Channel_1 , 1, ADC_SampleTime_15Cycles);
: b% @% r" j) u+ `" t  
) h# B0 s0 |; W& _  /* Enable ADC1 DMA */
5 y0 i' J6 E7 g( f  ADC_DMACmd(ADC1, ENABLE);
: t8 n6 o' z* I  X. |4 s  
( L. v- X" W  C5 X" u5 |    ; Q, w8 j, n4 `# }
    /* Enable DMA request after last transfer (Multi-ADC mode)  */
6 f" L% ^: [8 K$ o- B3 Z$ o  V  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);+ R% Q6 D7 W  V- o& Q! E
  - d+ f) h7 ]9 O  f
  
& ^9 S5 E) d0 J- R0 q2 U  c! ~, w  ADC_Cmd(ADC1, ENABLE);//开启AD1转换器    4 s7 y) F; x/ D% u% V
  ADC_Cmd(ADC2, ENABLE);//开启AD2转换器    ' I! c: b* |, b# {( H$ R

% b: d' O; x; ~' R$ @

转换示意图

转换示意图
赞 收藏 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 编辑 . t) \. N" P0 J' S9 A6 x
! o  b8 x) L$ R* V/ d4 A
内存地址自增不允许,因为只存取一个数
. K6 P. R! z9 Z: S# \这句注释错了吧,明明你设置的是DMA_MemoryInc_Enable2 v3 x4 w8 M4 b- X: P" l
虽然我也不知道到底是注释错了还是代码错了
5 j" @: h( l4 v, V8 V……
9 X; c5 f% ?/ z  z, O  ?% O多看了几段,为什么注释和代码都是自相矛盾?
% [+ Y# a: I% I+ A
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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版