晶振起振时间引起的一个小问题

我们知道低功耗的BLE在进行传输的时候,很多情况下数据都不是连续的,像广播包这种数据包,一般是双方约定好,数据按照一定的间隔发送,在数据之间BLE模块是进入低功耗模式的,而在MCU中,当BLE进入低功耗模式的时候,只会保留32.768K的一个时钟,系统的主时钟和一些模拟模块都会掉电,从而降低功耗,只有一个计数器会按照32.768K的时钟进行计数,当计数到一定值之后,会唤醒BLE模块进行数据传输。

而最近我们在使用这个功能的时候发现系统进入低功耗模式之后,计时总会差几百微秒,这个对于数据接收而言是无法接受的,因为这几百微秒的差异可能导致系统错过数据接收的窗口从而造成数据丢失。在分析问题之前我们先来看看整个进入低功耗和唤醒过程的基本流程。

DSM模式流程

DSM(Deep Sleep Mode)是指BLE进入低功耗模式,进入DSM和退出DSM模式的流程如下:

运行状态BLE使用32MHz分频后的1MHz时钟计数运行->准备进入DSM模式之前,系统将等待时间换算为32KHZ时钟计数周期->系统进入低功耗模式,计数时钟转换为32KHz,1MHz时钟关闭->到达计数周期系统唤醒->系统将32KHz下的计数周期折算到1MHz下并用1MHz时钟继续计数->到达指定等待时间开始数据传输

从上面的流程我们可以看到系统进入低功耗模式的时候有两次时钟切换,这主要是因为32KHz时钟比较省电,并且是个一直都在的时钟,所以里面还牵扯到两个时钟之间的切换和换算,之前一直认为是这里有问题,所以一直在分析是不是时钟换算引起的问题,不过后来想想,这个部分仿真应该可以完全cover,根本不用担心,现在仿真基本可以搞定大部分的数字问题,出问题基本都在模拟模块。而模拟部分是仿真的劣势所在。

在问题分析的时候倒是用了各种办法判断时钟是否可靠,比如改变定时时间,看看时间差和定时时间之间的线性关系,不过里面也有不少误导性的结果,这里就不详细说明了,我们还是来看看问题出现的原因。

问题分析

其实后来有数据表明这个时间误差是个绝对值,也就是和定时时间关系不大我们可以看看每次定时和32K时钟计数之间的关系。

DSM_Duration_With_32K_Counter.PNG

我们看到32K的系数还是比较准的,但是会有一个13.615的绝对误差,刚好是几百微秒的定时误差。偶然间我们发现当32MHz(也就是1MHz)计数时钟不关闭的时候整个误差就没有了,所以判断是32MHz时钟的启动时间导致的,而在仿真的时候启动时间很短,因为只是一个模拟电路的模型,启动时间只有90us,而我们实际测试发现晶振的启动时间达到了580us,也就是本来早就应该计数的1MHz计数器会多等待几百微秒之后才计数,所以当把晶振启动时间提前之后问题得到解决。

结论

晶振启动时间在电路中有不确定因素,和MCU内部的起振电路以及晶振外面的电路电容以及晶振本身都有关系,在一般应用中起振时间时间可能影响不大,但是在这个BLE模块设计中,并没有考虑到晶振起振时间的变化,而只是在晶振使能之后等待了一个时间就认为晶振已经有效,这个才是这个问题的真正根源,通过调整电路时延只是一个治标不治本的解决方法,并不能适应各种类型的晶振和电路。在这还想到一个问题,晶振其实是比较脆弱的,在某些情况下还可能出现晶振不起振的问题,这个又是另外一个问题了。

发表新评论