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

STM32L0系列ADC的低功耗模式AUTOFF和WAIT功能的使用疑惑

[复制链接]
iPeanut 提问时间:2022-1-2 19:13 / 未解决

在使用ADC的时候发现一些疑问,和调试分析分享 1.手册上介绍ADC有个低功耗模式,配置寄存器将AUTOFF=1和WAIT=1,可以让ADC在转换完成后自动关闭,再次触发时会自动开启,可以有效降低功耗。我将这两位功能使能后,发现每次想开启采样,若采用LL库函数LL_ADC_Enable()将ADEN位置1后,是无法等到ADRDY位被置1的,也就是ADRDY始终是0,但是如果不给ADEN置1,直接用LL_ADC_REG_StartConversion()函数给ADSTART位置1,让ADC开始转换,也是可以正常开始的,读到的ADC结果也正常。想问一下这是不是就是AUTOFF和WAIT产生的效果,那么在使用中,只要使能这两位,每次开启ADC采样的时候,直接使能开始ADSTART=1就可以了,不用再让ADEN=1,这样对吗?

2.结合第1个问题,我使用的cubeMX的LL库生成的ADC初始化函数,其中将AUTOFF=1,WAIT=1,上电后,运行完该初始化函数后,使用了校准功能,调用了LL_ADC_StartCalibration(ADC1)进行校准,调试发现,执行完该校准,再延时几个时钟周期后,ADC好像就已经可以正常工作,也是没有ADEN=1的情况下,直接让ADSTART=1,ADC就可以采集到正确数据了。我看到手册中有这样一个描述:启动校准(将ADCAL置1)时,或者使能ADC时(将ADEN置1),ADVREGEN位通过硬件被置1。也就是说执行了校准操作后ADC的调压器被使能了,且又被配置成了AUTOFF=1和WAIT=1的模式,那么在调压器使能的状态下,只要执行ADSTART=1就可以正常开始转换了。再结合其他讨论中有人说到如果要在系统进入低功耗模式前将ADC的调压器失能ADVREGEN=0才可以,据此推断,如果系统唤醒后想让ADC恢复正常工作,必须再执行一次校准操作或者执行一次ADEN=1的操作才可以。我在调试中在进入芯片的STOP模式前执行了CLEAR_BIT(ADC1->CR, ADC_CR_ADVREGEN)禁止调压器,在退出STOP模式后,再执行了一次LL_ADC_StartCalibration(ADC1)的校准操作,ADC都可以恢复正常采集数据。请教一下我的上述操作是否正确可靠?

3.虽然手册中介绍说AUTOFF和WAIT使能后ADC可以在采集后自动关闭,但我想尽快降低功耗,所以每次读取到序列最后一个数据后,都再执行一次ADSTP=1和ADDIS=1的操作。我的设计采用的是定时器中断里进行一次ADC采样的方式,每次中断里采样完毕还必执行一次LL_ADC_REG_StopConversion(ADC1)让ADSTP=1使ADC停止,然后再必执行一次LL_ADC_Disable(ADC1)让ADDIS=1使ADC关闭,而下次中断进入时,也是不执行ADEN=1,直接让ADSTART=1,等待ADC获得正确的采样值。。当前调试使用这种方式都是可以获得正确的采样数据的。但拿不准是否会有隐患。请问我这样使用是否规范可靠?

收藏 评论28 发布时间:2022-1-2 19:13

举报

28个回答
xmshao 回答时间:2022-1-6 12:08:52
你写的很多很详细,涉及细节还是很多的。这里逐一跟你交流下。


1、手册上介绍ADC有个低功耗模式,配置寄存器将AUTOFF=1和WAIT=1,可以让ADC在转换完成后自动关闭,再次触发时会自动开启,可以有效降低功耗。我将这两位功能使能后,发现每次想开启采样,若采用LL库函数LL_ADC_Enable()将ADEN位置1后,是无法等到ADRDY位被置1的,也就是ADRDY始终是0,但是如果不给ADEN置1,直接用LL_ADC_REG_StartConversion()函数给ADSTART位置1,让ADC开始转换,也是可以正常开始的,读到的ADC结果也正常。想问一下这是不是就是AUTOFF和WAIT产生的效果,那么在使用中,只要使能这两位,每次开启ADC采样的时候,直接使能开始ADSTART=1就可以了,不用再让ADEN=1,这样对吗?


===》这样没有什么问题,你的ADSART指令即可开启ADC转换,当然硬件会自动插入启动稳定时间,达到ADEN=1,ADRDY=1的效果。在AUTOFF=1和WAIT=1的情况下,软件启动或硬件触发或对ADC_DR的访问都可以启动ADC转换。


2、结合第1个问题,我使用的cubeMX的LL库生成的ADC初始化函数,其中将AUTOFF=1,WAIT=1,上电后,运行完该初始化函数后,使用了校准功能,调用了LL_ADC_StartCalibration(ADC1)进行校准,调试发现,执行完该校准,再延时几个时钟周期后,ADC好像就已经可以正常工作,也是没有ADEN=1的情况下,直接让ADSTART=1,ADC就可以采集到正确数据了。


===》这个其实跟第一个问题是一样的。尽管校准后理应进入ADC的power off状态,但ADSTART=1还是可以开启ADC转换。这里顺便说下,当我们将ADC配置在AUTOFF状态时,硬件会无视ADRDY标志的,而且会始终保持0状态,也就是上面你提到过的它始终为0的情形.



3、我看到手册中有这样一个描述:启动校准(将ADCAL置1)时,或者使能ADC时(将ADEN置1),ADVREGEN位通过硬件被置1。也就是说执行了校准操作后ADC的调压器被使能了,且又被配置成了AUTOFF=1和WAIT=1的模式,那么在调压器使能的状态下,只要执行ADSTART=1就可以正常开始转换了。再结合其他讨论中有人说到如果要在系统进入低功耗模式前将ADC的调压器失能ADVREGEN=0才可以,据此推断,如果系统唤醒后想让ADC恢复正常工作,必须再执行一次校准操作或者执行一次ADEN=1的操作才可以。我在调试中在进入芯片的STOP模式前执行了CLEAR_BIT(ADC1->CR, ADC_CR_ADVREGEN)禁止调压器,在退出STOP模式后,再执行了一次LL_ADC_StartCalibration(ADC1)的校准操作,ADC都可以恢复正常采集数据。请教一下我的上述操作是否正确可靠?


===》没有什么不可靠。首先,即使你关闭了ADC voltage regulator,当我们进行ADC校准时硬件会自动开启之。校准后即可直接使用ADSTART=1来开启ADC转换,当然此时还是基于你说到的AUTOFF=1模式。


4、虽然手册中介绍说AUTOFF和WAIT使能后ADC可以在采集后自动关闭,但我想尽快降低功耗,所以每次读取到序列最后一个数据后,都再执行一次ADSTP=1和ADDIS=1的操作。我的设计采用的是定时器中断里进行一次ADC采样的方式,每次中断里采样完毕还必执行一次LL_ADC_REG_StopConversion(ADC1)让ADSTP=1使ADC停止,然后再必执行一次LL_ADC_Disable(ADC1)让ADDIS=1使ADC关闭,而下次中断进入时,也是不执行ADEN=1,直接让ADSTART=1,等待ADC获得正确的采样值。


===》你的这些操作没有啥问题,也没看出有啥隐患。你没必要自己手动执行ADSTP=1和ADDIS=1操作了,硬件会自动完成。
butterflyspring 回答时间:2022-1-5 17:21:48
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主需要进一步进入低功耗模式,由于主电源调节器进入了低功耗模式,所以ADC的电压调节器也就不能工作了。
对于进出低功耗的操作手册上有一个顺序介绍,楼主按照这个顺序操作就可以了,附图就是这个顺序截图。
STM32L0 POWEROFFADC REG.png
STMCU-管管 回答时间:2022-1-3 17:41:26
可以看看这篇文章。点击
iPeanut 回答时间:2022-1-4 12:57:59

STMCU-管管 发表于 2022-1-3 17:41
可以看看这篇文章。点击

感谢您的回复。这篇文章中提到的退出STOP模式时,如果采用的是快速唤醒不考虑vrefint的时间有可能影响到ADC。我在使用时确实也是用的快速唤醒,我有两种进入STOP的情况,一种是准备长时间停留在STOP中,只有外部按键产生的中断才能唤醒,在这种模式下,进入STOP前使用CLEAR_BIT(ADC1->CR, ADC_CR_ADVREGEN)禁止的是ADC的调压器,退出STOP后一定使用校准操作再次启用ADC的调压器,并且也会等待几个时钟周期后再开启ADC功能,所以应该有足够的时间让ADC恢复正常。第二种情况是,设备正常工作期间,用定时器LPTIM定时去ADC采样,依靠每次定时器的中断唤醒STOP,这种情况下进入STOP前也是设置成快速唤醒,HSI保持工作,但不会将ADC的调压器禁止,LPTIM中断唤醒STOP后,在该中断回调函数中使能ADCSTART=1等待获得转换结果再退出中断回调函数。这第二种情况我这样使用是否有什么隐患吗?

iPeanut 回答时间:2022-1-5 20:29:38

butterflyspring 发表于 2022-1-5 17:21
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主 ...

很感谢您的回复,很有帮助。又去看了手册确实如您所说。但又增加了新的疑问:

1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢?

2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC的调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-5 20:31:14

butterflyspring 发表于 2022-1-5 17:21
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主 ...

很感谢您的回复,很有帮助。又去看了手册确实如您所说。但又增加了新的疑问: 1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢? 2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC的调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-5 20:36:52

很感谢您的回复,很有帮助。又去看了手册确实如您所说。但又增加了新的疑问: 1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢? 2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC的调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-6 08:54:52

butterflyspring 发表于 2022-1-5 17:21
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主 ...

很感谢您的回复,很有帮助。又去看了手册确实如您所说。但又增加了新的疑问: 1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢? 2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-6 08:59:23

很感谢您的回复,很有帮助。又去看了手册确实如您所说。但又增加了新的疑问:

1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢?

2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。外部中断唤醒STOP后,也不执行开启ADC的调压器操作。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-6 11:18:59

butterflyspring 发表于 2022-1-5 17:21
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主 ...

很感谢您的回复

iPeanut 回答时间:2022-1-6 11:20:01

butterflyspring 发表于 2022-1-5 17:21
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主 ...

很有帮助。又去看了手册确实如您所说。但又增加了新的疑问

1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢? 2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。外部中断唤醒STOP后,也不执行开启ADC的调压器操作。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-6 11:20:33
iPeanut 回答时间:2022-1-6 11:20:58

butterflyspring 发表于 2022-1-5 17:21
手册中关于AUTOFF 和 WAIT 介绍中提到,只要读取转换值后,再次触发就可以继续转换,并且后面有示意图
楼主 ...

1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢?

iPeanut 回答时间:2022-1-6 11:21:28

iPeanut 发表于 2022-1-6 11:20
很有帮助。又去看了手册确实如您所说。但又增加了新的疑问

1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢? 2.在我的第二种低功耗应用场景中,需要用LPTIM定时唤醒STOP,LPTIM的定时中断周期大约为4ms,在该中断中执行ADC采样操作,读取采样数据后就执行停止转换ADSTP=1,并将ADEN清0使ADC关闭(虽然我配置AUTOFF=1,但也执行了这个关闭动作),但不执行关闭ADC调压器的操作,退出中断后回到主循环,然后进入STOP等待下一个定时中断的到来。外部中断唤醒STOP后,也不执行开启ADC的调压器操作。主要是不想在反复开关ADC调压器上占用过多的等待时间,所以始终没执行ADVREGEN清0的操作。请问我这种不关闭ADC调压器就进入STOP的操作方式可靠吗?

iPeanut 回答时间:2022-1-6 11:21:49

iPeanut 发表于 2022-1-6 11:20
很有帮助。又去看了手册确实如您所说。但又增加了新的疑问

1.在我的第一种应用场景中,需要长时间停留在STOP里时,进入STOP前确实按照手册介绍的那个顺序执行的,但是在退出STOP时,并没有作循环等待REGLPF=0的操作,因为在看HAL库和LL库的例程里并没有看到等待这个标志位的操作所以忽略了,请问REGLPF位恢复为0大概需要多少时间?我用外部中断退出STOP时,中断回调函数入口的大概有4-5条语句执行后(系统时钟16MHz),这个时长是否足够保证REGLPF位恢复为0呢?也就是利用执行语句的延时是否可以保证后面的程序运行可靠呢?

12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版