📄 demozrfdapp.c
字号:
if ( APLIsRejoinComplete() )
{
// If there was no error, continue with normal logic.
// Or else handle as per application requirements.
if ( GetLastZError() == ZCODE_NO_ERROR )
{
ConsolePutROMString(rejoinSuccessMsg);
LEDBindingTask();
smApp = SM_APP_NORMAL_RUN;
}
// else there was an error and needs to be addressed.
else
{
ConsolePutROMString(rejoinFailedMsg);
// This action would depend on application.
// For time-being, we will simply keep trying to rejoin.
smApp = SM_APP_NORMAL_START;
}
}
break;
case SM_APP_NORMAL_RUN:
LED_ReceiveTask();
LED_SendTask();
// In this demo, we will wakeup if someone pushed a button
/*if ( appFlags.bits.S2Toggled )
{
appFlags.bits.S2Toggled = FALSE;
smApp = SM_APP_RUN_S2_TASK;
}
// or watchdog timer expired and we need to update D1.
else
smApp = SM_APP_RUN_D1_TASK;*/
break;
case SM_APP_RUN_S2_TASK:
// Once switch is toggled, we run the task until it is complete
// and go back to sleep.
if ( S2Task() )
{
// Once we update the S2 value, check for binding action
smApp = SM_APP_SLEEP;
GIEL = 0;
}
break;
case SM_APP_RUN_D1_TASK:
// After watchdog has expired, run the lamp task until it is complete.
if ( D1Task() )
smApp = SM_APP_SLEEP;
break;
case SM_APP_SLEEP:
if ( appFlags.bits.S2Toggled )
smApp = SM_APP_NORMAL_RUN;
// Before going to sleep, make sure that all outgoing transmissions are
// complete
else if ( APLIsIdle() )
{
DEBUG_OUT("Going to sleep...\r\n");
// Since some of the logic might have transmitted something on USART
// make sure that it is completely transmitted before we put core to sleep
// or else the outgoing UART data will be corrupted.
while ( !ConsoleIsPutReady() );
// Disable the stack.
APLDisable();
// The TMR0 will stop counting while sleeping, so
// turn off D2 to make sure power isn't wasted.
D2 = 0;
// Make sure that we wakeup from key press.
RBIE = 1;
SLEEP();
NOP();
DEBUG_OUT("Just woke-up from sleep...\r\n");
GIEL = 1;
// Reenable the stack.
APLEnable();
smApp = SM_APP_NORMAL_RUN;
}
break;
}
}
}
static BOOL IsMACAddrAssigned(void)
{
// Read MAC long address from app-specific nonvolatile memory.
NVMRead(&macInfo.longAddr,
(ROM void*)&macLongAddr,
sizeof(macInfo.longAddr));
// An address is said to be invlaid if its OUI matches with our preset OUI
if ( macInfo.longAddr.v[7] != MAC_LONG_ADDR_BYTE7 ||
macInfo.longAddr.v[6] != MAC_LONG_ADDR_BYTE6 ||
macInfo.longAddr.v[5] != MAC_LONG_ADDR_BYTE5 )
return FALSE;
else
return TRUE;
}
// Callback to application to notify of a frame transmission.
void AppMACFrameTransmitted(void)
{
// Turn on LED to indicate activity. TMR0IF interrupt will turn it off.
// See interrupt handler.
if ( !appFlags.bits.bInConfigMode )
D2 = 1;
}
// Callback to application to notify of a frame reception
void AppMACFrameReceived(void)
{
// Turn on LED to indicate activity. TMR0IF interrupt will turn it off.
// See interrupt handler.
if ( !appFlags.bits.bInConfigMode )
D2 = 1;
}
// Callback to application to notify of an ack timeout
void AppMACFrameTimeOutOccurred(void)
{
}
// Callback to an end device.
// Called when a suitable coordinator is found as part of associate process.
// Return TRUE if okay to associate.
// May use PANDesc.for more information about this coordinator.
// See MAC.h for definition of PANDesc.
BOOL AppOkayToAssociate(void)
{
return TRUE;
}
BOOL AppOkayToUseChannel(BYTE channel)
{
// This demo uses all available channels
// You may check given channel against your allowable channels and return TRUE
// or FALSE as needed.
// For 2.4GHz, channel = 11 through 26.
DEBUG_OUT("Now operating in next channel.\r\n");
return TRUE;
}
static void InitializeBoard(void)
{
// This is a RS232 console - you may replace it with any console you like.
ConsoleInit();
// Switches S2 and S3 are on RB5 and RB4 respectively. We want interrupt-on-change
INTCON = 0x00;
// There is no external pull-up resistors on S2 and S3. We will use internal pull-ups.
// The CC2420 provides SFD (Start of Frame Detect) signal on RB2. We are using
// the falling edge of that signal to generate INT2
// Enable PORTB internal pullups, INT2 on falling edge
INTCON2 = 0x00;
// Enable INT2 interrupt - SFD from CC2420
INTCON3 = 0xD0;
// CC2420 I/O assignments with respect to PIC:
// RB0 <- FIFO (Input)
// RB1 <- CCA (Input - Not used in this version of stack)
// RB2 <- SFD (Input - Generates interrupt on falling edge)
// RB3 <- FIFOP (Input - Used to detect overflow)
// RC0 -> CSn (Output - to select CC2420 SPI slave)
// RC1 -> VREG_EN (Output - to enable CC2420 voltage regulator)
// RC2 -> RESETn (Output - to reset CC2420)
// RC3 - > SCK (Output - SPI Clock to CC2420)
// RC4 <- SO (Input - SPI data from CC2420)
// RC5 -> SI (Output - SPI data to CC2420)
// Make PORTB as input - this is the RESET default
TRISB = 0xff;
// Set PORTC control signal direction and initial states
// Start with CC2420 disabled and not selected
LATC = 0xfd;
// Set the SPI module for use by Stack
TRISC = 0xD0;
// Set the SPI module
SSPSTAT = 0xC0;
SSPCON1 = 0x20;
// D1 and D2 are on RA0 and RA1 respectively, and CS of TC77 is on RA2.
// Make PORTA as digital I/O.
// The TC77 temp sensor CS is on RA2.
ADCON1 = 0x0F;
// Deselect TC77 (RA2)
LATA = 0x04;
// Make RA0, RA1, RA2 and RA4 as outputs.
TRISA = 0xE0;
// Enable global interrupts.
GIEL = 1;
GIEH = 1;
}
// NOTE: Several PICs, including the PIC18F4620 revision A3 have a RETFIE FAST/MOVFF bug
// The interruptlow keyword is used to work around the bug when using C18
// To work around the bug on PICC-18, configure the compiler to Compile for ICD
#if defined(MCHP_C18)
#pragma interruptlow HighISR
void HighISR(void)
#elif defined(HITECH_C18)
void interrupt HighISR(void)
#else
void HighISR(void)
#endif
{
// This is a quick way to display MAC TX/RX status on RD1 LED.
// TMR0IF is also used by TickUpdate, so we will let it clear the flag.
if ( !appFlags.bits.bInConfigMode )
{
if ( TMR0IF )
D2 = 0;
}
// Must call this so that MAC module can determine if a transmission is progress or not.
MACISR();
// Must call this so that tick manager can update its tick count.
TickUpdate();
// Is this a interrupt-on-change interrupt?
if ( RBIF == 1 )
{
// Clear mismatch condition and flag
if ( S2 == 0 )
appFlags.bits.S2Toggled = TRUE;
// Disable further RBIF until we process it
RBIE = 0;
// Clear mis-match condition
LATB = PORTB;
RBIF = 0;
}
}
#if defined(MCHP_C18)
#pragma code highVector=0x08
void HighVector (void)
{
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
#endif
#if defined(MCHP_C18)
#pragma code lowhVector=0x18
void LowVector (void)
{
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
#endif
/*
* ConfigTask is a blocking task that is executed when micro is reset with S3 pushed down.
* To indicate that config mode is entered, RD0 LED is turned ON.
*
* Once in config mode, you would see config menu on RS232 terminal. Use 19200, 8-N-1.
* When micro is first programmed, you must set its node id. Without valid node id,
* board will automatically enter into config mode. Once a node id is set, board will
* only enter into config mode if S3 was pushed down on startup.
*
*/
static void ConfigTask(void)
{
MENU_CMD c;
ConsolePutROMString(menu);
// While in config mode, disable PORTB interrupt-on-change.
RBIE = 0;
// Turn D1 & D2 ON to indicate that we are in config mode.
D1 = 1;
D2 = 1;
// Wait for S3 to get released
while( S3 == 0 );
while( 1 )
{
// Check to see if there was any key press in terminal.
if ( ConsoleIsGetReady() )
{
// Get the key value.
c = ConsoleGet();
// If this is a valid command, execute it.
if ( ExecuteMenuChoice(c) )
// After completion of every menu command or invalid command
// redisplay the menu message.
ConsolePutROMString(menu);
else // Quit command is executed
{
// Display message and quit
ConsolePutROMString(exitMsg);
break;
}
}
// If S2 alone is pressed in config mode, do join.
else if ( S2 == 0 && S3 == 1 )
ExecuteMenuChoice(MENU_CMD_JOIN);
else if ( S2 == 0 && S3 == 0 )
BindingTask();
}
// Turn OFF D1 & D2 to indicate that we are leaving config mode.
D1 = 0;
D2 = 0;
}
static void LEDBindingTask(void)
{
enum { LED_S_BINDING_IDLE, LED_S_BINDING_WAIT, LED_D_BINDING_IDLE, LED_D_BINDING_WAIT } ledBinding;
ledBinding = LED_S_BINDING_IDLE;
while(1)
{
APLTask();
switch(ledBinding)
{
case LED_S_BINDING_IDLE:
// Show that we are about to bind LED EP.
ConsolePutROMString(LEDSrcBindingMsg);
StartLEDCustomBind(CUSTOM_BIND_SOURCE, EP_LED_S);
// Now wait for respone from coordinator
ledBinding = LED_S_BINDING_WAIT;
// Enable Watchdog to catch lock-ups.
ENABLE_WDT();
break;
case LED_S_BINDING_WAIT:
CLRWDT();
if ( IsLEDBindComplete() )
{
ConsolePutROMString(ledSrcBindCompleteMsg);
// Disable watchdog before returning.
DISABLE_WDT();
ledBinding = LED_D_BINDING_IDLE;
//return;
}
break;
case LED_D_BINDING_IDLE:
// Show that we are about to bind LED EP.
ConsolePutROMString(LEDDecBindingMsg);
StartLEDCustomBind(CUSTOM_BIND_DEST, EP_LED_D);
// Now wait for respone from coordinator
ledBinding = LED_D_BINDING_WAIT;
// Enable Watchdog to catch lock-ups.
ENABLE_WDT();
break;
case LED_D_BINDING_WAIT:
CLRWDT();
if ( IsLEDBindComplete() )
{
ConsolePutROMString(ledSrcBindCompleteMsg);
// Disable watchdog before returning.
DISABLE_WDT();
return;
}
break;
}
}
}
static void BindingTask(void)
{
enum { SM_BINDING_IDLE, SM_BINDING_WAIT } smBinding;
smBinding = SM_BINDING_IDLE;
while(1)
{
// Keep the stack going...
APLTask();
switch(smBinding)
{
case SM_BINDING_IDLE:
// Binding action starts when both S2 and S3 are pressed.
{
// Indicate that we are entering into binding task.
D1 = 1;
D2 = 1;
// Wait until one of the swithes is released.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -