// USARTdemo.c // // Demo code that uses interrrupt driven I/O for // USART Rx and TX, and blinks a LED as well ;-) // (C) P.J.Onion 2005 // BAUD RATE - Settings in usart_open are for 9600 baud with // a 12.288Mhz crystal. /* Connect a terminal set to 9600 baud/8bit/no parity/ Start program. It will say "HELLO" Type @ab You should see the following..... HELLO Rxed 0x40 Rxed 0x61 Rxed 0x62 Packet Recieved: 40 61 62 0 48 10 2 0 c0 11 60 a4 4 84 40 40 0 18 @ab @ = Destination Address = 4 (Ignored) Length = 1 a = Source Address = 6 (Ignored) Prorocol = 1 (Ignored) b = 1 byte of data @ab = Recieved packet is echoed back... Try typing oabcdefghijklmnopq o = Destination Address = 6 (Ignored) Length = 16 a = Source Address = 6 (Ignored) Prorocol = 1 (Ignored) b..q = 16 bytes of data NOTE: It is dangerous to mix non-interrupt output from printf and interrupt output used to echo the packet back. But this is only a simple demo. In a real situation there would only be interrupt driven i/o in use for the network protocol on the USART. */ // ------------------------------------------------ // configuration // change these if you're wiring the LED to a pin other than RA1 #ifndef LED_TRIS #define LED_TRIS TRISCbits.TRISC0 #endif #ifndef LED_PIN #define LED_PIN PORTCbits.RC0 #endif // ------------------------------------------------ // this #include pulls in the correct processor-specific registers // definition file #include "pic18fregs.h" #include "stdio.h" #include "stdlib.h" #include "usart.h" #include "signal.h" #pragma stack 0x200 128 code char at __CONFIG1H conf1 = 0x22; code char at __CONFIG4L conf2 = 0x81; code char at __CONFIG2H conf3 = 0x0E; union PACKET { unsigned char raw[18]; struct { unsigned Len:4; unsigned Dst:4; unsigned Pro:4; unsigned Src:4; unsigned char bytes[16]; }; }; union PACKET pak1,pak2; #define NOPACKET 0 #define RXPACKET 1 unsigned char packetState = 0; /* Protocol FSM */ extern union USART USART_Status; unsigned char RxBuffer[16]; /* Circular Rx buffer */ unsigned char RxW,RxR; /* Write and Read index */ unsigned char TxLen,TxNext; /* TxBuffer length and Read index */ /* Set up the interrupt handlers */ DEF_INTHIGH(high_int) DEF_HANDLER(SIG_RC, _RC_handler) DEF_HANDLER(SIG_TX, _TX_handler); END_DEF SIGHANDLER(_TX_handler) { static unsigned char byte; byte = pak1.raw[TxNext]; /* Get byte from buffer */ TXREG = byte; /* Send it ! */ TxNext += 1; if(TxNext == TxLen) /* disable interrupts at the end of the buffer */ { PIE1bits.TXIE = 0; TxNext = TxLen = 0; } } SIGHANDLER(_RC_handler) { unsigned char ch; /* action to be taken when character arrives */ if(RCSTAbits.FERR) USART_Status.FRAME_ERROR = 1; if(RCSTAbits.OERR) USART_Status.OVERRUN_ERROR = 1; ch = RCREG; /* Get the character */ RxBuffer[RxW] = ch; /* Save it in the circular buffer */ RxW += 1; /* Note no check for buffer overflow ! */ RxW &= 0xF; } void startTx(void) { TxLen = pak1.Len + 3; TxNext = 0; PIE1bits.TXIE = 1; /* Enabling the interrupt will cause an interrupt */ } /* Embronic packet protocol handler */ unsigned char processByte(unsigned char byte) { static unsigned char Len,Cnt; unsigned char ret; ret = NOPACKET; switch(packetState) { case 0: pak1.raw[0] = byte; Len = pak1.Len + 3; /* Get packet length */ Cnt = 2; /* Should check if packet is for us here */ packetState = 1; break; case 1: pak1.raw[1] = byte; /* Should check src and protocol here */ packetState = 2; break; case 2: /* Save rest of packet 1..16 bytes pf paypload */ pak1.raw[Cnt] = byte; Cnt += 1; if(Cnt == Len) { ret = RXPACKET; packetState = 0; } break; } return(ret); } void delay_ms(long ms) { long i; while (ms--) for (i=0; i < 330; i++) ; } // -------------------------------------------------- // and our main entry point void main() { unsigned char n,ch; // set pin to output LED_TRIS = 0; TRISC = 0x80; /* Set USART RX data pin as input */ LED_PIN = 1; /* Turn on the led */ WDTCON = 0; RxR = RxW = 0; /* Initialise Rx circular buffer pointers */ usart_open( /* Use USART library to i nitialise the hardware */ USART_TX_INT_OFF & USART_RX_INT_ON & USART_BRGH_HIGH & USART_ASYNCH_MODE & USART_EIGHT_BIT, 79 ); stdout = STREAM_USART; printf("HELLO\r\n"); /* Note this does NOT use interupt I/O */ IPR1bits.RCIP = 1; /* Set both USART interrrupts to be */ IPR1bits.TXIP = 1; /* High priority */ INTCONbits.GIE = 1; /* Enable interrupts */ INTCONbits.PEIE = 1; // sit in an endless loop blinking the led for (;;) { LED_PIN = 0; delay_ms(252); LED_PIN = 1; delay_ms(250); /* Process any chars in the Rx Buffer */ while(RxR != RxW) { ch = RxBuffer[RxR]; RxR += 1; RxR &= 0xF; printf("Rxed 0x%x ",ch); if(processByte(ch)) /* Pass to protocol handler */ { printf("\r\nPacket Recieved: "); for(n=0;n<18;n++) { printf("%x ",pak1.raw[n]); } printf("\r\n"); startTx(); /* Echo the packet back */ } } } }