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

原文地址,后面有添加:

http://www.cnblogs.com/nixianmin/p/3192634.html

之前完成了规则通道DMA的数据传输了,不过平时在使用ADC的时候可能就会遇到很多情况,不可能就这样简单的按规则通道来采样,DMA存储,使用数据的;可能有时候会需要立刻采样,那样我们就需要利用到注入通道了。文档关于注入通道的解释:

1      利用外部触发或通过设置ADC_CR2寄存器的ADON位,启动一组规则通道的转换。 
2      如果在规则通道转换期间产生一外部注入触发,当前转换被复位,注入通道序列被以单次扫描方式进行转换。 
3      然后,恢复上次被中断的规则组通道转换。如果在注入转换期间产生一规则事件,注入转换不会被中断,但是规则序列将在注入序列结束后被执行。
  将变阻器的那路ADC设置为注入通道:
1  ADC_InjectedSequencerLengthConfig(ADC1, 1);\\设置注入通道长度
2  ADC_InjectedChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);\\配置注入通道
3  ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE);\\开始注入通道数据采样和转换
   开始之后,延迟足够的时间,让ADC采样和转换完成。
     用ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);读取注入通道1的数据,结果发现数据一直不变,那肯定是哪里设置出错了,找了下别人的设置,并做了一些尝试,发现了原来是设置的问题,注入采样的触发方式没有设置:
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);
     这个函数设置注入方式使用软件触发方式,设置完之后用开始采样和读取数据函数,就能采到正确的数据。
 
     上面的例子使用触发注入完成的,下面又尝试了自动注入。这样每次进行规则通道采样时,也会顺便把注入通道也进行采样了,而启动注入通道采样则不会对规则通道进行采样。
如果设置了 JAUTO 位,在规则组通道之后,注入组通道被自动转换。这可以用来转换在 ADC_SQRx 和 ADC_JSQR 寄存器中设置的多至 20 个转换序列。
     
     还有在规则通道使用DMA数据传输,且使用注入通道采样时,不知道会不会对数据有影响?
    查了下文档,只有在规则通道的转换结束时才产生 DMA 请求,并将转换的数据从 ADC_DR 寄存器传输到用户指定的目的地址,还有注入方式转换后数据存储到 ADC_DRJx寄存器和规则方式转换后数据存储在ADC_DR寄存器中。
  在注入通道和规则通道的混合使用中,我花了不少时间去找正确的设置,问题是不知道哪些库函数是必要的,哪些是非必要的,后来对着例子尝试之后才知道。后面我还想了解下具体的寄存器设置,看了几个初始化的函数,发现其实很多设置都是对ADC_CR1的设置,有不少不明白的看了寄存器就知道了,看来函数的使用还是要和寄存器对应的位结合起来,这样才能理解的透彻点。
  下面是我整个代码的设置,其他设置和上篇例子一样,只改了ADC设置:

static void Protect_AdcInit(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 2;//规则通道的数量
    ADC_Init(ADC1, &ADC_InitStructure);//这个大部分是初始化规则通道的
    
    ADC_TempSensorVrefintCmd(ENABLE);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_TempSensor,1,ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_Vrefint,2,ADC_SampleTime_239Cycles5);
    
    ADC_InjectedSequencerLengthConfig(ADC1, 1);
     ADC_InjectedChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);
    ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);//设置规则通道软件触发
    /* Enable automatic injected conversion start after regular one */
  //  ADC_AutoInjectedConvCmd(ADC1, ENABLE);

    
    ADC_DMACmd(ADC1, ENABLE);
    /* Enable ADC1 external trigger */
    ADC_ExternalTrigConvCmd(ADC1, DISABLE);
    ADC_ExternalTrigInjectedConvCmd(ADC1, DISABLE);

    ADC_Cmd(ADC1, ENABLE);

    ADC_ResetCalibration(ADC1);

    while(ADC_GetResetCalibrationStatus(ADC1));

    ADC_StartCalibration(ADC1);

    while(ADC_GetCalibrationStatus(ADC1));

}

======================没完,继续=================

读取数据在这里:

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


if(ADC_GetITStatus(ADC1,ADC_IT_JEOC) == SET){
ADC_ClearITPendingBit(ADC1,ADC_IT_JEOC);
inj_v1 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
inj_v1 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_4);
inj_v1 >>= 1;


inj_v2 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_2);
inj_v2 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_3);
inj_v2 >>= 1;


inj_v3 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_3);
inj_v3 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_2);
inj_v3 >>= 1;


inj_v4 = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_4);
inj_v4 += ADC_GetInjectedConversionValue(ADC2,ADC_InjectedChannel_1);
inj_v4 >>= 1;
}
}


/* 规则转换中断 */
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA1_FLAG_TC1) == SET){
DMA_ClearFlag(DMA1_FLAG_TC1);
DMA_ClearITPendingBit(DMA1_IT_GL1);
ADC_SoftwareStartConvCmd(ADC1,DISABLE);
DMA_Cmd(DMA1_Channel1,DISABLE);


/* ¼ÆËãת»»Öµ */
regular_convert_calc();


/* Æô¶¯ÏÂÒ»´Î´«Êä */
DMA1_Channel1->CNDTR = NUM_OF_REG_CHANNEL;
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
}

还有这篇说的也不错: 用TIM1产生6路ADC,用CCR4触发ADC1的注入通道采样

http://www.csdn123.com/html/itweb/20130801/33722_33714_33696.htm

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32是一款微控制器系列,具有丰富的外设功能。其中包括PWM(脉宽调制)和ADC(模数转换)功能。 PWM是一种通过调整信号的脉冲宽度来控制电平的技术。在STM32中,可以使用TIM(定时器)来生成PWM信号。通过设置TIM通道PWM模式,可以控制输出的占空比和频率。在引用中提到的例子中,TIM1通道一被设置为PWM模式,并且TIM_IT_Update和TIM_IT_CC3中断被允许。 ADC是一种将模拟信号转换为数字信号的技术。在STM32中,可以使用ADC模块来对外部信号进行采样和转换。引用中提到了三种使用ADC的方法,包括使用定时器中断进行ADC转换,使用连续转换模式结合DMA进行数据搬运,以及使用ADC的定时器触发功能结合DMA进行数据搬运。 在流程图中,当发生TIM_IT_Update中断时,使能TIM8并开始ADC采样;当发生TIM_IT_CC3中断时,失能TIM8并停止ADC采样。这样可以实现在PWM波内进行ADC采样,并用于触发发射信号、采样回波信号以及计算从发射到回波信号的时间。 总结起来,STM32可以通过设置TIM模块的通道PWM模式来生成PWM信号,并通过ADC模块对外部信号进行采样和转换。可以使用定时器中断或者定时器触发等方式来控制ADC的采样时间。这样就可以实现PWMADC的功能。<span class="em">1</span> #### 引用[.reference_title] - *1* [stm32如何实现PWM输出及周期内ADC采样](https://blog.csdn.net/qq_26786109/article/details/78223801)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值