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

ADC的规则通道和注入通道混合使用双adc dma触发pwm电机

[复制链接]
zero99 发布时间:2017-6-20 10:57
之前完成了规则通道DMA的数据传输了,不过平时在使用ADC的时候可能就会遇到很多情况,不可能就这样简单的按规则通道来采样,DMA存储,使用数据的;可能有时候会需要立刻采样,那样我们就需要利用到注入通道了。文档关于注入通道的解释:
  1. 1      利用外部触发或通过设置ADC_CR2寄存器的ADON位,启动一组规则通道的转换。 4 D- j1 j& @( X# K1 X
  2. 2      如果在规则通道转换期间产生一外部注入触发,当前转换被复位,注入通道序列被以单次扫描方式进行转换。 8 e, U7 E; X5 I9 A( H0 ?% K% C5 r, m
  3. 3      然后,恢复上次被中断的规则组通道转换。如果在注入转换期间产生一规则事件,注入转换不会被中断,但是规则序列将在注入序列结束后被执行。</font>
复制代码

+ T- D) C- l) ?) S& c& _
  将变阻器的那路ADC设置为注入通道:4 A) }  q& W; V0 R0 x
  1. 1  ADC_InjectedSequencerLengthConfig(ADC1, 1);\\设置注入通道长度$ N: a9 |+ Q8 y0 y# a8 D
  2. 2  ADC_InjectedChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);\\配置注入通道
    ) M  Z  f' o$ k+ u( X0 H1 l
  3. 3  ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE);\\开始注入通道数据采样和转换</font>
复制代码
3 h& d9 K4 R( v) {
& F5 j+ e( m; e8 P3 ]& D
  开始之后,延迟足够的时间,让ADC采样和转换完成。
$ E: n0 n. q' Y3 n, x  E# Q     用ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);读取注入通道1的数据,结果发现数据一直不变,那肯定是哪里设置出错了,找了下别人的设置,并做了一些尝试,发现了原来是设置的问题,注入采样的触发方式没有设置:) Y' G; @( H) Y
  1. ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);</font>
复制代码

- @# y' |) o) ~" `! B8 s     这个函数设置注入方式使用软件触发方式,设置完之后用开始采样和读取数据函数,就能采到正确的数据。& x; k5 Z; r- K% K! _

5 H) j9 O: L, F! ^     上面的例子使用触发注入完成的,下面又尝试了自动注入。这样每次进行规则通道采样时,也会顺便把注入通道也进行采样了,而启动注入通道采样则不会对规则通道进行采样。+ M$ _) a+ h0 _1 [- J2 A$ X  i- Y
如果设置了 JAUTO 位,在规则组通道之后,注入组通道被自动转换。这可以用来转换在 ADC_SQRx 和 ADC_JSQR 寄存器中设置的多至 20 个转换序列。
" U4 m" E( F/ [5 f+ a$ }* j7 ~     
1 G1 e1 Y+ r% t$ _4 B- l     还有在规则通道使用DMA数据传输,且使用注入通道采样时,不知道会不会对数据有影响?
+ Y- w8 t3 e! C2 H   查了下文档,只有在规则通道的转换结束时才产生 DMA 请求,并将转换的数据从 ADC_DR 寄存器传输到用户指定的目的地址,还有注入方式转换后数据存储到 ADC_DRJx寄存器和规则方式转换后数据存储在ADC_DR寄存器中。
: G$ v2 U% D3 n# o9 W  F6 d+ T; J2 p' D/ c3 ~3 {( @. L5 M- ?

9 f/ ]# t! ]& o! j  在注入通道和规则通道的混合使用中,我花了不少时间去找正确的设置,问题是不知道哪些库函数是必要的,哪些是非必要的,后来对着例子尝试之后才知道。后面我还想了解下具体的寄存器设置,看了几个初始化的函数,发现其实很多设置都是对ADC_CR1的设置,有不少不明白的看了寄存器就知道了,看来函数的使用还是要和寄存器对应的位结合起来,这样才能理解的透彻点。
% }6 p! _% r0 _9 I( v2 T0 w  下面是我整个代码的设置,其他设置和上篇例子一样,只改了ADC设置:7 E, B7 E) N0 Z) z( w% d

! M# C% a; d% H# S0 C- [
  1. static void Protect_AdcInit(void)  
    6 e/ n: l7 z7 o, l6 f) B
  2. {  5 @& X, Z& H7 R$ [8 [, M* \
  3.     ADC_InitTypeDef ADC_InitStructure;  
    * J  `' _& g: Y$ e! ^* I; D/ q# S
  4.       
    7 E- H, T- H/ w2 a
  5.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  - R1 M; P* e* T! m5 G' @  q
  6.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;  
    0 }+ }; s- M( ~( a3 t- S
  7.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  
    ) b# R2 f& w( H. g* U
  8.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发  - o: h2 m0 U1 I: s
  9.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  
    ( b4 \- b$ y; }6 B
  10.     ADC_InitStructure.ADC_NbrOfChannel = 2;//规则通道的数量  
    6 D7 W( R$ Y( z6 a4 f$ H' M6 b5 J
  11.     ADC_Init(ADC1, &ADC_InitStructure);//这个大部分是初始化规则通道的    [% [1 G9 N0 c" k" V
  12.       
    / U' U* t" Y  D. S- {0 f
  13.     ADC_TempSensorVrefintCmd(ENABLE);  : Z5 s  ]) m* ]$ {- L' z
  14.     ADC_RegularChannelConfig(ADC1,ADC_Channel_TempSensor,1,ADC_SampleTime_239Cycles5);  
    , b$ x9 X! d. `7 X7 q
  15.     ADC_RegularChannelConfig(ADC1,ADC_Channel_Vrefint,2,ADC_SampleTime_239Cycles5);  
    % v4 w+ M5 q: i; `4 v
  16.       
    7 B& L3 ^+ l, M
  17.     ADC_InjectedSequencerLengthConfig(ADC1, 1);  6 |$ g2 L- c  ^- @
  18.     ADC_InjectedChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);  
    7 Q( N; o# M& F( K( |. ~2 V) C
  19.     ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);//设置规则通道软件触发  ) ]* l# V# |% o6 \
  20.     /* Enable automatic injected conversion start after regular one */  
    9 Q* L1 r" y' ?
  21.   //  ADC_AutoInjectedConvCmd(ADC1, ENABLE);  - p1 A; l4 J2 Q( \, U7 d
  22.   " G! \& Z" o) }; B
  23.       * t3 ^; @7 x0 [6 L% f6 A8 m& x5 ]
  24.     ADC_DMACmd(ADC1, ENABLE);  - |3 i8 o; l1 q
  25.     /* Enable ADC1 external trigger */  # M) l/ p" ?/ o. q! @+ M9 v6 U: x
  26.     ADC_ExternalTrigConvCmd(ADC1, DISABLE);    |" F3 W  R" k& ]' `/ m
  27.     ADC_ExternalTrigInjectedConvCmd(ADC1, DISABLE);  3 K5 [: u8 }, {0 g2 T
  28.   
    " G9 i* }  O) r/ K0 B' H% f) Y
  29.     ADC_Cmd(ADC1, ENABLE);  
    - _& M: }9 m: X9 h
  30.   
    1 R8 a+ v5 f" ]4 y2 Z( s
  31.     ADC_ResetCalibration(ADC1);  - o3 d7 A+ Q/ n0 o& ?% G% |- |
  32.   
    ! ^: a. }% a. s! q( W& w
  33.     while(ADC_GetResetCalibrationStatus(ADC1));  8 y1 d8 A' K0 G6 r) @
  34.   - s- c& ?9 x$ X( a( w
  35.     ADC_StartCalibration(ADC1);  
    7 B. s2 j# h5 P& X
  36.   ' o" @2 H) o5 a9 r! p- r
  37.     while(ADC_GetCalibrationStatus(ADC1));  ' P1 `+ b$ q4 U8 r6 X- \
  38.   
    . H5 \- \8 W9 f, S* h! u$ i1 H. F/ S! Y
  39. }  [/size]
复制代码

0 `5 q0 Q0 e: m# [3 t
$ e5 ?8 G8 Y* e" b
读取数据在这里:

; d' A$ ^7 @( `2 E  S" M# R/ n
  1. /* 注入转换中断 */
    0 d  ~- u3 x8 M8 E
  2. void ADC1_2_IRQHandler(void)
    ; M: P  {% o6 L. U
  3. {
    5 @( B! [% |+ P% b: X
  4. s32 inj_v1,inj_v2,inj_v3,inj_v4;7 s0 Q, q1 R7 b& @" _

  5. . j8 w8 r% n" B; b( A
  6. if(ADC_GetITStatus(ADC1,ADC_IT_JEOC) == SET){
    8 D! E* J5 j8 {+ m2 n6 f6 ^% x
  7. ADC_ClearITPendingBit(ADC1,ADC_IT_JEOC);
    - }7 O' E2 E) {# i; n
  8. inj_v1 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);" G, b2 c. j! [, r$ ?$ M2 H4 t
  9. inj_v1 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_4);
    % Z2 I( w: U& A4 Q; l7 s
  10. inj_v1 >>= 1;
    - @: Z! V3 x& @2 A7 k
  11. 0 j! ?( z. B4 |" N* y5 F6 @3 o  J
  12. inj_v2 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_2);6 Z2 ~% y1 U( A7 q0 n8 i1 U- z
  13. inj_v2 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_3);
    2 x5 s3 P8 A0 Z( I" |5 U6 O% @
  14. inj_v2 >>= 1;" N& J* x8 S: Y6 p# e1 @2 g
  15. 3 ?* P, c" L) n0 i4 M' b3 g
  16. inj_v3 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_3);
    ' @* H, k# G8 w+ v# c
  17. inj_v3 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_2);
    / T# P& \- X. ], O6 I
  18. inj_v3 >>= 1;
    " D+ l& Y" P6 w. |& J6 r( ]5 C+ I

  19. 8 u8 \7 g) K/ Y
  20. inj_v4 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_4);
    ! k+ u! J0 M! `
  21. inj_v4 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_1);* G) k; [! j. K2 C. O8 }
  22. inj_v4 >>= 1;
    4 T3 L- T6 T& L# f, e( @
  23. }  |5 B$ Z" t" k. A' x, X
  24. }
    & U; ~: H% F# X: }9 `# s

  25. % {/ f4 K0 |- t
  26. /* 规则转换中断 */
    7 P' Z. v+ @8 `: ?7 [/ I* ]3 q% ~
  27. void DMA1_Channel1_IRQHandler(void)
    $ @. @: g1 G2 y& X. H
  28. {' _: j- h4 k* \, a9 P$ [' j2 n
  29. if(DMA_GetFlagStatus(DMA1_FLAG_TC1) == SET){
    $ M, n) N7 f: {5 F; W* F
  30. DMA_ClearFlag(DMA1_FLAG_TC1);
    3 ^, m  C( D& `! j; p
  31. DMA_ClearITPendingBit(DMA1_IT_GL1);+ y, g- w+ W. W6 X) M/ ^- f
  32. ADC_SoftwareStartConvCmd(ADC1,DISABLE);9 N( c  g: Q3 Y: r# M4 k: E
  33. DMA_Cmd(DMA1_Channel1,DISABLE);
    3 a  A  _3 \- \* e, J/ ^( B
  34. 1 \2 t8 v6 g; _7 i& g# _, t2 l  k
  35. regular_convert_calc();
    ! W( }' E1 H8 N, t; T- v$ B

  36. & }& E9 K) L- C- ?$ T6 ?
  37. DMA1_Channel1->CNDTR = NUM_OF_REG_CHANNEL;3 V9 u6 @- ^2 h" q. A( m$ j
  38. DMA_Cmd(DMA1_Channel1,ENABLE);) x; c, S' o2 k8 j9 c& Z0 R4 T( z
  39. ADC_SoftwareStartConvCmd(ADC1,ENABLE);
    ( X) Q# ~, V# R; M6 z
  40. }- q5 H+ H2 n. O7 f' l" V7 `
  41. }</font>
复制代码
0 y# `0 x9 L& f1 a
来源:lanmanck
赞 收藏 1 评论3 发布时间:2017-6-20 10:57

举报

3个回答
Inc_brza 回答时间:2017-6-26 14:37:25
谢谢分享,adc是个细活,特别是滤波。
valetang-126879 回答时间:2017-6-26 16:59:25
帮顶一下
帅包 回答时间:2023-4-17 17:00:03

感谢分享!!!

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版