一、ZigBee时钟介绍
1、时钟信号的产生
(1)高频时钟信号由两个高频振荡器产生:
• 32 MHz 晶振
• 16 MHz RC 振荡器
32 MHz 晶振启动时间对一些应用程序来说可能比较长,因此设备可以运行在 16 MHz RC 振荡器,直到晶振稳定。16 MHz RC 振荡器功耗少于晶振,但是由于不像晶振那么精确,不能用于 RF 收发器操作。
(2)低频时钟信号由两个低频振荡器产生:
• 32 kHz 晶振
• 32 kHz RC 振荡器
32 kHz XOSC 用于运行在 32.768 kHz,为系统需要的时间精度提供一个稳定的时钟信号。校准时 32 kHz RCOSC 运 行 在 32.753 kHz 。 校 准 只 能 发 生 在 32 kHz XOSC 使 能 的 时 候 ,这个校准可以通过使能 SLEEPCMD.OSC32K_CALDIS 位禁用。比起 32 kHz XOSC 解决方案,32 kHz RCOSC 振荡器应用于降低成本和电源消耗。这两个 32 kHz 振荡器不能同时运行。
2、时钟信号作用
CC2530在正常运行时需要一个高频时钟信号和低频时钟信号
CC2530核心板CPU需要高频时钟信号保证程序的运行;
低频时钟信号供给看门狗、睡眠定时器等片上外设。
3、由于16 MHz RC 振荡器功耗少于晶振,但是由于不像晶振那么精确,不能用于 RF 收发器操作。
所以在使用串口,特别是无线通信时,必须要用到32M的石英晶振作为高频时钟来源。
4、高频时钟源特点
两个高频时钟源可以同时起振产生高频时钟信号
两个低频时钟源,某一时刻只能有一个起振,并且起振的这个时钟源供给CC2530
二、系统高频时钟源切换
1、切换步骤:
(1)让两个高频时钟源起振
(2)等待时钟源稳定
(3)延时一小段时间(大于63us)
(4)不分频输出(即输出32M)
注、CLKCONCMD低三位控制分频
(5)选择高频时钟源作为主频
(6)确认当前系统时钟是不是选定的高频时钟源
2、用到的寄存器 SLEEPCMD、SLEEPSTA、CLKCONCMD、CLKCONSTA
(1)SLEEPCMD 睡眠模式控制寄存器
(2)SLEEPSTA 睡眠模式控制状态寄存器
(3)CLKCONCMD 时钟控制命令寄存器
(4)CLKCONSTA 时钟控制状态寄存器
3、操作过程:
(1)让SLEEPCMD的第二位为0,开启两个时钟源。
(2)SLEEPSTA寄存器第6位为1表示32M时钟源振荡稳定
(3)延时大于63us
(4)CLKCONCMD低三位设为000,表示不分频
(5)CLKCONSTA的第6位控制的是系统的主时钟,默认情况下为1,即使用RC16M;当为0时,表示使用外部32M,所以将CLKCONCMD的第6位置0
(6)检查CLKCONSTA的第6位,如果为1,则表示系统还是16M的时钟源,如果为0则表示时钟源为32M。
4、例程:
#include<iocc2530.h>
#include<string.h>
#define uint unsigned int
#define uchar unsigned char
/**********LED延时函数*******/
void delay()
{
uint x,y;
for(x=0;x<)250;x++)
for(y=0;y<2000;y++);
}
/**********时钟源切换延时函数*********/
void delayus()
{
uchar x=250;
while(x--);
}
/*******时钟源切换函数******/
void change32M()
{
SLEEPCMD &= ~0x04;//让两个时钟源起振
while(0==(SLEEPSTA & 0x40));//检测第6位是否为1,表示时钟源稳定
delayus();//延时63us
CLKCONCMD &= ~0x07; //低三位设置分频,此处设置为000,表示不分频
CLKCONCMD &= ~0x40; //第6为置0表示使用32M的时钟源
while(CLKCONSTA & 0x40); //检测第6位是否为0,为0则表示此时系统统时钟使用的时32M的时钟源
}
/*****IO口初始化函数******/
void Init()
{
P1DIR |= 0x01; //P1_0
}
void main()
{
Init();
change32M();
while(1)
{
P1_0 ^=1; //异或运算
delay();
}
}
二、ZigBee定时器T1—查询方式
1、相关寄存器
CC2530的T1定时器(16位)需要配置三个寄存器T1CTL、T1STAT、IRCON
(1)T1CTL 定时器1的控制和状态
(2)T1STAT 定时器1状态寄存器
(3)IRCON 中断标志寄存器
2、例程
/*******定时器T1通过查询方式控制LED1周期性闪烁****/
#include<iocc2530.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define LED1 P1_0
/****P1口初始化函数*****/
void initled(void)
{
P1DIR |= 0x01;
LED1 = 1;
}
/******定时器初始化函数*******/
{
void initT1()
T1CTL = 0x0d; //128分频,自动重装 0x0000-0xFFFF
T1STAT= 0x21; //通道 0,中断有效
}
void main()
{
uchar count=0;
initLed(); //调用初始化函数
initT1();
while(1)
{
if(IRCON > 0)
{
IRCON=0;
if(count++ >= 1) //约 1s 周期性闪烁,大约为 1025MS
{
count=0;
LED1 = !LED1; //LED1 闪烁
}
}
}
}
三、ZigBee定时器T3—中断方式
1、相关寄存器 ——— T3CTL, T3CCTL0, T3CC0, T3CCTL1, T3CC1
(1)T3CTL ——定时器3控制寄存器
(2)T3CCTL0 ——定时器3通道 0捕获/比较控制寄存器
(3)T3CC0 ——定时器 3 通道 0 捕获/比较值
(4)T3CCTL1 —— 定时 3 通道 1 捕获/比较控制
(5)T3CC1——定时器 3 通道 1 捕获/比较值
2、例程
#include <ioCC2530.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define LED1 P1_0
uint count; //定时器计数
/*****P1初始化函数******/
void initled(void)
{
P1DIR |= 0X01;
LED1 = 1;
}
/*******定时器初始化函数*****/
void initT3()
{
T3CTL |= 0x08 ; //开溢出中断
T3IE = 1; //开总中断和 T3 中断
T3CTL |= 0xE0; //128 分频,128/16000000*N=0.5S,N=62500
T3CTL &= ~0x03; //自动重装 00->0xff 62500/255=245(次)
T3CTL |= 0x10; //启动
EA = 1; //开总中断
}
/********定时器T3中断处理函数*******/
#pragma vector = T3_VECTOR
__interrupt void T3_ISR(void)
{
IRCON = 0x00; //清中断标志, 也可由硬件自动完成
if(count++ > 244) //245 次中断后 LED 取反,闪烁一轮(约为 0.5 秒时间)
{
count = 0; //计数清零
LED1 = ~LED1; //改变 LED1 的状态
}
}
void main()
{
initled();
initT3();
while(1);
}
参考声明:
https://www.bilibili.com/read/cv2435936?share_medium=android&share_source=qq&bbid=XY059F20DE97643AA518E1D8E5B92F72BC859&ts=1580379008736