切换系统高频时钟源

CC2530在正常运行的时候需要一个高频时钟信号和一个低频的时钟信号

  • 高频时钟信号:主要供给给CPU,保证程序的运行
  • 低频时钟信号:主要供给看门狗,睡眠定时器等偏上外设

时钟信号来源

  • 高频信号两个来源:芯片内部的16M RC电路;外接的32M石英晶振
  • 低频信号两个来源:芯片内部的32K RC电路,外接的32.768K石英晶振

CC2530默认上电的时候,是内部的2个RC电路作为高频和低频的时钟来源

如果我们在用串口,特别是无线通信的时候,必须要用32M的石英晶振作为高频时钟来源,16M比32M的速度慢,为32M的1/2

高频时钟源特点:

  • 两个高频时钟源可以同时起振产生高频时钟信号
  • 而两个低频时钟源,某一时刻只能有1个起振,并且起振能的这个时钟源供给CC2530

切换步骤:

1、2个高频时钟源起振; 让SLEEPCMD的第2位为0;

SLEEPCMD &=0xFB;//1111 1011 开启2个高频时钟源

2、待目标时钟源振荡稳定;SLEEPSTA寄存器的第6位为1表示32 时钟源稳定

while(0==(SLEEPSTA & 0x40));// 0100 0000 等待32M稳定

3、 延时一小段时间63us(不定); 超过63微秒延时

void delayus()//调用函数实现
{
    char k=63;
    while(k--);
}

4、不分频输出; 把寄存器CLKCONCMD的低3位 设置为000,表示不分频输出

CLKCONCMD &=0xF8;//1111 1000 不分频输出

5、 选中目标高频时钟源作为系统主时钟; 把寄存器CLKCONCMD的第6位 清0,设置32M作为系统主时钟

CLKCONCMD &=0XBF;//1011 1111 设置32M作为系统主时钟

6、确认一下当前工作的系统时钟是不是所选的高频时钟;如果读CLKCONSTA这个寄存器的第6位为0,表示32M的时钟源已经作为了当前的系统主时钟,程序可以往下运行了。

while(CLKCONSTA & 0x40); //0100 0000 等待32M成功成为当前系统主时钟

数码管测试

32M代码:

#include <iocc2530.h>
#include"74LS164_8LED.h"
void delayus()
{
    char k=63;
    while(k--);
}

void delay()
{
  int i,j;
     for(i=0;i<1000;i++)
       for(j=0;j<800;j++);
}

void Init32M()
{
   SLEEPCMD &=0xFB;//1111 1011 开启2个高频时钟源
   while(0==(SLEEPSTA & 0x40));// 0100 0000 等待32M稳定
   delayus();
   CLKCONCMD &=0xF8;//1111 1000 不分频输出
   CLKCONCMD &=0XBF;//1011 1111 设置32M作为系统主时钟
   while(CLKCONSTA & 0x40); //0100 0000 等待32M成功成为当前系统主时钟
}
void main()
{
     char i;
     LS164_Cfg();
     Init32M();
     while(1)
     {
         for(i=0;i<10;i++)
         {
            LS164_BYTE(i);//数码管显示函数,i为几,数码管显示几
            delay();
         }
     }
}

16M代码:

#include <iocc2530.h>
#include"74LS164_8LED.h"
void delay()
{
  int i,j;
     for(i=0;i<1000;i++)
       for(j=0;j<800;j++);
}
void main()
{
     char i;
     LS164_Cfg();
     while(1)
     {
         for(i=0;i<10;i++)
         {
            LS164_BYTE(i);
            delay();
         }
     }
}

另外附上74LS164_8LED 数码管显示的代码,把代码添加到工程里即可

74LS164_8LED.h

#ifndef __74LS164_8LED_H__
#define __74LS164_8LED_H__
#include<ioCC2530.h>
#define  LS164_DATA  P1_3
#define  LS164_CLK   P1_2
#define  UCHAR  unsigned char 
void LS164_Cfg();
void LS164_BYTE(UCHAR Data);//P1.3  DATA   P1.2  CLK
#endif

74LS164_8LED.c

#include<ioCC2530.h>
#include"74LS164_8LED.h"
static UCHAR LED_Map[]={0x3f,0x06,0x5b,0x4f,
                        0x66,0x6d,0x7d,0x07,
                        0x7f,0x6f,0x00,0xFF};
void LS164_Cfg()
{
    P1SEL &=~0x0C;//xxxx 00xx  配置为普通IO模式
    P1DIR |=0x0C;//xxxx 11xx   配置为输出模式
}
void LS164_BYTE(UCHAR Index) //P1.3  DATA   P1.2  CLK
{  
    UCHAR i=0;
    UCHAR Data=LED_Map[Index];
    for(;i<8;i++)
    {
        if(0x80 & Data)
        {
            LS164_DATA=1;            
        }
        else
        {
            LS164_DATA=0; 
        }
        Data=Data << 1;
        LS164_CLK=0;
        LS164_CLK=1;
    }
}

USB转串口配置

CC2530具备两个串口,且每个串口都可以配置选择控制脚

步骤:

1、指定串口的IO位置

PERCFG &=0xFE;//1111 1110 选中串口0的的备用位置1

2、相应IO配置成偏上外设功能

P0SEL |=0x0C;       //0000 1100 P0_2 p0_3为偏上外设功能

3、8个数据位,1个停止位,无流控,无校验确立

U0CSR |=0Xc0;

4、波特率设置

U0GCR =8;
U0BAUD=59;

5、开CPU中断,对应串口接收中断

EA=1;
URX0IE=1;//结尾为0或8则可以直接选择赋值

USART0接收字符利用中断服务函数

  • 当一个字节由串口接收到C2530,字节会保存到U0DBUF寄存器,同时接收中断标志URX0IF位会置1

  • 可以利用中断服务程序来接收该字符串

  • 中断服务函数

    #pragma vector = URX0_VECTOR
    __interrupt void UART0_ISR(void)

总测试代码

#include <iocc2530.h>
char ch;
void Cfg32M()
{
    SLEEPCMD &=0xFB; //fB 0 00 让2个时钟源都起振
    while(0==(SLEEPSTA & 0x40));  //  0100 0000  如果32M 晶振供电且稳定了,那么程序往下运行
    CLKCONCMD &=0xF8; //1111 1000 不分频输出

    CLKCONCMD &=0xBF;//1011 1111 让32M作为系统主时钟供给CPU
    while(1==(CLKCONSTA & 0x40));//如果32M确实供给CPU在工作,那么程序往下执行
    SLEEPCMD |=0x40;// 0000 0100 
}
void UartCfg()
{//串口0的备用位置1配置成波特率9600
   PERCFG &=0xFE;//1111 1110 选中串口0的的备用位置1
   P0SEL  |=0x0C;       //0000 1100 P0_2 p0_3为偏上外设功能
   
   U0CSR |=0Xc0;
   
   U0GCR =8;
   U0BAUD=59;
   EA=1;
   URX0IE=1;
}

void main()
{
  Cfg32M();
  UartCfg();
    while(1);
}

#pragma vector=URX0_VECTOR//中断服务函数
__interrupt void UART0_ISR(void)
{
    
    URX0IF=0;//串口0来数据的标志位,硬件会置1,我们软件要清0
    ch=U0DBUF;//从接受寄存器里取字节存入变量ch
    
    U0DBUF=ch;//把变量ch里的值赋给串口0发送数据寄存器
    while(0==UTX0IF);
    UTX0IF=0;
}