/* test code for learning how to use the UART on the AVR AT90S8515 Created by Jim Patchell September 30, 2001 Users are free to use this code any way they see fit */ #include #include #pragma interrupt_handler iTxd:11 #pragma interrupt_handler iRxd:10 typedef struct { volatile int head; volatile int tail; volatile int nchar; volatile int size; }IODESC; volatile IODESC txdesc; char txbuff[32]; volatile IODESC rxdesc; char rxbuff[32]; void InitUart(int baud) { int i; UCR |= 0x18; /* enable uart rec and xmit */ UBRR = baud; txdesc.head = 0; /* initialize transmit descriptor */ txdesc.tail = 0; txdesc.nchar = 0; txdesc.size = 32; rxdesc.head = 0; /* initialize receiever descriptor */ rxdesc.tail = 0; rxdesc.size = 32; rxdesc.nchar = 0; for(i=0;i<32;++i) { txbuff[i] = 'o'; rxbuff[i] = 'i'; } } void Disable(void) /* disable interrupts */ { SREG &= ~0x80; } void Enable(void) /* enable interrupts */ { SREG |= 0x80; } void EnableRxIRQ(void) { /************************** ** Enable Receiver interrupts **************************/ UCR |= 0x80; } void DisableRxIRQ(void) { /************************** ** Disable Receirver interrupts **************************/ UCR &= ~0x80; } void EnableTxIRQ(void) { UCR |= 0x20; /* enable transmit data register empty interrupt */ } void DisableTxIRQ(void) { UCR &= ~0x20; /* disable transmit data register empty interrupt */ } void iRxd(void) { /************************** ** Interrupt handler for ** Receive Interrupts **************************/ char c = UDR; /* read data from receive data reg */ if(rxdesc.nchar < rxdesc.size) /* is there space to put char? */ { rxbuff[rxdesc.head++] = c; /* put character into buffer */ if(rxdesc.head == rxdesc.size) rxdesc.head = 0; /* wrap head pointer */ rxdesc.nchar++; /* increment character count */ } /* otherwise, just drop character */ } void iTxd(void) /* interrupt handler for uart */ { char c; c = (char)txbuff[txdesc.tail++]; /* get character from buffer */ --txdesc.nchar; /* one less character to send */ if(txdesc.nchar == 0) /* is xmit buffer empty? */ DisableTxIRQ(); /* stop transmitting data */ if(txdesc.tail == txdesc.size) txdesc.tail = 0; /* wrap tail pointer */ UDR = c; } void LED_On(int i) { PORTB = ~BIT(i); /* low output to turn LED on */ } int GetC(void) { /********************************* ** Get a character from the UART ** If there is no character, wait *********************************/ int c; while(rxdesc.nchar == 0); /* wait for character to apear in buffer */ Disable(); /* disable interrupts */ c = (int)rxbuff[rxdesc.tail++]; /* get character from buffer */ if(rxdesc.tail == rxdesc.size) rxdesc.tail = 0; /* wrap tail pointer */ rxdesc.nchar--; /* decrement number of chars in buffer */ Enable(); return c; /* return fetched character */ } void PutC(int i) { while(txdesc.nchar == txdesc.size); /* pend on buffer full */ Disable(); /* Disable interrupts */ txbuff[txdesc.head++] = (char)i; /* put data into buffer */ if(txdesc.head == txdesc.size) txdesc.head = 0; /* wrap head pointer */ if(txdesc.nchar == 0) /* first char in buff? */ EnableTxIRQ(); /* start transmit interrupt */ txdesc.nchar++; Enable(); /* enable interrupts */ } main() { int i,j; InitUart(25); DDRB = 0xFF; /* output */ PORTB = 0xFF; /* all off */ EnableRxIRQ(); /* enable receive interrupt */ Enable(); /* enable global interrupts */ j=0; while(1) { LED_On(j); if(++j == 8) j = 0; i = GetC(); /* get character from UART */ if(i == '\r') PutC('\n'); PutC(i); while((PIND & 0x80) == 0); /* stop if button 7 is pushed */ } return 0; }