/** SER0.C ********************************************************* Sende- und Empfangsroutinen mit Interrupt Pufferung in zirkularem Buffer Timer1 als Baudratengenerator erfordert folgende Makros CLOCKMHZ Taktfrequenz (11,12,16) BAUD Baudrate (2400,4800,9600) *******************************************************************/ #include "ser0.h" #include #include #ifdef __C51__ #else #include #include #define putchar putchar_pc #endif #ifdef LDEBUG #define CLOCKMHZ 12 #else #ifndef CLOCKMHZ #define CLOCKMHZ 12 #endif /* CLOCKMHZ */ #endif /* LDEBUG */ #if CLOCKMHZ==11 #define TIMER2400 0xF4 #define TIMER4800 0xFA #define TIMER9600 0xFD #endif #if CLOCKMHZ==12 #define TIMER2400 0xF3 #define TIMER4800 0xF9 #define TIMER9600 0xFD #endif #if CLOCKMHZ==16 #define TIMER2400 0xEF #define TIMER4800 0xF7 #define TIMER9600 0xFC #endif #ifndef BAUD #define BAUD 9600 #endif #if BAUD==2400 #define TIMER1 TIMER2400 #elif BAUD==4800 #define TIMER1 TIMER4800 #elif BAUD==9600 #define TIMER1 TIMER9600 #elif #define TIMER1 TIMER9600 #endif /* verwendete Hardware-Ressourcen 8051x SERIAL0 TIMER1 stellt Baudrate ein */ /** LOCAL **********************************************************/ /* Interrupt-Bearbeitung * --------------------- * Zirkularer Puffer 'buffer', wird von ISR_serial beschrieben und * von getch() gelesen. ba und be zeigen jeweils auf den Anfang * und auf das Ende. Auf den Index be wird geschrieben, vom Index ba * wird gelesen. Beim Schreiben wird be inkrementiert, ba bleibt konstant; * beim Lesen wird ba inkrementiert, be bleibt konstant. * wenn be==ba -> buffer leer * wenn ba!=0 : be==ba-1 -> buffer voll * ba==0 : be==BUFFER-1 -> buffer voll */ #define RXBUFFER 4 volatile char xdata i_rxovfl=0; volatile char xdata i_rxbuffer[RXBUFFER]; volatile char xdata i_rxba=0; /* Index für den Beginn des zirkularen Buffers */ volatile char xdata i_rxbe=0; /* Index für das Ende des zirkularen Buffers */ #define TXBUFFER 4 volatile char xdata i_txempty=1; volatile char xdata i_txbuffer[TXBUFFER]; volatile char xdata i_txba=0; /* Index für den Beginn des zirkularen Buffers */ volatile char xdata i_txbe=0; /* Index für das Ende des zirkularen Buffers */ #ifdef __C51__ void serial(void) interrupt 4 #else void serial(void) #endif { if (TI) { if (i_txba==i_txbe) /* wenn buffer leer keine Aussendung */ { i_txempty = 1; } else { SBUF=i_txbuffer[i_txba++]; if (i_txba==TXBUFFER) i_txba=0; i_txempty = 0; } TI=0; } if (RI) { if ( (((i_rxba==0) && (i_rxbe==(RXBUFFER-1))) || (i_rxbe==(i_rxba-1)) ) ) { /* Buffer voll */ i_rxovfl=1; } else { i_rxbuffer[i_rxbe++] = SBUF; if (i_rxbe==RXBUFFER) i_rxbe=0; } RI=0; } } /** PUBLIC **********************************************************/ void serial0_init(void) { /* serielle Schnittstelle 0 */ /* SCON */ SM0=0;SM1=1; /* Modus 1, 8 Bit, Timer 1 */ SM2=0; /* Multi-Controller aus */ REN=1; /* Empfänger einschalten */ TB8=0;RB8=0; /* kein 9-tes Bit */ TI=1; /* PCON */ PCON |= 0x80; /* Division durch 2 */ /* Timer 1 */ /* TMOD */ TMOD &= 0x0F; /* T1 auf Modus 2, Reload */ TMOD |= 0x20; TH1 = TIMER1; /* Reload-Wert aus Liste */ /* TCON */ TR1 = 1; /* T1 einschalten */ /* Interrupts */ ES = 1; /* Serieller Interrupt ein */ /* Interrupt von Timer 1 wird nicht benötigt */ EA = 1; } char txs (void) /* SendeStatus */ { #ifdef __C51__ return ((i_txba==0) && (i_txbe==TXBUFFER-1)) || ((i_txba!=0) && (i_txbe==i_txba-1)); #else return 1; #endif } char putchar (char c) { if (txs()) { while (txs()); /* wenn Buffer voll, warten */ } #ifdef __C51__ i_txbuffer[i_txbe++] = c; if (i_txbe==TXBUFFER) i_txbe=0; if (i_txempty) TI=1; #else putch(c); #endif return c; } char rxs (void) /* EmpfangsStatus */ { #ifdef __C51__ return (!(i_rxba==i_rxbe)); #else return (kbhit()); #endif } char _getkey(void) /* Empfang eines Zeichens */ { char c; if (rxs()==0) { while (rxs()==0) ; } #ifdef __C51__ ES = 0; /* Seriellen Interrupt ausschalten */ c = i_rxbuffer[i_rxba++]; if (i_rxba==RXBUFFER) i_rxba=0; ES = 1; #else c = getch(); #endif return (c); }