📄 basic_rf.c
字号:
/*******************************************************************************************************
* *
* ********** *
* ************ *
* *** *** *
* *** +++ *** *
* *** + + *** *
* *** + CHIPCON CC2420 BASIC RF LIBRARY *
* *** + + *** Initialization, Packet transmission, Packet reception, *
* *** +++ *** *
* *** *** *
* ************ *
* ********** *
* *
*******************************************************************************************************/
#include "..\include\rfcom.h"
#include "..\..\..\Os\include\FreeRTOS.h"
//-------------------------------------------------------------------------------------------------------
// The RF settings structure is declared here, since we'll always need halRfInit()
volatile BASIC_RF_SETTINGS rfSettings;
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// void basicRfInit(BASIC_RF_RX_INFO *pRRI, UINT8 channel, WORD panId, WORD myAddr)
//
// DESCRIPTION:
// Initializes CC2420 for radio communication via the basic RF library functions. Turns on the
// voltage regulator, resets the CC2420, turns on the crystal oscillator, writes all necessary
// registers and protocol addresses (for automatic address recognition). Note that the crystal
// oscillator will remain on (forever).
//
// ARGUMENTS:
// BASIC_RF_RX_INFO *pRRI
// A pointer the BASIC_RF_RX_INFO data structure to be used during the first packet reception.
// The structure can be switched upon packet reception.
// UINT8 channel
// The RF channel to be used (11 = 2405 MHz to 26 = 2480 MHz)
// WORD panId
// The personal area network identification number
// WORD myAddr
// The 16-bit short address which is used by this node. Must together with the PAN ID form a
// unique 32-bit identifier to avoid addressing conflicts. Normally, in a 802.15.4 network, the
// short address will be given to associated nodes by the PAN coordinator.
//-------------------------------------------------------------------------------------------------------
void basicRfInit (BASIC_RF_RX_INFO *pRRI, UINT8 channel, WORD panId, WORD myAddr)
{
UINT8 n;
// Make sure that the voltage regulator is on, and that the reset pin is inactive
SET_VREG_ACTIVE();
halWait(1000);
SET_RESET_ACTIVE();
halWait(1000);
SET_RESET_INACTIVE();
halWait(500);
// Initialize the FIFOP external interrupt
FIFOP_INT_INIT();
ENABLE_FIFOP_INT();
// Turn off all interrupts while we're accessing the CC2420 registers
portDISABLE_INTERRUPTS();
// Register modifications
FASTSPI_STROBE(CC2420_SXOSCON);
FASTSPI_SETREG(CC2420_MDMCTRL0, 0x0AF2); // Turn on automatic packet acknowledgment
FASTSPI_SETREG(CC2420_MDMCTRL1, 0x0500); // Set the correlation threshold = 20
FASTSPI_SETREG(CC2420_TXCTRL, 0xA0FF); // Set output power to 0dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0FB); // Set output power to -1dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0F7); // Set output power to -3dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0F3); // Set output power to -5dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0EF); // Set output power to -7dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0EB); // Set output power to -10dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0E7); // Set output power to -15dBm
// FASTSPI_SETREG(CC2420_TXCTRL, 0xA0E3); // Set output power to -25dBm
FASTSPI_SETREG(CC2420_IOCFG0, 0x007F); // Set the FIFOP threshold to maximum
FASTSPI_SETREG(CC2420_SECCTRL0, 0x01C4); // Turn off "Security enable"
// Set the RF channel
halRfSetChannel(channel);
// Turn interrupts back on
portENABLE_INTERRUPTS();
// Set the protocol configuration
rfSettings.pRxInfo = pRRI;
rfSettings.panId = panId;
rfSettings.myAddr = myAddr;
rfSettings.txSeqNumber = 0;
rfSettings.receiveOn = FALSE;
// Wait for the crystal oscillator to become stable
halRfWaitForCrystalOscillator();
// Write the short address and the PAN ID to the CC2420 RAM (requires that the XOSC is on and stable)
portDISABLE_INTERRUPTS();
FASTSPI_WRITE_RAM_LE(&myAddr, CC2420RAM_SHORTADDR, 2, n);
FASTSPI_WRITE_RAM_LE(&panId, CC2420RAM_PANID, 2, n);
portENABLE_INTERRUPTS();
} // basicRfInit
//-------------------------------------------------------------------------------------------------------
// BYTE basicRfSendPacket(BASIC_RF_TX_INFO *pRTI)
//
// DESCRIPTION:
// Transmits a packet using the IEEE 802.15.4 MAC data packet format with short addresses. CCA is
// measured only once before backet transmission (not compliant with 802.15.4 CSMA-CA).
// The function returns:
// - When pRTI->ackRequest is FALSE: After the transmission has begun (SFD gone high)
// - When pRTI->ackRequest is TRUE: After the acknowledgment has been received/declared missing.
// The acknowledgment is received through the FIFOP interrupt.
//
// ARGUMENTS:
// BASIC_RF_TX_INFO *pRTI
// The transmission structure, which contains all relevant info about the packet.
//
// RETURN VALUE:
// BOOL
// Successful transmission (acknowledgment received)
//-------------------------------------------------------------------------------------------------------
BOOL basicRfSendPacket (BASIC_RF_TX_INFO *pRTI)
{
WORD frameControlField;
UINT8 packetLength;
BOOL success;
BYTE spiStatusByte;
// Wait until the transceiver is idle
while (FIFOP_IS_1 || SFD_IS_1);
// Turn off global interrupts to avoid interference on the SPI interface
portDISABLE_INTERRUPTS();
// Flush the TX FIFO just in case...
FASTSPI_STROBE(CC2420_SFLUSHTX);
// Turn on RX if necessary
if (!rfSettings.receiveOn) FASTSPI_STROBE(CC2420_SRXON);
// Wait for the RSSI value to become valid
do
{
FASTSPI_UPD_STATUS(spiStatusByte);
}
while (!(spiStatusByte & BM(CC2420_RSSI_VALID)));
/*
// TX begins after the CCA check has passed
do {
FASTSPI_STROBE(CC2420_STXONCCA);
FASTSPI_UPD_STATUS(spiStatusByte);
halWait(1);
} while (!(spiStatusByte & BM(CC2420_TX_ACTIVE)));
*/
// Write the packet to the TX FIFO (the FCS is appended automatically when AUTOCRC is enabled)
packetLength = pRTI->length + BASIC_RF_PACKET_OVERHEAD_SIZE;
frameControlField = pRTI->ackRequest ? BASIC_RF_FCF_ACK : BASIC_RF_FCF_NOACK;
FASTSPI_WRITE_FIFO((BYTE*)&packetLength, 1); // Packet length
FASTSPI_WRITE_FIFO((BYTE*)&frameControlField, 2); // Frame control field
FASTSPI_WRITE_FIFO((BYTE*)&rfSettings.txSeqNumber, 1); // Sequence number
FASTSPI_WRITE_FIFO((BYTE*)&rfSettings.panId, 2); // Dest. PAN ID
FASTSPI_WRITE_FIFO((BYTE*)&pRTI->destAddr, 2); // Dest. address
FASTSPI_WRITE_FIFO((BYTE*)&rfSettings.myAddr, 2); // Source address
FASTSPI_WRITE_FIFO((BYTE*)pRTI->pPayload, pRTI->length); // Payload
// Wait for the transmission to begin before exiting (makes sure that this function cannot be called
// a second time, and thereby cancelling the first transmission (observe the FIFOP + SFD test above).
FASTSPI_STROBE(CC2420_STXONCCA);
while (!SFD_IS_1);
// Turn interrupts back on
portENABLE_INTERRUPTS();
// Wait for the acknowledge to be received, if any
if (pRTI->ackRequest)
{
rfSettings.ackReceived = FALSE;
// Wait for the SFD to go low again
while (SFD_IS_1);
// We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished
// The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small margin
halWait((12 * BASIC_RF_SYMBOL_DURATION) + (BASIC_RF_ACK_DURATION) + (2 * BASIC_RF_SYMBOL_DURATION) + 100);
// If an acknowledgment has been received (by the FIFOP interrupt), the ackReceived flag should be set
success = rfSettings.ackReceived;
} else {
success= TRUE;
}
// Turn off the receiver if it should not continue to be enabled
portDISABLE_INTERRUPTS();
if (!rfSettings.receiveOn) FASTSPI_STROBE(CC2420_SRFOFF);
portENABLE_INTERRUPTS();
// Increment the sequence number, and return the result
rfSettings.txSeqNumber++;
return success;
} // halRfSendPacket
//-------------------------------------------------------------------------------------------------------
// void halRfReceiveOn(void)
//
// DESCRIPTION:
// Enables the CC2420 receiver and the FIFOP interrupt. When a packet is received through this
// interrupt, it will call halRfReceivePacket(...), which must be defined by the application
//-------------------------------------------------------------------------------------------------------
void basicRfReceiveOn (void)
{
rfSettings.receiveOn = TRUE;
FASTSPI_STROBE(CC2420_SRXON);
FASTSPI_STROBE(CC2420_SFLUSHRX);
FIFOP_INT_INIT();
ENABLE_FIFOP_INT();
} // basicRfReceiveOn
//-------------------------------------------------------------------------------------------------------
// void halRfReceiveOff(void)
//
// DESCRIPTION:
// Disables the CC2420 receiver and the FIFOP interrupt.
//-------------------------------------------------------------------------------------------------------
void basicRfReceiveOff (void)
{
rfSettings.receiveOn = FALSE;
FASTSPI_STROBE(CC2420_SRFOFF);
DISABLE_FIFOP_INT();
} // basicRfReceiveOff
//-------------------------------------------------------------------------------------------------------
// SIGNAL(SIG_INTERRUPT0) - CC2420 FIFOP interrupt service routine
//
// DESCRIPTION:
// When a packet has been completely received, this ISR will extract the data from the RX FIFO, put
// it into the active BASIC_RF_RX_INFO structure, and call basicRfReceivePacket() (defined by the
// application). FIFO overflow and illegally formatted packets is handled by this routine.
//
// Note: Packets are acknowledged automatically by CC2420 through the auto-acknowledgment feature.
//-------------------------------------------------------------------------------------------------------
#pragma vector=PORT2_VECTOR
__interrupt void fifo_rx (void)
{
WORD frameControlField;
INT8 length;
BYTE pFooter[2];
CLEAR_FIFOP_INT();
// Clean up and exit in case of FIFO overflow, which is indicated by FIFOP = 1 and FIFO = 0
if((FIFOP_IS_1) && (!(FIFO_IS_1)))
{
FASTSPI_STROBE(CC2420_SFLUSHRX);
FASTSPI_STROBE(CC2420_SFLUSHRX);
return;
}
// Payload length
FASTSPI_READ_FIFO_BYTE(length);
length &= BASIC_RF_LENGTH_MASK; // Ignore MSB
// Ignore the packet if the length is too short
if (length < BASIC_RF_ACK_PACKET_SIZE)
{
FASTSPI_READ_FIFO_GARBAGE(length);
// Otherwise, if the length is valid, then proceed with the rest of the packet
} else {
// Register the payload length
rfSettings.pRxInfo->length = length - BASIC_RF_PACKET_OVERHEAD_SIZE;
// Read the frame control field and the data sequence number
FASTSPI_READ_FIFO_NO_WAIT((BYTE*) &frameControlField, 2);
rfSettings.pRxInfo->ackRequest = !!(frameControlField & BASIC_RF_FCF_ACK_BM);
FASTSPI_READ_FIFO_BYTE(rfSettings.pRxInfo->seqNumber);
// Is this an acknowledgment packet?
if ((length == BASIC_RF_ACK_PACKET_SIZE) && (frameControlField == BASIC_RF_ACK_FCF) && (rfSettings.pRxInfo->seqNumber == rfSettings.txSeqNumber))
{
// Read the footer and check for CRC OK
FASTSPI_READ_FIFO_NO_WAIT((BYTE*) pFooter, 2);
// Indicate the successful ack reception (this flag is polled by the transmission routine)
if (pFooter[1] & BASIC_RF_CRC_OK_BM) rfSettings.ackReceived = TRUE;
// Too small to be a valid packet?
} else if (length < BASIC_RF_PACKET_OVERHEAD_SIZE) {
FASTSPI_READ_FIFO_GARBAGE(length - 3);
return;
// Receive the rest of the packet
} else {
// Skip the destination PAN and address (that's taken care of by harware address recognition!)
FASTSPI_READ_FIFO_GARBAGE(4);
// Read the source address
FASTSPI_READ_FIFO_NO_WAIT((BYTE*) &rfSettings.pRxInfo->srcAddr, 2);
// Read the packet payload
FASTSPI_READ_FIFO_NO_WAIT(rfSettings.pRxInfo->pPayload, rfSettings.pRxInfo->length);
// Read the footer to get the RSSI value
FASTSPI_READ_FIFO_NO_WAIT((BYTE*) pFooter, 2);
rfSettings.pRxInfo->rssi = pFooter[0];
// Notify the application about the received _data_ packet if the CRC is OK
if (((frameControlField & (BASIC_RF_FCF_BM)) == BASIC_RF_FCF_NOACK) && (pFooter[1] & BASIC_RF_CRC_OK_BM)) {
rfSettings.pRxInfo = basicRfReceivePacket(rfSettings.pRxInfo);
}
}
}
} // fifo_rx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -