STM32L053 隔几秒钟采集一次数据。STM32L053 低功耗时,进入停止模式,通过RTC中断唤醒,唤醒后,打开EnableADC()采集数据,采集完成后,关闭DisableADC(),以节省电池电量。但是有时候出现死循环,不知道是怎么回事,也是按参数手册上面做的,还是不行。 void EnableADC(void) { ADC1->ISR |= ADC_ISR_ADRDY; ADC->CCR |= (ADC_CCR_VREFEN|ADC_CCR_TSEN); ADC1->CR |= ADC_CR_ADEN; //使能ADC if ((ADC1->CFGR1 & ADC_CFGR1_AUTOFF) == 0) { while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) { //这里可以添加超时管理 /*打开时,这个地方有时候出现死循环*/ } } ADC1->CR |= ADC_CR_ADSTART; //启动ADC转换 } void DisableADC(void) { //确保没有转换 if ((ADC1->CR & ADC_CR_ADSTART) != 0) { //停止任何正在进行的转换 ADC1->CR |= ADC_CR_ADSTP; } //等到ADSTP由硬件复位即停止转换 while ((ADC1->CR & ADC_CR_ADSTP) != 0) { //这里可以添加超时管理 } ADC1->CR |= ADC_CR_ADDIS; //禁用ADC //等到ADC是完全禁用 while ((ADC1->CR & ADC_CR_ADEN) != 0) { //这里可以添加超时管理 /*关闭时,这个地方有时候出现死循环*/ } ADC1->ISR |= ADC_ISR_ADRDY; ADC->CCR &= ~(ADC_CCR_VREFEN|ADC_CCR_TSEN); } |
STM32L011D4芯片用SWD无法下载程序
求助:STM32L0系列标准库哪里下?
STM32L051低温时LPUART串口波特率异常
STM32L051单片机ADC如何彻底关闭?
STM32L051C8进入低功耗模式电流偏大
STM32L052C8T6通过I2C模拟读16位数
STM32L0的VLCD外接5V会有问题吗
求助!!使用STM32L073 IO口模拟IIC接口读写AT24CM01 程序不停...
STM32L072RB写Bank2 EEPROM不响应中断
STM32L031无法进入boot
下面是开始程序时的ADC与DMA的初始化部分。
uint16_t ADC_array[6];
//这个函数配置ADC的DMA来存储结果序列,转换的结果存储在n个元素数组
void ConfigureDMA(void)
{
//使外围时钟DMA
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
//启用DMA传输ADC
ADC1->CFGR1 |= ADC_CFGR1_DMAEN;
//配置外围数据寄存器地址
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
//配置内存地址
DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
//配置待传输的数据数 的数量
DMA1_Channel1->CNDTR = 6;
//配置使能存储器递增模式、存储器16 位模式、外设16 位模式,
//传输错误中断使能和传输完成中断使能
DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 \
| DMA_CCR_TEIE | DMA_CCR_TCIE;
//使能DMA
DMA1_Channel1->CCR |= DMA_CCR_EN;
//启用中断DMA通道1
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
//设置优先级的DMA通道1
NVIC_SetPriority(DMA1_Channel1_IRQn,2);
}
void ADC_Init(void)
{
//使外围时钟GPIOA GPIOC
//AD1=PA4=IN4 AD2=PA5=IN5 AD3=PA0=IN0 AD4=PC3=IN13
RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOCEN;
//设置口线为模拟输入
GPIOA->MODER |= (GPIO_MODER_MODE0|GPIO_MODER_MODE4|GPIO_MODER_MODE5);
GPIOC->MODER |= GPIO_MODER_MODE3;
//使外围ADC的时钟
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
//ADCCLK(异步时钟模式)
ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE;
//选择连续转换模式
ADC1->CFGR1 |= ADC_CFGR1_CONT;
ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL4 | ADC_CHSELR_CHSEL13 \
| ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL17 | ADC_CHSELR_CHSEL18;
//采样时间选择39.5 个 ADC 时钟周期
ADC1->SMPR = ADC_SMPR_SMP_0 | ADC_SMPR_SMP_2;
//采样时间选择79.5 个 ADC 时钟周期
//ADC1->SMPR = ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2;
//使能溢出中断 OVR 位置 1 时产生中断
ADC1->IER = ADC_IER_OVRIE;
//使能 VREFINT,使能温度传感器
ADC->CCR |= (ADC_CCR_VREFEN|ADC_CCR_TSEN);
//ADC上启用中断
NVIC_EnableIRQ(ADC1_COMP_IRQn);
//为ADC设置中断优先级
NVIC_SetPriority(ADC1_COMP_IRQn,3);
if(vref_vol == 0)
{
//以下几行为ADC 校准
//确保 ADEN=0
if ((ADC1->CR & ADC_CR_ADEN) != 0)
{
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN);
}
//将 ADCAL 置 1
ADC1->CR |= ADC_CR_ADCAL;
//等待,直至 ADCAL=0
while ((ADC1->ISR & ADC_ISR_EOCAL) == 0)
{
}
//校准已完成
ADC1->ISR |= ADC_ISR_EOCAL;
/* 计算内部Vref电压(mV) */
vref_vol = (uint16_t)( 3000.0 * (*(uint16_t *)0x1FF80078) / 4095.0);
Vrefint_cal=(*(uint16_t *)0x1FF80078);
}
ConfigureDMA(); //函数配置ADC的DMA
}
ADC采集数据时,单片机是不进入停止模式的,采集完成后,才进入停止模式,单片机采集数据,采用的是ADC+DMA的方式,DMA中断。ADC与DMA的初始化,在开始程序中完成。ADC打开采集与关闭在唤醒后while(1){ }中使用。
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
没有重新配置时钟,时钟配置在开始的程序中,已经配置了。唤醒后,打开EnableADC(); 采集完成后,DisableADC();,然后, __WFI();,周而复始。
评分
查看全部评分
好的,试下,唤醒后再重新配置时钟。我是这样使用的。
int main(void)
{
......
LCD_Init();
RTC_Init(); //RTC定时唤醒停止模式下的单片机
ADC_Init();
......
while (1)
{
...... if(采集数据=1)
{
采集数据=0;
采集完成=0;
EnableADC();
}
......
if(采集完成=1)
{
采集完成=0;
DisableADC();
}
......
if(无数据采集)
{
__WFI();
}
}
}
是保持配置,你可以不重新配置时钟, 但是相应外设的时钟还是需要自己开启的 ,
我在开始初始化的程序中,外设时钟打开,进入停止模式时,没有关闭相应的外设时钟,刚才我试了下,进入停止模式时,关闭相应外设时钟,退出停止模式时,打开相应外设时钟,电流是一样的, 我的RTC+LCD时,停止模式时,电流是28 uA,不知道你们可以最低降到多少。我也感觉电流大了,但是降不下来了。
//程序完成后将调试线置为模拟
GPIOA->MODER |= (GPIO_MODER_MODE13 |GPIO_MODER_MODE14);
//禁止 PVD 电源电压检测器
CLEAR_BIT(PWR->CR, PWR_CR_PVDE);
//使超低功率模式 VREFINT 在低功耗模式下关闭
//SET_BIT(PWR->CR, PWR_CR_ULP);
//从超低功率模式使快醒来
SET_BIT(PWR->CR, PWR_CR_FWU);
//(HSI) 振荡器作为从停止模式唤醒时钟
MODIFY_REG(RCC->CFGR,RCC_CFGR_STOPWUCK, (uint32_t)(RCC_CFGR_STOPWUCK) );
RCC->CFGR |= RCC_CFGR_STOPWUCK; //(HSI) 振荡器作为从停止模式唤醒时钟
//CLEAR_BIT(PWR->CR, PWR_CR_LPRUN);
CLEAR_BIT(PWR->CR, (PWR_CR_PDDS | PWR_CR_LPSDSR |PWR_CR_LPRUN)); //清除标志
SET_BIT(PWR->CR, (PWR_CR_LPSDSR|PWR_CR_LPRUN)); //设置标志 低功率运行模式下调压器进入低功耗模式
// SET_BIT(PWR->CR, PWR_CR_LPRUN);
SET_BIT(SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
SET_BIT(SCB->SCR, SCB_SCR_SLEEPONEXIT_Msk);
__WFI();
评分
查看全部评分