Vous êtes sur la page 1sur 11

/* PIC Comm This Comm is for a PIC16F690 to communicate with one HC12 with SPI and talk to another

PIC/HC12 pair through an Xbee using EUSART To use this code, first set the PIC_SIDE to ROAMER or POD The header file contains all #defines Contents: -Main Loop: This Checks for SSP Comm, EUSART TX Finished, and Timer Overflow -Init_All: This function initializes the SSP, the EUSART, and all Pins Start_Timer: This function starts the timer -SSP_SM: This is the state machine for the SSP Comm -EUSART_TX_SM: -Interrupt Response: This checks for timer overflows and also contains the EUSART RX SM */ #define _LEGACY_HEADERS #include <htc.h> #include <stdio.h> #include "pic16f690.h" #include "PICCOMM.h"

//__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT & BORDIS & IESODIS & FCMDIS); __CONFIG(CP_OFF & WDTE_OFF & PWRTE_ON & FOSC_HS); /*Function Prototypes*/ void Init_All(void); void SSP_SM(unsigned char, unsigned char); unsigned char EUSART_TX_SM(unsigned char, unsigned char); void TimerUpdate(unsigned char, unsigned char); /* Static Variables */ //General Setup static unsigned char CurrentSSPState; static unsigned char CurrentRXState; static unsigned char CurrentTXState; unsigned char EventType; unsigned char EventParam; static unsigned char OutgoingMess[NumberOutgoingBytes] = {0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67}; static unsigned char IncomingMessage[NumberIncomingBytes]; static unsigned char DEBUGGINGFLAG=0; //For the Timer static unsigned char TimerOverflowFlag = 0; static unsigned char TimerOverflowCounter = 0; //For RX static unsigned static unsigned static unsigned static unsigned static unsigned static unsigned static unsigned static unsigned static unsigned

char char char char char char char char char

LSB = 0; Byte = 0; BytesLeft = 0; MaxBytes = 0; IncomingCheckSum = 0; XbeeStatus = 0; XbeeStatusFlag = 0; InactionFlag = 0; Rerun = False;

/*

MAIN LOOP */ void main () { //Initialize Settings Init_All(); //Forever Loop while (1) { //Check for SSP Comm if ((SSPSTAT & 0b00000001)) //SSP Buffer Full, Go Read it! { EventType = ES_SSP; EventParam = SSPBUF; SSP_SM(EventType,EventParam); //Call SSP SM and send it the contents of the buffer }//End if //Check for TX Finished if (CurrentTXState == TransmitWaitForXbeeStatus) { if (PIR1 & 0b00010000) //If we recieved data { EventType = ES_TX; EUSART_TX_SM(EventType,0); }//End if } //End if //Check for Timer Overflow if (TMR1IF) { TimerOverflowCounter++; if (TimerOverflowCounter++ == 225) { EventType = ES_TIMEOUT; EUSART_TX_SM(EventType,0); TimerOverflowCounter = 0; TimerUpdate(TXTimer,OFF); } } //Check if Xbee Status Arrived if (XbeeStatusFlag == 1) { Rerun = EUSART_TX_SM(ES_XbeeStatus,XbeeStatus); if (Rerun == True) { EUSART_TX_SM(EventType,0); } } //Check for OERR Flag or FERR Flag if (RCSTA & 0b00000010) //OERR Flag { RCREG; RCSTA &= ~0b0001000; //CREN = 0; RCSTA |= 0b0001000; //CREN = 1; //PORTC |= 0b00000001;//Turn on Debugging Light CurrentRXState = Waitingfor7E; } else if (RCSTA & 0b00000100) //FERR Flag { RCREG;

TXSTA &= ~0b0010000; //TXEN = 0; TXSTA |= 0b0010000; //TXEN = 1; //PORTC |= 0b00000001;//Turn on Debugging Light CurrentRXState = Waitingfor7E; } }//End forever loop }//End main function /* INITIALIZATION FUNCTION */ void Init_All(void) { //SSPSTAT Register SSPSTAT &= ~0b11000000; // Clear SMP and CKE //Clear Flags SSPCON &= ~0b11000000; //Clear WCOL and SSPOV //Enable Interrupts PIE1 |= 0b00100000; //Turn on RX Interrupt (RCIE) INTCON |= 0b11000000; //Enable Peripheral and Global Interrupts //Setup Timer OPTION_REG = 0b00000101; //Set Timer0 Prescaler T1CON = 0b00000000; // Set Timer 1 //Set Tris Bits for SCK, SDO, SDI TRISB |= 0b01110000; //Make SCK, SDI, and RX inputs TRISB &= ~0b10000000; //Make TX Output TRISC &= ~0b10010011; //Make SDO Output PORTC &= ~0b00010000; //Reset Xbee PORTC |= 0b00010000; //Reset Xbee TRISA &= ~0b10000000; //Make SDO Output ANSEL &= 0b00000000; //Clear Ansel ANSELH &= 0b00000000; //Clear Ansel //SSPCON Register SSPCON |= 0b00110100; //Set CKP, SSPM2, and SSPEN //Set EUSART Registers SPBRG = 0b10000001; //Set Baud rate to 9600 SPBRGH = 0; TXSTA = 0b00100100; //Set up TX RCSTA = 0b10010000; //Set up RX RCREG; //Clear RX Flag //Set Inital State Machine States CurrentSSPState = Idle; CurrentRXState = Waitingfor7E; CurrentTXState = WaitingforSend; return; } /* TIMER UPDATE */ void TimerUpdate(unsigned char Timer, unsigned char TimerStatus) { if (Timer == RXTimer)

{ if (TimerStatus == ON) //Turn on Timer 0 { T0IE = 1; //Enable Timer 0 Overflow Interrupts TMR0 = 0; } else //Turn off Timer 0 { T0IE = 0; //Enable Timer 0 Overflow Interrupts } } else { if (TimerStatus == ON) { T1CON |= 0b00000001; //Turn Timer 1 on } else { T1CON &~ 0b00000001; //Turn Timer 1 off } } return; }

/* SSP STATE MACHINE */ void SSP_SM(unsigned char EventType, unsigned char EventParam) { unsigned char CheckKindMessage = 0; //Checks the Kind of message being sent (0x37 = Request to Send; 0x39 = Null; 0x42 = Ask State) static int SSPCounter = 0; //Keeps Track of Number of Bytes Recieved/Send switch ( CurrentSSPState ) { case Idle : // If current state Idle switch ( EventType ) { case ES_SSP : //If event is event one { SSPSTAT; CheckKindMessage = EventParam; //Check the message in the buffer //Clear Flags SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV if (CheckKindMessage == 0x37) //If the Message is Request for Sending { SSPCounter = 0; //Reset SSP Counter CurrentSSPState = Recieving; } else if (CheckKindMessage == 0x42) //If the Message is a Request for Message { SSPCounter = 0; //Reset SSP Counter SSPBUF = OutgoingMess[SSPCounter]; //Start sending the Message CurrentSSPState = Sending; } else if (CheckKindMessage == 0x39) //If the Message is a Null { SSPCounter = 0; //Reset SSPCounter SSPBUF = 0xAA; //Send a Null Message SSPCounter++; //Increment the SSPCounter CurrentSSPState = Nulling; //Decide what the next state will be } } break;

} break; case Sending : // If current state is state one switch ( EventType ) { case ES_SSP : //If event is event one { if (SSPCounter == NumberOutgoingBytes-1) //Sending the last Byte { int i; SSPBUF; //Clear Flags SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV SSPBUF = OutgoingMess[SSPCounter];//Send the last Byte //OutgoingMess[CommandByte] = 0x67; //Reset the Message so Amanda can see new messages from old CurrentSSPState = Idle;//Go back to idle } else { SSPBUF; //Clear Flags SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV SSPBUF = OutgoingMess[SSPCounter]; SSPCounter++; //Increment the SSPCounter } } break; } break; // repeat state pattern as required for other states case Recieving : // If current state is asking to send a message switch ( EventType ) { case ES_SSP : //If event is event one { if (SSPCounter == NumberIncomingBytes-1) //Sending the End Byte { unsigned char NewEventType = ES_SENDMESSAGE; EUSART_TX_SM(NewEventType,0); IncomingMessage[SSPCounter] = EventParam;//Save the Byte //Clear Flags SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV CurrentSSPState = Idle;//Go back to idle } else { IncomingMessage[SSPCounter] = EventParam;//Save the Byte //Clear Flags SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV SSPCounter++; //Increment the SSPCounter } } break; // repeat cases as required for relevant events } // end switch on CurrentEvent break; case Nulling : // If current state is state one switch ( EventType ) { case ES_SSP : //If event is event one { if (SSPCounter == NumberOutgoingBytes-1) //Sending the last Byte { //Clear Flags SSPBUF;

SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV SSPBUF = 0xAA;//Send Null CurrentSSPState = Idle;//Go back to idle } else { //Clear Flags SSPBUF; SSPCON &= ~(0b11000000); //Clear WCOL and SSPOV SSPBUF = 0xAA; //Send Null SSPCounter++; //Increment the SSPCounter } } break; }// end switch on CurrentEvent break; } //End CurrentSSPState Switch }//End SSP SM /* EUSART TX STATE MACHINE */ unsigned char EUSART_TX_SM(unsigned char EventType, unsigned char EventParam) { //Define variables const unsigned char Preamble[5] = {0x7E,0x00,DataSize,0x01,0x01}; //Constant Start of Message static unsigned char TXCounter = 0; //Keeps track of byte number static unsigned char Checksum = 0; //Calculate checksum static unsigned char RetryCount = 0; //If TX fails, retry two times unsigned char Status = False; switch ( CurrentTXState ) { case WaitingforSend : // If Waiting to send a message if ( EventType == ES_SENDMESSAGE )// Start Sending the Message { TXCounter = 0; TXREG = Preamble[TXCounter]; TXCounter++; if (DEBUGGINGFLAG == 1) Checksum = 0; CurrentTXState = TransmitWaitForXbeeStatus; } break; case TransmitWaitForXbeeStatus : // If current state is state one switch ( EventType ) { case ES_TX : //If event is event one { if (TXCounter < 5) //If the counter is low, send the 5 Preamble bytes { TXREG = Preamble[TXCounter]; TXCounter++; } else if (TXCounter == (NumberIncomingBytes + 5)) //All Data out, send Checksum { TXREG = (0xFF - (Checksum + 2)); Checksum = 0; TXCounter++; DEBUGGINGFLAG = 1; } else if (TXCounter > (NumberIncomingBytes + 5)) //Last Data out, do nothing,

wait for response { TXCounter++; } else { TXREG = IncomingMessage[TXCounter - 5]; Checksum += IncomingMessage[TXCounter - 5]; TXCounter++; } } break; case ES_XbeeStatus : //If event is event one { if (EventParam == ACK) //If the message is Ack, go back to idle { RetryCount = 0; CurrentTXState = WaitingforSend; XbeeStatusFlag = 0; } else if ((EventParam == CCA) && (RetryCount < 2)) //Back Off { PORTC |= 0b00000010;//Turn on Debugging Light TimerUpdate(TXTimer,ON); RetryCount++; CurrentTXState = TransmitBackoff; XbeeStatusFlag = 0; } else if (RetryCount == 2) // Message Failed { PORTC |= 0b00000100;//Turn on Debugging Light CurrentTXState = WaitingforSend; RetryCount = 0; XbeeStatusFlag = 0; } else //Try Sending again { //PORTC |= 0b00000001;//Turn on Debugging Light EventType = ES_SENDMESSAGE; RetryCount++; CurrentTXState = WaitingforSend; Status = True; XbeeStatusFlag = 0; } } break; } // end switch on CurrentEvent break; case TransmitBackoff : // Waiting for Timeout to Resend if ( EventType == ES_TIMEOUT )// Start Sending the Message { EventType = ES_SENDMESSAGE; Status = True; CurrentTXState = WaitingforSend; } break; }//End switch on Current State return Status; } /* INTERRUPT

*/ void interrupt ISR(void) { static unsigned char InterruptEventType = 0; static unsigned char InterruptEventParam = 0; if (T0IF) //If the interrupt is a timer overflow { T0IF = 0; //Clear the Flag InterruptEventType =ES_TIMEOUT; //Set Event as a Timeout InterruptEventParam = 0; } else if ((PIR1 & 0b00100000)==0b00100000) //If the interrupt is a RX recieved, go into the RX state machine { InterruptEventType = ES_RX; InterruptEventParam = RCREG; InactionFlag = 0; if (DEBUGGINGFLAG == 1) { InactionFlag = 1; InactionFlag = 0; } } else { InterruptEventType = ES_NULL; //The interrupt only pertains to the TX timer InterruptEventParam = ES_NULL; } if (InterruptEventType == ES_RX || InterruptEventType == ES_TIMEOUT) { switch ( CurrentRXState ) { case Waitingfor7E : // If current state is state one switch ( InterruptEventType ) { case ES_RX : //If Recieved a Byte { Byte = InterruptEventParam; if (Byte == (0x7E)) { TimerUpdate(RXTimer,ON); InactionFlag = 1; CurrentRXState = WaitingforMSB; PORTC ^= 0b00000001;//Turn on Debugging Light } } break; } // end switch on CurrentEvent break; case WaitingforMSB : // If current state is state one switch ( InterruptEventType ) { case ES_TIMEOUT : //If event is event one { CurrentRXState = Waitingfor7E;//Go back to idle TimerUpdate(RXTimer,OFF); } break; case ES_RX : //If Recieved a Byte { Byte = EventParam;

TimerUpdate(RXTimer,ON); InactionFlag = 1; CurrentRXState = WaitingforLSB; } break; } break;

// end switch on CurrentEvent

case WaitingforLSB : // If current state is state one switch ( InterruptEventType ) { case ES_TIMEOUT : //If event is event one { CurrentRXState = Waitingfor7E;//Go back to idle TimerUpdate(RXTimer,OFF); } break; case ES_RX : //If Recieved a Byte { LSB = InterruptEventParam; //Take in the number of data in the message TimerUpdate(RXTimer,ON); InactionFlag = 1; CurrentRXState = WaitingforAPI; } break; } break;

// end switch on CurrentEvent

case WaitingforAPI : // If current state is state one switch ( InterruptEventType ) { case ES_TIMEOUT : //If event is event one { CurrentRXState = Waitingfor7E;//Go back to idle TimerUpdate(RXTimer,OFF); } break; case ES_RX : //If Recieved a Byte { Byte = InterruptEventParam; if (Byte == 0x89) { TimerUpdate(RXTimer,ON); InactionFlag = 1; CurrentRXState = WaitingforXbeeFrame; } else if (Byte == 0x8A) { CurrentRXState = Waitingfor7E; } else if (LSB == 0x0A) { BytesLeft = 9; MaxBytes = 9; TimerUpdate(RXTimer,ON); InactionFlag = 1; CurrentRXState = RecievingData; } else { BytesLeft = 10; MaxBytes = 10; TimerUpdate(RXTimer,ON); InactionFlag = 1;

CurrentRXState = RecievingData; } } break; } break;

// end switch on CurrentEvent

case WaitingforXbeeFrame : // If current state is state one switch ( InterruptEventType ) { case ES_TIMEOUT : //If event is event one { CurrentRXState = Waitingfor7E;//Go back to idle TimerUpdate(RXTimer,OFF); } break; case ES_RX : //If Recieved a Byte { Byte = InterruptEventParam; TimerUpdate(RXTimer,ON); InactionFlag = 1; CurrentRXState = WaitingforXbeeStatus; } break; } // end switch on CurrentEvent break; case WaitingforXbeeStatus : // If current state is state one switch ( InterruptEventType ) { case ES_TIMEOUT : //If event is event one { CurrentRXState = Waitingfor7E;//Go back to idle TimerUpdate(RXTimer,OFF); } break; case ES_RX : //If Recieved a Byte { XbeeStatusFlag = 1; XbeeStatus = InterruptEventParam; CurrentRXState = Waitingfor7E; } break; } // end switch on CurrentEvent break; case RecievingData : // If Recieving Data switch ( InterruptEventType ) { case ES_TIMEOUT : //If Timeout, go back to begining { CurrentRXState = Waitingfor7E;//Decide what the next state will be TimerUpdate(RXTimer,OFF); } break; case ES_RX : //If Recieved a Byte { Byte = InterruptEventParam; //Read in the data if (BytesLeft == 0) { if ((0xFF - IncomingCheckSum) != Byte) //Check if IncomingCheckSum is correct { }

IncomingCheckSum = 0; CurrentRXState = Waitingfor7E; //Return to idle } else { OutgoingMess[MaxBytes - BytesLeft] = Byte; //Save the Data in the Outgoing Message IncomingCheckSum += Byte; BytesLeft--; } } break; } break; } //End Switch on CurrentRXState }//End of RX State Machine } // End of Interrupt

// end switch on CurrentEvent

Vous aimerez peut-être aussi