二、CC2530的时钟配置
概述
CC2530同样也有两个时钟,一个是高频时钟信号给CPU使用,另一个低频时钟信号给看门狗,睡眠定时器等使用;
相对应的高速时钟CC2530片内有一个16MHz的RC振荡器,也可以使用外接32M时钟晶振,同样的低速时钟也有片外和片内两个,同时如果需要外设和看门狗等,需要设置一个低频的时钟信号,而且内部也有一个低频RC震荡电路。
因此CC2530在完全不接外部晶振的情况下也可以正常工作;
如果使用串口,或者进行通讯的时候,都需要设置为32MHz的时钟信号,否则将不能正常工作!
在配置竟真的时候两个高频时钟源可以同时起振,但是只能有一个供给CPU。
配置32MHz晶振的过程
把默认的16MHzRC振荡器更换为外部32MHz晶振
1、开始需要先让两个时钟源同时开始震荡,就是让SLEEPCMD的第二位为零;
2、之后需要等待时钟源的稳定。即读取SLEEPSTA寄存器的第六位,为1时表示32MHz的时钟源已经稳定了;
3、产生一个63微妙以上的延时;
4、设置32MHz的时钟为不分频的输出,即把寄存器CLKCONCMD的低三位设置为000,表示不分频;
5、选中高频的时钟源作为系统的主时钟,即把寄存器CLKCONCMD的第六位清零,表示令32MHz的时钟源为系统主时钟;
6、最后如果读取的CLKCONSTA这个寄存器的第六位为0,表示32MHz的时钟已经作为了当前的系统主时钟,程序可以继续运行;
下面的代码展示了更换工作频率的过程:
/****************************************************************************
* 名 称: sys32_clk_init()
* 功 能: 把系统时钟设置为32MHz
* 入口参数: 无
* 出口参数: 无
****************************************************************************/
void sys32_clk_init(void)
{
/*开始需要先让两个时钟源同时开始震荡,就是让SLEEPCMD的第二位为零;---------------------------------------------------*/
SLEEPCMD &= 0xFB;
/*之后需要等待时钟源的稳定。即读取SLEEPSTA寄存器的第六位,为1时表示32MHz的时钟源已经稳定了;------------------------*/
while(0 == (SLEEPSTA & 0x40));
/*产生一个63微妙以上的延时;---------------------------------------------------------------------------------------*/
for(int i=0;i<1000;i++) for(int j=0; j<800; j++);
/*设置32MHz的时钟为不分频的输出,即把寄存器CLKCONCMD的低三位设置为000,表示不分频;--------------------------------*/
CLKCONCMD &= 0xF8;
//选中高频的时钟源作为系统的主时钟,即把寄存器CLKCONCMD的第六位清零,表示令32MHz的时钟源为系统主时钟;--------------*/
CLKCONCMD &= 0xBF;
/*最后如果读取的CLKCONSTA这个寄存器的第六位为0,表示32MHz的时钟已经作为了当前的系统主时钟,程序可以继续运行;-------*/
while(CLKCONSTA & 0x40);
}
三、配置串口
CC2530上可以配置两个串口,分别是串口0和串口1,是片上外设。需要对其寄存器进行控制
串口的配置过程:
1、指定串口的IO的位置;
2、对相应的IO配置成片上外设功能;
3、对8个数据位,一个停止位,无流控以及无校验寄存器控制;
4、设置波特率;
5、打开CPU中断;
6、配置对应的串口中断和串口中断函数;
下面的代码展示了配置串口的初始化函数:
/****************************************************************************
* 名 称: uart0_init()
* 功 能: 对串口0进行初始化
* 入口参数: 波特率的大小,可以设置为115200或者9600,输入其他值默认代表115200
* 出口参数: 无
****************************************************************************/
void uart0_init(long int rate)
{
PERCFG = 0x00; //外设控制寄存器 USART 0的IO位置:0为P0口位置1
P0SEL = 0x0c; //P0_2,P0_3用作串口(外设功能)
P2DIR &= ~0xC0; //P0优先作为UART0
U0CSR |= 0x80; //设置为UART方式
switch(rate)
{
case 115200: { U0GCR |= 11; U0BAUD |= 216;} break; //波特率设为115200
case 9600 : { U0GCR |= 8; U0BAUD |= 59 ; }break; //波特率设为115200
default:U0BAUD |= 216; //波特率设为115200
}
UTX0IF = 0; //UART0 TX中断标志初始置位0
U0CSR |= 0x40; //允许接收
IEN0 |= 0x84; //开总中断允许接收中断
}
下面的代码展示了串口发送数据的函数:
/****************************************************************************
* 名 称: printf()
* 功 能: 串口发送函数 !!!需要包含string.h头文件
* 入口参数: Data:发送缓冲区
* 出口参数: 无
****************************************************************************/
void printf(char *a_string_data)
{
u16 qwq;
u16 length_qwq;
length_qwq = strlen(a_string_data); //判断要发送的字符串的长度
for(qwq=0; qwq<length_qwq; qwq++)
{
U0DBUF = *a_string_data++; //一个一个字节的发送和更新数据
while(UTX0IF == 0); //判断是否已经发送完成
UTX0IF = 0;
}
}
下面的代码展示了串口中断函数,可以接收串口接收到的数据:
/****************************************************************************
* 名 称: 串口中断处理函数
* 描 述: 当串口0产生接收中断,将收到的数据保存在RxBuf中
****************************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
int j;
static int qwq;
char RxBuf;
static char data[255];
URX0IF = 0; // 清中断标志
RxBuf = U0DBUF; //读出串口里的数据
if((qwq < 255))//一次最多接收50个字符
data[qwq++] = RxBuf;
if(RxBuf == '\n') //检测接收到了最后一个字符
{
for (j=0;j<255;j++) sdata[j] = data[j]; //把接收到的全局变量先传递出
memset(data, 0, 255);//清空接收缓冲区
qwq=0;
}
}