[求助] 关于STM32 AD转换的ADC_FLAG_EOC标志位问题

xinsuiwuhen   2013-9-16 19:25 楼主
小弟最近再写STM32的ADC,看了很多网的例程都是用DMA接数据,但是我想直接用AD读到寄存器,再拿出来处理。
在写程序的时候发现个问题,while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); 这个while循环总是过不去,真心很郁闷……有哪位大神遇到过类似的问题吗? 求帮忙解决下  下面附上我的初始化以及读ADC程序
/************************ADC初始化***************************/
void ADC_Config(void)       
{
        ADC_InitTypeDef ADC_InitStruct;
        GPIO_InitTypeDef GPIO_InitStruct;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);                                           //使能ADC1时钟

        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;                                                                   //配置对应的ADC通道IO口
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
        GPIO_Init(GPIOC,&GPIO_InitStruct);

        ADC_DeInit(ADC1);                                                                                                                        //将ADC所有寄存器值恢复默认
        ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;                                                                //ADC1与ADC2工作在独立工作模式
        ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;                                                        //ADC数据右对齐
        ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;                                                        //DISABLE工作在单次模式;ENABLE工作在连续模式
        ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;                                //定义触发方式,此处为软件触发
        ADC_InitStruct.ADC_NbrOfChannel = 1;                                                                                //ADC通道数目
        ADC_InitStruct.ADC_ScanConvMode = ENABLE;                                                                        //ADC工作在单通道还是多通道模式

        ADC_ITConfig(ADC1,ADC_IT_EOC,DISABLE);
        ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
        ADC_Init(ADC1,&ADC_InitStruct);

/***************设置指定ADC的规则组通道,设置它们的转化顺序和采样时间****************/
/***************使能ADC的通道13,采样序列号为1,采样周期为71.5周期*******************/
        ADC_RegularChannelConfig(ADC1,ADC_Channel_11,1,ADC_SampleTime_71Cycles5);
        ADC_Cmd(ADC1,ENABLE);
        ADC_ResetCalibration(ADC1);                                                                                                        //重置ADC的校准寄存器
        while(ADC_GetResetCalibrationStatus(ADC1));                                                                        //获取ADC重置校准寄存器状态,直到校准寄存器重设完成
        ADC_StartCalibration(ADC1);                                                                                                        //开始指定ADC的校准
        while(ADC_GetCalibrationStatus(ADC1));                                                                            //获取指定ADC的校准程序,直到校准完成
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                                                                            //使能ADC1的软件转换启动功能
               
}

/***********读ADC程序*********************/
void Read_ADC(void)
{
        unsigned short result = 0;
        unsigned short id;
        unsigned char a,b,c,d,i;
        for(i=0;i<1;i++)
        {
                ADC_SoftwareStartConvCmd(ADC1,ENABLE);                                        //启动ADC1转换
/*                do{
                        id = ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC);                        //读取转换标志
                  }while(!id);*/       
                while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));        
                                         
                ADC_SoftwareStartConvCmd(ADC1,DISABLE);                  
                result += ADC_GetConversionValue(ADC1);       
                Delay_ARMJISHU(8000000);
        }
        result = result>>3;                                                                                //取8次平均值
        result = (unsigned int)(((unsigned long)result)*3300>>12);  //把采集到的数值转换成电压数据

        a = result / 1000;
        b = (result - a*1000)/100;
        c = (result - a*1000 - b*100)/10;
        d = result - a*1000 - b*100 - c*10;

        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, 0x56);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, 0x3d);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, a+48);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1,0x2e);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, b+48);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, c+48);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, d+48);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1,0x56);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);       
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, 0x0d);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1,0x0a);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);               
}

回复评论 (9)

用DMA没什么不好,配置好后直接读全局变量就可以了,也不会占用什么资源。
我的博客
点赞  2013-9-17 10:40

回复 楼主xinsuiwuhen 的帖子

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
试一下.
点赞  2013-9-17 12:03

回复 板凳Study_Stellaris 的帖子

谢谢版主。。我刚刚试过了,还是不行,问题比较纠结,我后来想试试,会不会触发这个接收完成中断(ADC_IT_EOC),一样的问题,这个中断也完全不会触发。  但是我再我程序上附加DMA的接收,完全正常(我觉得这个可以说明我ADC初始化应该没大问题吧)………… 我实在想不明白为什么ADC_FLAG_EOC这个中断标志上过不去。。。。  版主有这方面的经验吗?求教啊
点赞  2013-9-17 12:20

回复 板凳Study_Stellaris 的帖子

额,不好意思版主。。。 我刚才没烧对程序,改了之后确实通了。。。。。。。  版主求教啊,这个是为什么呢?  跪谢啊
点赞  2013-9-17 12:29
问下,你后来解决了吗?我出现这个问题但是改了之后发现还是不行
点赞  2013-11-7 12:34

回复 5楼xinsuiwuhen 的帖子

问下,你后来解决了吗?我出现这个问题但是改了之后发现还是不行
点赞  2013-11-7 12:35
引用: 北京 发表于 2013-11-7 12:35
问下,你后来解决了吗?我出现这个问题但是改了之后发现还是不行

我最近也碰到过这个问题,但是最后发现犯得错误很二,,,是由于ADC的初始化函数没有加入到头文件中去,,啊,,,多么痛的领悟,,,
点赞  2014-11-10 21:36
引用: 北京 发表于 2013-11-7 12:35
问下,你后来解决了吗?我出现这个问题但是改了之后发现还是不行
今天我也出现这个问题,发现DMA方式没有问题。另外如果编译选项改为-O1就可以了。
如果编译选项选择-O2或者-Otime就会有楼主说的问题。
原因还在查找当中。
点赞  2014-12-3 17:24

image.png 如果FLASH运行较慢的话,读的时候已经清零了。   image.png  直接操作寄存器快一点      while((ADC1->SR & ADC_FLAG_EOC) == RESET);//等待转换结束  。应该就可以了

点赞  2022-8-22 10:35
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复