zigbee从入门到砸开发板之CC2530(二)
文章目录
4、时钟
概述
1、CC2530在正常运行的时候需要一个高频时钟信号和一个低频的时钟信号
- 高频时钟信号,主要供给CPU,保证程序的运行。
- 低频时钟信号,主要供给看门狗、睡眠定时器等偏上外设。
2、时钟信号的来源;
- 高频信号有2个,芯片内部的16M RC电路;外接的32M石英晶振
- 低频信号也有2个来源,芯片内部的32K RC电路,外接的32.768K石英晶振。
3、CC2530芯片默认上电的时候,是内部的2个RC电路作为高频和低频的时钟来源。
4、如果我们在用串口,特别是无线通信的时候,必须要用32M的石英晶振作为高频时钟来源。
5、高频时钟源特点:
- 2个高频时钟源可以同时起振产生高频时钟信号,但只有一个有效。
- 而2个低频时钟源,某一时刻只能有1个起振,并且起振的这个时钟源供给CC2530.
CLKCONCMD 时钟控制命令寄存器
CLKCONCMD | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
位 | OSC32K | OSC | TICKSPD | TICKSPD | TICKSPD | CLKSPD | CLKSPD | CLKSPD |
OSC:系统时钟源选择位:【0:32MHZ的XOSC】【1:16MHZ的RCOSC】
CLKSPD:时钟速度(不能高于OSC设置的系统时钟设置)(可以为任意值,受OSC位的限制,如果OSC==1 ,无论本位是多少,都会还原成16MHZ)[000:为32MHZ,000+1:为32/2MHZ,…]
CLKCONSTA 时钟控制状态寄存器
CLKCONSTA | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
位 | OSC32K | OSC | TICKSPD | TICKSPD | TICKSPD | CLKSPD | CLKSPD | CLKSPD |
控制命令发出后,通过本寄存器查询是否完成设置
切换系统时钟源步骤
- 起振两个高频时钟源,并等待稳定起振
- 延时一段时间
- 设置时钟源(不分频、选外部32MHZ),并查询是否设置成功
1、让SLEEPCMD的第2位为0;
2、SLEEPSTA寄存器的第6位为1表示32M 时钟源稳定
3、超过63微秒延时
4、把寄存器CLKCONCMD的低3位 设置为000,表示不分频输出
5、把寄存器CLKCONCMD的第6位 清0,设置32M作为系统主时钟
6、如果读CLKCONSTA这个寄存器的第6位为0,表示32M的时钟源已经作为了当前的系统主时钟,程序可以往下运行了。
关于SLEEPCMD、SLEEPSTA两个寄存器
这两个寄存器用于电源管理与复位中,这里由于需要起振两个时钟源,所以需要设置下。
SLEEPCMD.2:默认为1,代表关闭不用的RC振荡器
SEELPSTA.6(SEELPSTA.XOSC_STB):【0:32MHZ晶振上电不稳定】【1:32MHZ晶振上电稳定】
实例
#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);
delay();
}
}
}
=============================================================================
#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
=============================================================================
#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;
}
}
5、串口
概述
CC2530具有两个串行通信接口:USART0 USART1。具有UART和SPI两种模式(主要用UART模式)
UART模式
异步通信
两种接口选择方式:
- 双线接口:RXD TXD
- 四线接口:RXD TXD RTS CTS
PERCFG寄存器配置串口备用位置
USARTx有两个备用位置
USART0:【P0.2-RX; P0.3-TX】【P1.4-RX; P1.5-TX】
USART1:【P0.5-RX; P0.4-TX】【P1.7-RX; P1.6-TX】
PERCFG | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
位 | - | - | - | - | - | - | U1CFG | U0CFG |
UxCFG:【0:地址一;1:地址二】
UxCSR寄存器配置串口工作状态
UxCSR | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
位 | MODE | RE | SLAVE | FE | FRR | RX_BYTE | TX_BYTE | ACTIVE |
MODE:模式选择【0-SPI模式】【1-UART模式】
RE:启动UART接收器【1-启动】
UxUCR寄存器
UxUCR | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
位 | FLUSH | FLOW | D9 | BIT9 | PARITY | SPB | STOP | START |
UxDBUF寄存器
串口数据发送与接收缓冲器
BAUD_M寄存器
波特率小数部分的值
UxGCR通用控制寄存器
UxGCR的低四位 == BAUD_E:波特率指数部分的值
【小结】由BAUD_M、BAUD_E设置波特率;例如: U0GCR =8;U0BAUD=59;
串口中断相关
串口中断使能: URXxIE=1; UTXxIE=1;
串口中断标志位:URXxIF; UTXxIF;
串口功能实现步骤
- 指定串口的IO位置
- 对IO配置成片上外设功能
- 确立传输方式
- 确定波特率
- 开中断
实例
#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 sdfs(void)
{
URX0IF=0;//串口0来数据的标志位,硬件会置1,我们软件要清0
ch=U0DBUF;//从接受寄存器里取字节存入变量ch
U0DBUF=ch;//把变量ch里的值赋给串口0发送数据寄存器
while(0==UTX0IF);
UTX0IF=0;
}