📄 raido.c
字号:
#include "raido.h"
#include "dma.h"
#include "wait.h"
#include "serial.h"
#include "ap.h"
__no_init RX_PACKET_STRUCT rxData1 @ "PM0_XDATA";
__no_init RX_PACKET_STRUCT rxData2 @ "PM0_XDATA";
static DMA_DESC* dmaRx; // DMA用在收,这里记录收用到那个通道并得到配置内存的的地址
static BYTE dmaNumberRx = 0; // 用来记录那个DMA通道被分配
volatile BYTE RxStatus = 0;
volatile BYTE TxStatus = 0;
BYTE *recBuffer;
extern RCEPACKET recPacket;
void SetRec(RX_PACKET_STRUCT * pReceiveData);
BOOL RaidoInit(UINT32 frequency, UINT16 localAddress,UINT16 panid)
{
BOOL status=TRUE;
SET_MAIN_CLOCK_SOURCE(CRYSTAL);
SETPAN(panid);
SETLOCALADDRESS(localAddress);
if(frequency > 2047000)
SetFrequency(frequency);
else
SetFrequency(2405000);
//打开RF电源.
RFPWR = 0x04;
while((RFPWR & 0x10)){}
// 关闭地址自动译码,自动CRC开启
MDMCTRL0H &= ~ADR_DECODE;
MDMCTRL0L |= AUTO_CRC;
// Turning on AUTO_TX2RX
FSMTC1 = ((FSMTC1 & (~AUTO_TX2RX_OFF & ~RX2RX_TIME_OFF)) | ACCEPT_ACKPKT);
// Turning off abortRxOnSrxon.
FSMTC1 &= ~0x20;
// 初始化F发送与接收的状态
TxStatus = TX_IDLE; //
RxStatus = RX_IDLE; //
// Clearing the RF interrupt flags and enable mask and enabling RF interrupts
RFIF = 0;
RFIM = 0;
INT_SETFLAG(INUM_RF,INT_CLR);
INT_ENABLE(INUM_RF,INT_ON);
// Setting the frequency and initialising the radio
// Setting the number of bytes to assert the FIFOP flag
IOCFG0 = 7;
INT_SETFLAG(INUM_RFERR, INT_CLR);
INT_ENABLE(INUM_RFERR, INT_ON);
recBuffer=&rxData1.payloadLength;//设置接收BUFFER的起始地址1
SetRec(&rxData1);//初始装配接收的地址1并打开RF接收
// Flushing both Tx and Rx FiFo. The flush-Rx is issued twice to reset the SFD.
// Calibrating the radio and turning on Rx to evaluate the CCA.
// SFD 开始帧定界符
SRXON;
SFLUSHTX;
SFLUSHRX;
SFLUSHRX;
STXCALN;
ISSTART;
//DMA部分的初始化
DmaInit();
dmaRx = DmaAllocChannel(&dmaNumberRx, &rxCallBack);
if((dmaNumberRx == 0) || (dmaNumberRx > 4))
{
status = FALSE;
}
DmaFromRadio(dmaRx, 0, TRUE);
DMA_ABORT_CHANNEL(dmaNumberRx);
INT_ENABLE(INUM_DMA, INT_ON);
////////播种
{
UINT16 rndSeed;
BYTE i;
rndSeed = 0;
for(i=0; i<16; i++)
{
/* use most random bit of analog to digital receive conversion to populate the random seed */
rndSeed = (rndSeed << 1) | (ADCTSTH & 0x01);
}
/*
* The seed value must not be zero. If it is, the psuedo random sequence will be always be zero.
* There is an extremely small chance this seed could randomly be zero (more likely some type of
* hardware problem would cause this). The following check makes sure this does not happen.
*/
if (rndSeed == 0x0000)
{
rndSeed = 0xBEEF; /* completely arbitrary "random" value */
}
/*
* Two writes to RNDL will set the random seed. A write to RNDL copies current contents
* of RNDL to RNDH before writing new the value to RNDL.
*/
RNDL = rndSeed & 0xFF;
RNDL = rndSeed >> 8;
}
return status;
}
void SetRec(RX_PACKET_STRUCT * pReceiveData)
{
DMA_ABORT_CHANNEL(dmaNumberRx);
// Setting the address to where the received data are to be written.
SET_DMA_DEST(dmaRx,pReceiveData);
SET_DMA_LENGTH(dmaRx,127);
// Arming the DMA channel. The receiver will initate the transfer when a packet is received.
DMA_ARM_CHANNEL(dmaNumberRx);
//FSMSTATE有限状态机状态
if(FSMSTATE == 6 && RXFIFOCNT > 0)
{
ISFLUSHRX;
ISFLUSHRX;
}
// Turning on the receiver
ISRXON;
return;
}
void rxCallBack(void)
{
RX_PACKET_STRUCT __xdata* rPacketPtr;
BYTE res = FALSE;
if(RXFIFOCNT > 0)
{
ISFLUSHRX;
ISFLUSHRX;
}
// Investigating the received packet.
// Checking the destination address and that the CRC is OK.
// The message is ACK'ed if it tells to.
rPacketPtr = (RX_PACKET_STRUCT __xdata*) GET_DMA_DEST(dmaRx);
if(rPacketPtr->payload[rPacketPtr->payloadLength-1]&0x80) //crc校验
{
if(recPacket.statusACnt.recPacktetCnt==0)
{
if(rPacketPtr==&rxData1)
{
recPacket.statusACnt.recPacktetCnt++;
recPacket.statusACnt.is1Rec=RECAPACKET;
SetRec(&rxData2);//装配下此接收的地址
}
else
{
recPacket.statusACnt.recPacktetCnt++;
recPacket.statusACnt.is2Rec=RECAPACKET;
SetRec(&rxData1);//装配下此接收的地址
}
}
else if(recPacket.statusACnt.recPacktetCnt==1)
{
if(rPacketPtr==&rxData1)
{
if(recPacket.statusACnt.is1Rec==RECAPACKET)//原来有包的是1,而这次要存的也是1,则接收状态不变
{
SetRec(&rxData2);//装配下此接收的地址
}
else
{
recPacket.statusACnt.recPacktetCnt++;
recPacket.statusACnt.is1Rec=RECAPACKET;
SetRec(&rxData2);//装配下此接收的地址,BUFFER总是接收最新最近,当BUFFER放不下时就把原来的冲掉
}
}
else
{
if(recPacket.statusACnt.is2Rec==RECAPACKET)//原来有包的是1,而这次要存的也是1,则接收状态不变
{
SetRec(&rxData1);//装配下此接收的地址
}
else
{
recPacket.statusACnt.recPacktetCnt++;
recPacket.statusACnt.is2Rec=RECAPACKET;
SetRec(&rxData1);//装配下此接收的地址,BUFFER总是接收最新最近,当BUFFER放不下时就把原来的冲掉
}
}
}
else if(recPacket.statusACnt.recPacktetCnt>=2)
{
recPacket.statusACnt.recPacktetCnt=2;
if(rPacketPtr==&rxData1)
{
recPacket.statusACnt.is1Rec=RECAPACKET;
SetRec(&rxData2);
}
else
{
SetRec(&rxData1);
recPacket.statusACnt.is2Rec=RECAPACKET;
}
}
res=TRUE;
}
if(res == FALSE)
{
ISFLUSHRX; //清RX FIFO
ISFLUSHRX;
// rearming DMA channel
DMA_ARM_CHANNEL(dmaNumberRx); //接收错误DMA地址不变,BUFFER状态
RFIM |= IRQ_SFD;
}
return ;
}
void SetFrequency(UINT32 frequency)
{
frequency /= 1000;
frequency -= 2048;
FSCTRLL = (BYTE) frequency;
FSCTRLH = ((FSCTRLH & ~0x03) | (BYTE)((frequency >> 8) & 0x03));
return;
}
BOOL SendPacket(TX_PACKET_STRUCT * packetPtr) //这一层只在物理上的发,没成功也不受控制。像什么CSMA等在MID层实现
{
BOOL res = TRUE;
// Clearing RF interrupt flags and enabling RF interrupts.
if(FSMSTATE == 6 && RXFIFOCNT > 0)
{
ISFLUSHRX;
ISFLUSHRX;
}
RFIF &= ~IRQ_TXDONE;
RFIM &= ~IRQ_SFD;
INT_SETFLAG(INUM_RF, INT_CLR);
// Writing the total packet length, addresses and flags to Tx FiFo.
// Transferring the payload if any.RFD RF Data
//RFD = (pPacketPointer->payloadLength + SPP_HEADER_AND_FOOTER_LENGTH); //加载包长
RFD = MAC_FRAME_LENGTH+packetPtr->payloadLength; //加载包长
RFD = packetPtr->fcf.low;
RFD = packetPtr->fcf.high;
RFD = packetPtr->dsn;
RFD = packetPtr->destpanid.low;
RFD = packetPtr->destpanid.high;
RFD = packetPtr->destAddress.lowaddress; //加载目标地址
RFD = packetPtr->destAddress.highaddress;
RFD = packetPtr->srcpanid.low;
RFD = packetPtr->srcpanid.high;
RFD = packetPtr->srcAddress.lowaddress;
RFD = packetPtr->srcAddress.highaddress;//插入源地址(TX结构体中没有)
for(BYTE i=0;i<packetPtr->payloadLength;i++)
RFD=packetPtr->payload[i];
// If the RSSI value is not valid, enable receiver
if(RSSIL == 0x80)
{
ISRXON;
// Turning on Rx and waiting 320u-sec to make the RSSI value become valid.
halWait(1);
}
CSMA_BackOff();
//Transmitting
ISTXONCCA; //执行ISTXONCCA下一条命令就可以看的出是不是在发吗??
//if(TX_ACTIVE)
if(FSMSTATE > 30)
{
// Asserting the status flag and enabling ACK reception if expected.
TxStatus = TX_IN_PROGRESS; //这里没说发成功,只是说正在发,成没成功看中断
RFIM |= IRQ_TXDONE;
}
else
{
ISFLUSHTX;
res = FALSE;
RFIM &= ~IRQ_TXDONE;
TxStatus=TX_IDLE;///////////////
}
return res;
}
void CSMA_BackOff(void)
{
BYTE nb;
UINT32 delay;
nb = 0;
do {
if (nb)
{
delay= GetRandomByte(); //rannum will be between 0 and delay-1
// delay=delay<<TICKSPD;
while (delay)
delay--;
}
//check CCA
if (CCA) break;//判断CCA状态标志,看CCA是否为1,为1说明信道可以用。这些标志是硬件置位自动并是不停的在看
nb++;
}while (nb <= macMaxCSMABackoffs);
return;
}
BYTE GetRandomByte(void)
{
ADCCON1 = (ADCCON1 & ~0x0c) | 0x04;
/* return new randomized value from hardware */
return(RNDH);
}
#pragma vector=RF_VECTOR
__interrupt void spp_rf_IRQ(void)
{
BYTE enabledAndActiveInterrupt;
GLOBAL_INT_ENABLE(INT_OFF);
enabledAndActiveInterrupt = RFIF;
RFIF = 0x00; // Clear all interrupt flags
INT_SETFLAG(INUM_RF, INT_CLR); // Clear MCU interrupt flag
enabledAndActiveInterrupt &= RFIM;
// Start of frame delimiter (SFD)
if(enabledAndActiveInterrupt & IRQ_SFD)
{
if(RxStatus == RX_WAIT)
{
RxStatus = RX_IN_PROGRESS;
RFIM &= ~IRQ_SFD;
}
}
// Transmission of a packet is finished. Enabling reception of ACK if required.
if(enabledAndActiveInterrupt & IRQ_TXDONE)
{
if(TxStatus == TX_IN_PROGRESS)
{
TxStatus = TX_SUCCESSFUL;
}
// Clearing the tx done interrupt enable
RFIM &= ~IRQ_TXDONE;
}
GLOBAL_INT_ENABLE(INT_ON);
}
#pragma vector=RFERR_VECTOR
__interrupt static void rf_error_IRQ(void)
{
GLOBAL_INT_ENABLE(INT_OFF);
// If Rx overflow occurs, the Rx FiFo is reset.
// The Rx DMA is reset and reception is started over.
if(FSMSTATE == 17)
{
STOP_RADIO();
ISFLUSHRX;
ISFLUSHRX;
DMA_ABORT_CHANNEL(dmaNumberRx);
DMA_ARM_CHANNEL(dmaNumberRx);
ISRXON;
}
else if(FSMSTATE == 56)
{
ISFLUSHTX;
}
INT_SETFLAG(INUM_RFERR,INT_CLR);
GLOBAL_INT_ENABLE(INT_ON);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -