cc1020项目部分代码
每次对CC1020 的读写操作都包含7 位地址位(A6:A0)、1 位写操作位(写为高)、一字节数据,写操作前必须先让PSEL 使能有效(低有效)。在PCLK 的上升沿,先发送地址MSB 位(A6)。
/**********************************************************
**************************
函数功能:写一字节数据到CC1020
入口参数:val:要写入的数据
出口参数:无
备注 : 无
***********************************************************
**************************/
void WriteCC1020(char val)
{
char BitCounter;
for (BitCounter=8;BitCounter!=0;BitCounter--)
{
PCLK_LOW;
PDI_LOW;
if(val&0x80)
PDI_HIGH;
val<<=1;
PCLK_HIGH;
}
PCLK_LOW;
}
/**********************************************************
**************************
函数功能:写CC1020 寄存器值
入口参数:addr:寄存器地址 data:写入数据
出口参数:无
备注 : 无
***********************************************************
**************************/
void WriteToCC1020Register(char addr, char data)
{
PSEL_LOW;
WriteCC1020((addr<<1)|0x01); //写数最低位是1
WriteCC1020(data);
PSEL_HIGH;
}
SPI 读操作:
PCLK 的上升沿,先发送读寄存器的地址MSB 位,地址发送结束后发送写操作位(写操作为低),之后在PCLK 的下降沿把寄存器值所存到单片机。
/**********************************************************
**************************
函数功能:读cc1020 寄存器值
入口参数:addr:寄存器地址
出口参数:返回寄存器内容
备注 : 无
***********************************************************
**************************/
char ReadFromCC1020Register(char addr)
{
char BitCounter;
char Byte;
PSEL_LOW; // Send address bits
WriteCC1020(addr<<1); //CC1020 读操作 发送7Bit 地址 1Bit R/W 0-W,位移后最低位一定是0。
for(BitCounter=8;BitCounter!=0;BitCounter--)
{
PCLK_HIGH;
Byte<<=1;
if(PDO_IN)
Byte|=1;
PCLK_LOW;
}
PSEL_HIGH;
return Byte;
}
程序设计采用状态机切换方式,主程序处理发送缓冲区数据及把从cc1020 接收到接收缓冲区的数据通过UART 发送到PC 机显示。当没有按键触发发送数据及接收缓冲区为空的时候状态机处于IDLE_STATE 状态,模块不断检测数据包前导码,如果检测到正确的前导码及一字节同步字,状态切换到RX_STATE 接收同步字、地址、数据包长度、数据。如果有按键触发,主程序初始化发送缓冲区数据
包长度及装载发送数据,切换到TX_STATE 发送数据包数据,先发送前导码。
维护状态函数:
/**********************************************************
************
函数功能:维护状态
入口参数:无
出口参数:无
备注 :空闲状态下CC1020 为接收模式,通过中断查询前导码
***********************************************************
***********/
void ChangeState(void)
{
switch(NextState) //下一个状态
{
case RX_STATE: //下一状态为接收
if(State==TX_STATE) //当前为发送
{
/* MSP430 calls */
TI_CC_DCLK_PxIES &= DCLK; // Int on raising edge
TI_CC_DIO_PxDIR &= DIO; // Set DIO as input
SetupCC1020RX(RXANALOG, PA_POWER); //发送到接收模式切换
}
State=RX_STATE; //接收状态
BitCounter =0; //位计数器清零
ByteCounter=0; //字计数器清零
break;
case TX_STATE: //下一个状态为发送状态
if(State!=TX_STATE) //当前不是发送状态
{
TI_CC_DCLK_PxIES |= DCLK; //INT on falling edge
TI_CC_DIO_PxDIR |= DIO; // Set DIO as output
SetupCC1020TX(TXANALOG, PA_POWER); //从接收到发送切换
}
State=TX_STATE; //状态为发送
BytesToSend=TXBufferIndex; // Number of bytes to send 发送字节数 包含 Preable 和Header
TXBuffer[PreambleLength+3]=BytesToSend-HEADER_SIZE-Preamble Length; //装载数据长度
LastDataBit = FALSE; //标志清零
TXBufferIndex=0; //发送索引清零
BitCounter=0; //位计数器清零
ShiftReg=TXBuffer[TXBufferIndex++]; // 装载发送数据 装载第一个发送数据
printfch(ShiftReg);/////////////////
break;
case IDLE_STATE: //下一状态为空闲
if(State==TX_STATE)
{ // 当前状态为发送
TI_CC_DCLK_PxIES &= DCLK; // Int on raising edge
TI_CC_DIO_PxDIR &= DIO; // Set DIO as input
SetupCC1020RX(RXANALOG, PA_POWER); // 从发送到接收切换
}
State=IDLE_STATE; //当前状态为空闲
//空闲状态初始化发送缓冲区下标
TXBufferIndex=HEADER_SIZE+PreambleLength;
PreambleCount=0;
PreambleError=0;
PreambleFound=FALSE; // Preamble 头标志清零
UI1Found=FALSE; // UI1 标志清零
break;
}
}
CC1020 和单片机的通信采用中断方式,在DLCK 产生的中断函数中通过DIO 完成通信。定义了一个字节的移位寄存器共用体:
// Union for shifting bits in or out of the CC1020 union
{
char ShiftReg; //发送,接收字节
struct {
unsigned char ShiftRegLSB :1;
unsigned char :1;
unsigned char :1;
unsigned char :1;
unsigned char :1;
unsigned char :1;
unsigned char :1;
unsigned char ShiftRegMSB :1;
};
};
中断接收及发送函数:
/**********************************************************
**************************
函数功能:CC1020 收发数据中断处理
入口参数:无
出口参数:无
备注 : 空闲状态下先接收前导码
***********************************************************
**************************/
#pragma vector="PORT1"_VECTOR
__interrupt void PORT1_ISR(void)
{
// This function must execute as fast as possible.
// Therefore, as much processing as possible is left to the main program.
switch (State)
{
case TX_STATE:
// Write data to CC1020
//DIO=ShiftRegMSB;
if (ShiftRegMSB) // MCU 发送数据到 CC1020
TI_CC_DIO_PxOUT |= DIO;
else
TI_CC_DIO_PxOUT &= DIO;
ShiftReg=ShiftReg<<1;
BitCounter++;
// If last data bit has been sent
if(LastDataBit) //是否是最后一个数据
{
// Remain in TX until last data bit has been sent on
RF:
if(BitCounter > RFPACKET_EXTENSION) // 发送最后RFPACKET_EXTENSION bit 位 保持输出功率
{
BitCounter = 0;
TXBufferIndex = 0;
LastDataBit = FALSE;
NextState=IDLE_STATE;
break;
}
else
{ }
// Else (not last data bit)
}
else
{
// Load new TX data and monitor end of packet: //装载新的发送数据 并检测是不是最后一个数据
if(BitCounter==1)
{
if(TXBufferIndex>BytesToSend) //是否发完最后一个发送数据
{
BitCounter = 0;
LastDataBit = TRUE; //最后字节数据标志
ShiftReg = 0x00; //发送完数据 发送0x00 作为结束标志
}
}
//发完一个字节
if(BitCounter==8)
{
BitCounter=0;
ShiftReg=TXBuffer[TXBufferIndex++];
}
}
break;
case RX_STATE:
// Read data from CC1020
ShiftReg=ShiftReg<<1;
ShiftRegLSB= ((TI_CC_DIO_PxIN & DIO)>>1); // Low-side
LO (DIO not inverted) //移位到最后一位
BitCounter++;
// If received 8bits=1byte
if(BitCounter==8) //接收到一个字节
{
BitCounter=0;
// Process received RF data:
switch(ByteCounter)
{
// Byte-0 = SOF part 1:
case 0 :
if(ShiftReg!=UI2) //UI2 接收不正确回到空闲状态
{
NextState=IDLE_STATE;
}
break;
// Byte-1 = address:
case 1 : //接收到地址字节
// Addressing not implemented
break;
// Byte-2 = packet length/size:
case 2 : //数据包长度
BytesToReceive=ShiftReg; //为长度减1
if(BytesToReceive>TX_BUFFER_SIZE) //接收到的数据长度大于 缓冲区长度
{
BytesToReceive=0;
}
break;
// Rest of the packet is data, store it in the receive buffer default :
RXBuffer[RXBufferWriteIndex]=ShiftReg;
//存入缓冲区
//RXBufferWriteIndex=(RXBufferWriteIndex+1)%RX_BUFFER_SIZE;
RXBufferWriteIndex++;
RXBufferWriteIndex&=0x3F;
break;
}
if(ByteCounter>=BytesToReceive+2) //如果接收数据包完成
{
NextState=IDLE_STATE; //转到空闲状态
}
ByteCounter++;
}
break;
case IDLE_STATE: //
// Read data from CC1020
ShiftReg=ShiftReg<<1; //空闲状态小 从读CC1020 数据
//ShiftRegLSB=DIO; // Low-side LO (DIO not inverted)
ShiftRegLSB= ((TI_CC_DIO_PxIN & DIO)>>1); //读DIO P2.4
BitCounter++;
// If preamble found, look for Start Of Frame (SOF)
if(PreambleFound) //前导标志置1 受到有效前导
{
// If first unique identifier found,
enter RX mode
if(ShiftReg==UI1) //UI1 被找到
{
// Initialise RX processing state directly:
// Avoid latency with background scheduler.
BitCounter=0; //
ByteCounter=0;
State = RX_STATE; //收到一个则进入接收状态
NextState=RX_STATE;
// Else if we are still receiving preamble, do nothing
} //没有正确收到 UI1
else
if((ShiftReg==VALID_PREAMBLE_BYTE_1)||(ShiftReg==VALID_PREA
MBLE_BYTE_2)) //如果仍然在收到前导 什么都不做
{
// Else if we are not receiving a correct preamble, declare
an error
}else if(PreambleError==0) //否则前导错误
{
PreambleError++; //前导错误变量加1
}else
{
}
// If preamble error found, increase the error counter
regardless of bits read
if(PreambleError>0)
{ //前导错误变量加 1
PreambleError++;
}
// Once an error condition has occurred, a correct SOF must be
found
// within 9 bits (error counter is initially incremented by 2),
otherwise
// we abort and start looking for preamble again
if(PreambleError>10) //如果大于10
{
PreambleFound=FALSE; //前导错误标志 复位
}
// Else (preamble has not been found) //前导标志没有置位
}else
{ //从CC1020 读取值 首先读取前导
// If valid preamble, increase counter
if(ShiftReg==VALID_PREAMBLE_BYTE_1)||(ShiftReg==VALID_PREAM
BLE_BYTE_2)) //如果读取到有效的 Preamble
{
PreambleCount++; // 读到前导 Preamble 加1
// Else (not valid preamble), reset counter
}else
{
PreambleCount=0; //如果收到有一次错误Preamble 则 前导码计数器清零
}
// If required preamble reached, indicate preamble found
if(PreambleCount>=PREAMBLE_REQ) // 指示 Preamble 找到
{
PreambleFound=TRUE; //置位前导标志
PreambleError=0;
}
//printfch(PreambleCount);
}
break;
default:
// Enter known state in case something goes haywire
NextState=IDLE_STATE;
break;
}
//INTF=0;
TI_CC_DCLK_PxIFG &= DCLK; // Clear flag
}
无线传感器网络标准ZigBee要有麻烦了。一家与无线传感器技术相竞争的公司最近推出了基于通用网络标准IP的产品。
基于IP:可与企业网相连
PhyNet就是这家名为Arch Rock的公司新推出的产品,同ZigBee一样,它也可以将无线设备连接到采用IEEE 802.15.4无线协议的低功率网状网络上。不同的是,新的竞争者采用的是IP协议。Arch Rock公司表示,IP可以使PhyNet具有更好的扩展性,并且能够直接连接在企业自己的数据网络上。
Arch Rock总裁兼首席执行官Roland Acra说:“ZigBee不是基于IP的,因为在定义IP时,人们在传统观念上认为IP的开销太大。现在我们的产品证明,用户可以用非常紧凑的方式在低功率、低带宽设备中使用IP,结合两者最好的特性。”
Arch Rock公司同时是IETF“IP over 802.15.4”网络标准RFC 4944的贡献者。一年前,该公司推出了用于在低功率无线传感器网(WSN)上使用IP的试验项目Primer Pack。
Acra说,PhyNet可提供一种分层架构。它包括一台管理WSN集合的服务器和将每条传感器网连接在企业IP网络上的PhyNet路由器。其他网络必须有一个与每个传感器网同处一个位置的控制器。这样,用户的传感器应用可以距离相隔很远,也可以分布在企业园区,或者就在隔壁。
PhyNet系列还包括一些节点产品。节点可以连接模拟和数字的传感器,包括已有的数据记录器。Acra说:“我们的客户现在可以进入一个他们希望连接和集中管理多个装备传感器的楼宇的阶段。PhyNet将使得管理服务和应用运行在受保护的企业数据中心里面。”
如果传感器网络中的流量增加,可以添加更多的路由器,每台路由器可将吞吐量增加250K bit/s并提供可恢复性。
ZigBee反击:定位不同领域
ZigBee支持者似乎并不担心。以太网发明人Bob Metcalfe认为“ZigBee/15.4和IP/15.4都可以在嵌入式网络技术领域大有前途”。Metcalfe的投资公司是ZigBee芯片制造商Ember的股东。
Metcalfe在标准方面有着令人感兴趣的历史。Metcalfe曾经发明过以太网,曾在1995年预测以太网的终结。这一次,他没有低估IP,但他表示:“仅仅将IP包塞到15.4包中对于嵌入式网络还不够。ZigBee也解决了很多其他问题。”
Metcalfe说,ZigBee正应用在家庭自动化和计费系统中,而Arch Rock公司产品的用户似乎更多的是工业领域中的客户。Acra也表示:“我们的产品应用在干粗活的世界中——它们被安装在运送货物的列车上和电线杆上。”因此,这两种技术可能实际上定位于不同的应用领域。
Arch Rock已经开始销售配置10个节点、两台路由器和一台服务器的入门级PhyNet系统,价格为7995美元。