EFR32MG21(Series 2)定时器作为频率信号发生器
关键词:
ZigBee, EmberZnet, TIMER, Frequency, 频率,定时器,MG21, EFR32, ONE-SHOT, PWM
在我司项目研发中,偶然发现EFR32MG21(本文称为MG21)这款ZigBee芯片的性能和配置都特别好,而我们项目刚好用到定时器来进行电机控制,灯光调色等,于是认真的去了解这个芯片定时器的功能,发现有30个多工作模式可以用,经过仔细了解,对于我们会使用到的工作方式作一个说明。也欢迎同行进行开发交流。由于这个定时器工作方式实在太多,我们仅仅会将用到的功能单独成文。这里先介绍的是定时器作为信号发生器。
MG21的定时器功能特别强大和复杂,也可以用来给其他设备提供时钟,为了降低设备对时钟晶振和芯片的需要,也可以直接使用它给其他设备提供时钟。一个稍为复杂的设备可能会用到多个时钟,如果对时钟的要求不是十分严格,则可参考本法。
频率范围
首先要说明的是时钟的频率是有限制的,而且不会十分的精准,我们在使用zigbee协议之后,MG21的高频时钟也就是38.4MHZ的晶振,本文的时钟信号发生器也会是在这个时钟基础上进行分频所得。
MG21定时器频率计算公式为:
[ ftimer = fclk / (2^(perscale+1) x (top + 1)) ]
因此在不改变分频数prescale的条件下,可以配置的频率为 292.96Hz~19.2Mhz。每个定时器还可以通过对时钟进行最高1024次分频,从面得到频率0.2861Hz的信号,这相当于一个周期的时间为3.495秒的信号。这里是用于时钟信号,因此可以认为理论都是50%占空比的方波,但实际上会略有偏差,实测也有可能会是52%。
测试工具和方法
经过理论上的计算之后,我们可以对开发板进行编码测试,测试时可以使用示波器,也可以使用梦源制作的USB逻辑分析仪(型号DSLogic Plus)。用它可以进行测试信号,然后在电脑软件上可以直接显示出信号的数字波型。 它的最大采样速率为400MHz,所以也满足了这次的测量的要求。
为了能够测试结果是否可行,我还们还要让EFR32MG21输出信号,使用一个开发板,在任何一个Zigbee工程当中,增加代码让他输出信号到指定的引脚,(注意避开协议栈默认会占用的引脚),将逻辑分析仪的表笔接到开发板对应引脚上,即可开始测量。开发板可以选择官方的SLWSTK6006A或者我们公司新一信息的NEWBIT-ZDK-2。以官方的为例,接线如下:
图2 逻辑分析与ZigBee开发板的连接方法
测量的结果
下载程序并测量信号,所目标设置为1M时,得到的图3的波形。结果显示是1.01MHz, 计算其误差在1%。对寄存器进行修改,经过测试大致得到如下的规律:
表1
TOP值 |
0 |
1 |
10 |
100 |
65535 |
输出频率 |
19.05MHz |
9.52Mhz |
1.75Mhz |
190.11KHz |
292.93Hz |
上表反映的测量的读数,与理论值并没有完全相符,但差别非常小,对于时钟精准度要求不那么高的话,可以直接使用。
图3 定时器输出设置为1MHz的输出波形
测试的代码
定时器的代码不多,而且也不需要Simplicity studio v4进行配置,为方便大家的测试和使用,我们将所用的代码开源于https://gitee.com/newbitcode/efr32mg_peri。部分代码如下:
// timer configuration void nb_timer_init(void) { uint32_t timerFreq = 0; // Initialize the timer TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT; // Configure TIMER0 Compare/Capture for output compare TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; timerInit.prescale = timerPrescale1; timerInit.enable = false; timerCCInit.mode = timerCCModeCompare; timerCCInit.cmoa = timerOutputActionToggle; // configure, but do not start timer TIMER_Init(TIMER0, &timerInit); // Route Timer0 CC0 output to PC3 GPIO->TIMERROUTE[0].ROUTEEN = GPIO_TIMER_ROUTEEN_CC0PEN; GPIO->TIMERROUTE[0].CC0ROUTE = (TIMER0_GPIO_PORT << _GPIO_TIMER_CC0ROUTE_PORT_SHIFT) | (TIMER0_GPIO_PIN << _GPIO_TIMER_CC0ROUTE_PIN_SHIFT); TIMER_InitCC(TIMER0, 0, &timerCCInit); // Set Top value // Note each overflow event constitutes 1/2 the signal period timerFreq = CMU_ClockFreqGet(cmuClock_TIMER0)/(timerInit.prescale + 1); int topValue = timerFreq / (2*OUT_FREQ) - 1; TIMER_TopSet (TIMER0, topValue); /* Start the timer */ TIMER_Enable(TIMER0, true); } |
有关Simplicity Studio软件安装请进页面,搭建EFR32 ZigBee开发环境>>
。在开发和测试的过程中,感谢世强元件的工程师给予的支持。