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

STM32F401 adc转换不结束?!

[复制链接]
dgdzes 提问时间:2019-9-23 09:41 /
使用STM32F401RET6芯片,sysem tick产生5ms中断,主程序查询5ms是否有到,到了就做启动一次ad转换(查询方式),下一个5ms去判断转换是否结束(实际转换不需要这么长时间),如果转换结束就读取转换值。再下一个5ms来又启动转换,如此循环。但是现在现象是,进入调试后,可以正常转换几次,转换值也是正确的,紧接着就是不能查询到转换结束标志EOC,但STRT一直为1. 如果改变写法,启动adc后,立即等待adc做完,这样写就正常。
u16 Get_Adc(void)   
{
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_480Cycles );  
        ADC_SoftwareStartConv(ADC1);         
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
        return ADC_GetConversionValue(ADC1);
}      

void adc_scan(void)  //@5ms
{
#if 1   // 这样写就正常
        res = Get_Adc();
        cnt++;
        return;
#else    // 这样写就开始正常转换,几次后EOC标志就不会被置位。
    if(index == 0)
    {
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_480Cycles );  
        ADC_SoftwareStartConv(ADC1);
        index = 1;
    }
    else
    {
        if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ) == SET)
        {
            ADC1->SR = ~(uint32_t)ADC_SR_EOC;
            cnt++;
            res = (uint16_t)ADC1->DR;
            index = 0;
        }        
    }

#endif
}   

哪位有遇到过这种情况吗?为什么不立即去等ADC做完就有问题,还是adc就有这种限制?
附件是整个项目文件。

stm32f401ret6_adc_issue.zip

下载

475.19 KB, 下载次数: 4, 下载积分: ST金币 -1

收藏 评论8 发布时间:2019-9-23 09:41

举报

8个回答
废鱼 回答时间:2019-9-23 09:46:56
楼主建议看一下ADC的采样频率,ADC采集我不建议在定时中做,可以再外部判断ticks的值进行判断是否需要采样。
dgdzes 回答时间:2019-9-23 09:59:12
安 发表于 2019-9-23 09:46
楼主建议看一下ADC的采样频率,ADC采集我不建议在定时中做,可以再外部判断ticks的值进行判断是否需要采样 ...

版主,你好。adc采集是在主程序里做的,system tick 中断只产生一个5ms标志。帮看看这个时钟配置是否有问题(HCLK=84M, PCLK1=42M, PCLK2=84M),似乎有问题也说不通,因为换一种写法,它确是正常的,不知道真实的问题在哪里。
void adc_initialize(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_CommonInitTypeDef ADC_CommonInitStructure;
        ADC_InitTypeDef ADC_InitStructure;

        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
   
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); /* ADC1复位 */
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE);/* 复位结束 *

        ADC_CommonInitStructure.ADC_Mode                         = ADC_Mode_Independent;/* 独立模式 */
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;/* 两个采样阶段之间的延迟5个时钟 */
        ADC_CommonInitStructure.ADC_DMAAccessMode         = ADC_DMAAccessMode_Disabled; /* DMA失能 */
        ADC_CommonInitStructure.ADC_Prescaler                 = ADC_Prescaler_Div8;/* 预分频4分频。ADCCLK=84/4=21Mhz,ADC时钟最好不要超过36Mhz        */
        ADC_CommonInit(&ADC_CommonInitStructure);

        ADC_InitStructure.ADC_Resolution                   = ADC_Resolution_12b;/* 12位模式 */
        ADC_InitStructure.ADC_ScanConvMode                   = DISABLE;/* 非扫描模式    */
        ADC_InitStructure.ADC_ContinuousConvMode   = DISABLE;/* 关闭连续转换 */
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;/* 禁止触发检测,使用软件触发 */
        ADC_InitStructure.ADC_DataAlign                    = ADC_DataAlign_Right;/* 右对齐 */  
        ADC_InitStructure.ADC_NbrOfConversion           = 1;/* 1个转换在规则序列中 也就是只转换规则序列1        */
        ADC_Init(ADC1, &ADC_InitStructure);/* ADC初始化 */      
   
        ADC_Cmd(ADC1, ENABLE);       
}         

main里的循环:
while(1)
    {                               
        if(system_tick != 0)
        {
            system_tick = 0;                       
            adc_scan();                   
        }            
    }
wenyangzeng 回答时间:2019-9-23 10:07:16
其实楼主在5mS中断到来时设置一个标志位,主循环里判断标志位为1时启动ADC,并等待ADC转换结束即可。一般在定时器中断里进行ADC转换不是一个好方案。
dgdzes 回答时间:2019-9-23 10:15:21
wenyangzeng 发表于 2019-9-23 10:07
其实楼主在5mS中断到来时设置一个标志位,主循环里判断标志位为1时启动ADC,并等待ADC转换结束即可。一般在 ...

wenyangzeng,你好;ad是在主程序里的做的,我的做法是启动ad后,没有立即等它做完,而是下个5ms去判断EOC是否有置位,但几次正常采集后就不正常了,EOC标志不能被置位?!但换一种写法(启动ad后,紧接着就判断EOC标志),这样却正常。
GPTKEY 回答时间:2019-9-23 10:39:16
建议 你换个方式   1 使用ADC转换完成中断去处理结果,这样可以防止你不等待时,ADC进行了多次转换,
2使用DMA去处理你的ADC转换结果

目前一直等肯定可以,你不等待,就把ADC设置成单次触发,不要设置成连续转换,我觉得这个才是问题所在
wenyangzeng 回答时间:2019-9-23 11:29:33
dgdzes 发表于 2019-9-23 10:15
wenyangzeng,你好;ad是在主程序里的做的,我的做法是启动ad后,没有立即等它做完,而是下个5ms去判断EO ...

两次定时器中断里不见得ADC刚好转换结束,所以还是不要在定时器中断里判断ADC转换是否结束,而是启动ADC转换后就等待结束比较合理。
废鱼 回答时间:2019-9-23 14:05:29
楼主,在定时器中不要进行ADC的任何操作,包括ADC的状态检查,只需要将需要的变量设置即可。while循环中判断,只要需要采集就去采集。
dgdzes 回答时间:2019-9-23 14:13:05
50031185 发表于 2019-9-23 10:39
建议 你换个方式   1 使用ADC转换完成中断去处理结果,这样可以防止你不等待时,ADC进行了多次转换,
2使用 ...

非常感谢你的建议,单次转换改为中断的方式,可以;
这里还是有疑问,用查询方式,并没设置成连续转换,5ms轮询一次怎么就检测不到EOC标志呢,用其它芯片的adc都可以这样操作。是不是ST哪里有特殊要求。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版