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

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

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

  将变阻器的那路ADC设置为注入通道:
  1. 1  ADC_InjectedSequencerLengthConfig(ADC1, 1);\\设置注入通道长度
  2. 2  ADC_InjectedChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);\\配置注入通道
  3. 3  ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE);\\开始注入通道数据采样和转换</font>
复制代码


  开始之后,延迟足够的时间,让ADC采样和转换完成。
     用ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);读取注入通道1的数据,结果发现数据一直不变,那肯定是哪里设置出错了,找了下别人的设置,并做了一些尝试,发现了原来是设置的问题,注入采样的触发方式没有设置:
  1. ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);</font>
复制代码

     这个函数设置注入方式使用软件触发方式,设置完之后用开始采样和读取数据函数,就能采到正确的数据。

     上面的例子使用触发注入完成的,下面又尝试了自动注入。这样每次进行规则通道采样时,也会顺便把注入通道也进行采样了,而启动注入通道采样则不会对规则通道进行采样。
如果设置了 JAUTO 位,在规则组通道之后,注入组通道被自动转换。这可以用来转换在 ADC_SQRx 和 ADC_JSQR 寄存器中设置的多至 20 个转换序列。
     
     还有在规则通道使用DMA数据传输,且使用注入通道采样时,不知道会不会对数据有影响?
   查了下文档,只有在规则通道的转换结束时才产生 DMA 请求,并将转换的数据从 ADC_DR 寄存器传输到用户指定的目的地址,还有注入方式转换后数据存储到 ADC_DRJx寄存器和规则方式转换后数据存储在ADC_DR寄存器中。


  在注入通道和规则通道的混合使用中,我花了不少时间去找正确的设置,问题是不知道哪些库函数是必要的,哪些是非必要的,后来对着例子尝试之后才知道。后面我还想了解下具体的寄存器设置,看了几个初始化的函数,发现其实很多设置都是对ADC_CR1的设置,有不少不明白的看了寄存器就知道了,看来函数的使用还是要和寄存器对应的位结合起来,这样才能理解的透彻点。
  下面是我整个代码的设置,其他设置和上篇例子一样,只改了ADC设置:

  1. static void Protect_AdcInit(void)  
  2. {  
  3.     ADC_InitTypeDef ADC_InitStructure;  
  4.       
  5.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  
  6.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;  
  7.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  
  8.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发  
  9.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  
  10.     ADC_InitStructure.ADC_NbrOfChannel = 2;//规则通道的数量  
  11.     ADC_Init(ADC1, &ADC_InitStructure);//这个大部分是初始化规则通道的  
  12.       
  13.     ADC_TempSensorVrefintCmd(ENABLE);  
  14.     ADC_RegularChannelConfig(ADC1,ADC_Channel_TempSensor,1,ADC_SampleTime_239Cycles5);  
  15.     ADC_RegularChannelConfig(ADC1,ADC_Channel_Vrefint,2,ADC_SampleTime_239Cycles5);  
  16.       
  17.     ADC_InjectedSequencerLengthConfig(ADC1, 1);  
  18.     ADC_InjectedChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);  
  19.     ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);//设置规则通道软件触发  
  20.     /* Enable automatic injected conversion start after regular one */  
  21.   //  ADC_AutoInjectedConvCmd(ADC1, ENABLE);  
  22.   
  23.       
  24.     ADC_DMACmd(ADC1, ENABLE);  
  25.     /* Enable ADC1 external trigger */  
  26.     ADC_ExternalTrigConvCmd(ADC1, DISABLE);  
  27.     ADC_ExternalTrigInjectedConvCmd(ADC1, DISABLE);  
  28.   
  29.     ADC_Cmd(ADC1, ENABLE);  
  30.   
  31.     ADC_ResetCalibration(ADC1);  
  32.   
  33.     while(ADC_GetResetCalibrationStatus(ADC1));  
  34.   
  35.     ADC_StartCalibration(ADC1);  
  36.   
  37.     while(ADC_GetCalibrationStatus(ADC1));  
  38.   
  39. }  [/size]
复制代码


读取数据在这里:

  1. /* 注入转换中断 */
  2. void ADC1_2_IRQHandler(void)
  3. {
  4. s32 inj_v1,inj_v2,inj_v3,inj_v4;

  5. if(ADC_GetITStatus(ADC1,ADC_IT_JEOC) == SET){
  6. ADC_ClearITPendingBit(ADC1,ADC_IT_JEOC);
  7. inj_v1 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
  8. inj_v1 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_4);
  9. inj_v1 >>= 1;

  10. inj_v2 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_2);
  11. inj_v2 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_3);
  12. inj_v2 >>= 1;

  13. inj_v3 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_3);
  14. inj_v3 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_2);
  15. inj_v3 >>= 1;

  16. inj_v4 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_4);
  17. inj_v4 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_1);
  18. inj_v4 >>= 1;
  19. }
  20. }

  21. /* 规则转换中断 */
  22. void DMA1_Channel1_IRQHandler(void)
  23. {
  24. if(DMA_GetFlagStatus(DMA1_FLAG_TC1) == SET){
  25. DMA_ClearFlag(DMA1_FLAG_TC1);
  26. DMA_ClearITPendingBit(DMA1_IT_GL1);
  27. ADC_SoftwareStartConvCmd(ADC1,DISABLE);
  28. DMA_Cmd(DMA1_Channel1,DISABLE);

  29. regular_convert_calc();

  30. DMA1_Channel1->CNDTR = NUM_OF_REG_CHANNEL;
  31. DMA_Cmd(DMA1_Channel1,ENABLE);
  32. ADC_SoftwareStartConvCmd(ADC1,ENABLE);
  33. }
  34. }</font>
复制代码

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