|
SPI 读写函数:
每次对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
}
|
|