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

stm32 ADC定时唤醒采集数据,工作一段时间adc值不变了

[复制链接]
baosong123 提问时间:2018-8-18 16:13 /
程序整体 是开机工作 采集数据,数据符合要求就进入stm32停机模式,同时开启rtc 2s的闹钟,闹钟唤醒后继续采集数据,判断数据情况在进入停机反复如此
现在问题是程序复位后可以正常采集 正常工作,但是不知道过多久,随机的,adc的数据就会停留在一个固定数值,不论我怎么调节模拟输入都无效
用仿真器查了  dma 和  数据buf 和adc的DR寄存器数值都一致,排除数据处理的问题,在adc这边数据已经不采集了不知道哪里的问题,求助大神们
adc 相关代码
#include "ADC_init.h"
u16 ADC_ConvertedValue[2]={0,0};



void ADC_Configuration(void)

{

       ADC_InitTypeDef   ADC_InitStructure;   //定义adc结构体      
       DMA_InitTypeDef DMA_InitStructure;  //定义dma结构体
       


           DMA_DeInit(DMA1_Channel1);        /* 将与 DMA 有关的寄存器设我初始值 */
/*定义 DMA 外设基地址, 这里的 ADC1_DR_Address 是用户自己定义的,即为存放转换结果的寄存器 ,他的作用
就是告诉 DMA 取数就到 ADC1_DR_Address 这里来取。*/
DMA_InitStructure.DMA_PeripheralBaseAddr =ADC1_DR_Address;

/*定义内存基地址,即告诉 DMA 要将从 AD 中取来的数放到 ADC_ConvertedValue 中 */
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&ADC_ConvertedValue;
/*定义 AD 外设作为数据传输的来源,即告诉 DMA 是将 AD 中的数据取出放到内存中,不能反过来*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/*指定 DMA 通道的 DMA 缓存的大小,即告诉 DMA 开辟几个内存空间,由于我们只取通道 10 的 AD 数据所以只需
开辟一个内存空间*/
DMA_InitStructure.DMA_BufferSize = 2;
/*设定寄存器地址固定,即告诉 DMA,只从固定的一个地方取数*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*设定内存地址固定,即每次 DMA,,只将数搬到固定的内存中*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*设定外设数据宽度,即告诉 DMA 要取的数的大小*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

/*设定内存的的宽度*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

/*设定 DMA 工作再循环缓存模式,即告诉 DMA 要不停的搬运,不能偷懒*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

/*设定 DMA 选定的通道软件优先级*/
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA channel1,CPU 有好几个 DMA 秘书,现在只用 DMA1_Channel1 这个秘书*/
DMA_Cmd(DMA1_Channel1, ENABLE);

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;/*设置 ADC 工作在独立模式*/
ADC_InitStructure.ADC_ScanConvMode = ENABLE; /*单通道选择dis,多通道选择en*/
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /*设定 AD 转化在连续模式*/
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        /*不使用外部chu发转换*/
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;/*采集的数据在寄存器中以右对齐的方式存放*/
ADC_InitStructure.ADC_NbrOfChannel = 2;        /*设定要转换的 AD 通道数目*/
ADC_Init(ADC1, &ADC_InitStructure);

//ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器

RCC_ADCCLKConfig(RCC_PCLK2_Div8); /*配置 ADC 时钟,为 PCLK2 的 8 分频,即 9MHz*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_3,1, ADC_SampleTime_239Cycles5); /*配置 ADC1 的通道3为 55.5 个采样周期 ,负压传感*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_9,2, ADC_SampleTime_239Cycles5); /*配置 ADC1 的通道9为 55.5 个采样周期 ,电池电压*/
ADC_DMACmd(ADC1, ENABLE);  /* Enable ADC1 DMA */
ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 */
ADC_ResetCalibration(ADC1);/*复位校准寄存器 */

while(ADC_GetResetCalibrationStatus(ADC1));        /*等待校准寄存器复位完成 */

ADC_StartCalibration(ADC1);        /* ADC 校准 */

while(ADC_GetCalibrationStatus(ADC1));        /* 等待校准完成*/

ADC_SoftwareStartConvCmd(ADC1, ENABLE);/* 由于没有采用外部触发,所以使用软件触发 ADC 转换 */       

}





sd.png
收藏 评论18 发布时间:2018-8-18 16:13

举报

18个回答
baosong123 回答时间:2018-9-1 11:24:31
butterflyspring 发表于 2018-8-29 11:47
STOP mode唤醒之后就是MSI作为系统时钟,如果你之前不是用MSI,你不需要重新配置?

我现在可以确定,确实是因为添加了stop模式之后出的问题,如果屏蔽掉stop模式 就没问题,每次需要复位adc才恢复正常,然后又运行一段时间又出问题
void work_200ms(void)
{
         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);   //打开复用功能和adc时钟       

                                        if(Press_set==0)//如果处于暂停状态进入停机
                                                {
                                                        TIM_SetAutoreload(TIM1,100);//改频率
                                                        TIM_SetCompare4(TIM1,0);//改占空比
                                       
                                                        Ledless_L;       
                                                        warn_voice(off,100,500);//关闭漏气报警
                                                        warn_time=0;       
                                                  stop_mode();     
                                                }       
       
               
                               
        if(Press_set==125&&time2_flag==1&&press_end==1)//如果处于工作状态并且 达到200ms定时,并且 压力达到设定值进入停机
        {                                TIM_Cmd(TIM2, DISABLE); //关闭计时                                       
                                        time2_flag=0;
                                        work_time=0;
                                        debug_string("Press_adc:");                       
                                        debug_16bit_assic(Press_adc);
                                        debug_string("Vbat_adc:");                       
                                        debug_16bit_assic(Vbat_adc);
                //debug_string("Vref_adc:");                       
                        //                debug_16bit_assic(Vref_adc);                       
               
//200ms工作完成,清除ad数据,下次唤醒重新采集
                                        ready_num=0;
                                //adc_num=0;
                                //Adc_ready=0;
                                //清场完毕,打开rtc时钟,进入睡眠
                if(Stop_flag==0)
                {
                                        RTC_init();                //配置rtc
                                        RTC_EXTI_INITIAL(ENABLE);//打开闹钟中断
                                        Stop_flag=1;
                           stop_mode();
                }
        }

                Ledrun_L;


}
baosong123 回答时间:2018-9-3 13:52:04
我有在唤醒后重新配置了时钟,唤醒后第一时间配置的时钟,和开机复位刚运行是同一个时钟函数
void clk_init(void)
{   ErrorStatus HSEStartUpStatus;
    RCC_DeInit();                 //RCC寄存器设置为默认值
    RCC_HSEConfig(RCC_HSE_ON);        //打开高速外部时钟

    HSEStartUpStatus=RCC_WaitForHSEStartUp ();         //等待时钟起振
    if(HSEStartUpStatus == SUCCESS)
    {
        RCC_HCLKConfig(RCC_SYSCLK_Div1);                 //AHB 时钟为系统时钟
        RCC_PCLK2Config(RCC_HCLK_Div1);           //高速AHB总线时钟为系统时钟
        RCC_PCLK1Config(RCC_HCLK_Div2);                        //低速AHB总线为1/2系统时钟
        FLASH_SetLatency(FLASH_Latency_2);
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//预取指缓存使能

        RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);        //设置PLL输入时钟分频和PLL 倍频系数
        RCC_PLLCmd(ENABLE);
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);


        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);   //设置pll输出时钟为系统时钟
        while(RCC_GetSYSCLKSource()!=0x08);
    }

                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);   //打开复用功能和adc时钟                                  
   
}
baosong123 回答时间:2018-9-8 09:31:52
程序重新规划,只写了一个最简单定时一秒进入闹钟,唤醒 后立即停机
                RTC_init();//闹钟初始化
       
                while(1)
                                {
                                       
                                stop_mode();       
                                        if(Stop_flag==0)       
                                        {
                                        debug_16bit_assic(sleep_num);       
                                  debug_16bit_assic(ADC_ConvertedValue[0]);       
                                        }
                                       
       
                               


                                }

adc的死机问题也是存在
五哥1 回答时间:2018-8-18 22:48:12
什么硬件?把内存再扩大一些,在一些关键节点加个延时看看

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

feixiang20 回答时间:2018-8-18 23:14:44
是否超过数值限制了

评分

参与人数 1蝴蝶豆 +1 收起 理由
zero99 + 1

查看全部评分

jiekechoo 回答时间:2018-8-19 09:36:49
我的STM32L152,第一次读取ADC数据正常,然后进入STOP模式后5分钟唤醒,再读ADC数据一直是第一次的数据。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

baosong123 回答时间:2018-8-20 10:56:17
我现在把 低功耗那块屏蔽了,工作了几个小时,没有出现adc 停机的情况,怀疑是频繁进入低功耗引起的
butterflyspring 回答时间:2018-8-20 11:43:47
是不是ADC进入低功耗了,你可以尝试重新设置看看?

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

jiekechoo 回答时间:2018-8-25 17:30:36
butterflyspring 发表于 2018-8-20 11:43
是不是ADC进入低功耗了,你可以尝试重新设置看看?

重新唤醒后,时钟挂了?
butterflyspring 回答时间:2018-8-28 15:28:15
jiekechoo 发表于 2018-8-25 17:30
重新唤醒后,时钟挂了?

stop mode之后需要重新配置时钟呀
jiekechoo 回答时间:2018-8-28 17:23:02
butterflyspring 发表于 2018-8-28 15:28
stop mode之后需要重新配置时钟呀

重新初始化?你搞过STOP模式吗?
butterflyspring 回答时间:2018-8-29 11:47:19
jiekechoo 发表于 2018-8-28 17:23
重新初始化?你搞过STOP模式吗?

STOP mode唤醒之后就是MSI作为系统时钟,如果你之前不是用MSI,你不需要重新配置?


delete.JPG
jiekechoo 回答时间:2018-8-29 17:32:08
butterflyspring 发表于 2018-8-29 11:47
STOP mode唤醒之后就是MSI作为系统时钟,如果你之前不是用MSI,你不需要重新配置?

官方的例程里早就写明了需要重新配置时钟的,而且,必须要跟你启动时的时钟一样才有意义。

现在问题好像不是时钟问题,是ADC读取的问题了。唤醒后,读取ADC是失败的。

baosong123 回答时间:2018-9-3 13:53:51
void out_stop(void)
{
        clk_init();
        USART_Cmd(USART1, ENABLE);
        work_time=0;
        time2_flag=0;
        debug_string("wake\n");        

}

void stop_mode(void)
{
        

debug_string("in stop\n");        

USART_Cmd(USART1, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
//PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);


}
这是进入和退出停机模式的函数,请高手指教,停机模式里我屏蔽掉pwr那条指令,程序运行就不会出问题,加上这个过段时间就adc数据就保持不变了
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版