程序整体 是开机工作 采集数据,数据符合要求就进入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 转换 */ } |
我现在可以确定,确实是因为添加了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;
}
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时钟
}
RTC_init();//闹钟初始化
while(1)
{
stop_mode();
if(Stop_flag==0)
{
debug_16bit_assic(sleep_num);
debug_16bit_assic(ADC_ConvertedValue[0]);
}
}
adc的死机问题也是存在
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
重新唤醒后,时钟挂了?
stop mode之后需要重新配置时钟呀
重新初始化?你搞过STOP模式吗?
STOP mode唤醒之后就是MSI作为系统时钟,如果你之前不是用MSI,你不需要重新配置?
官方的例程里早就写明了需要重新配置时钟的,而且,必须要跟你启动时的时钟一样才有意义。
现在问题好像不是时钟问题,是ADC读取的问题了。唤醒后,读取ADC是失败的。
{
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数据就保持不变了