| 1 | /**************************************************************
 | 
| 2 | *                                                              *
 | 
| 3 | *                         UART.c                                *
 | 
| 4 | *                                                              *
 | 
| 5 | ***************************************************************/
 | 
| 6 | 
 | 
| 7 | /* Include-Dateien
 | 
| 8 |    -----------------*/
 | 
| 9 | 
 | 
| 10 | 
 | 
| 11 | #include <avr/io.h>
 | 
| 12 | #include <avr/interrupt.h>
 | 
| 13 | 
 | 
| 14 | /* UCR - UART Control Register: Bit Definitionen
 | 
| 15 |    -----------------------------------------------------------*/
 | 
| 16 | #define     RXCIE    0x80    // Bit 7
 | 
| 17 | #define     TXCIE    0x40    // Bit 6
 | 
| 18 | #define     UDRIE    0x20    // Bit 5
 | 
| 19 | #define     RXEN     0x10    // Bit 4
 | 
| 20 | #define     TXEN     0x08    // Bit 3
 | 
| 21 | #define     CHR9     0x04    // Bit 2
 | 
| 22 | #define     RXB8     0x02    // Bit 1
 | 
| 23 | #define     TXB8     0x01    // Bit 0
 | 
| 24 | 
 | 
| 25 | /* USR - UART Status Register: Bit Definitionen
 | 
| 26 |     ---------------------------------------------------------*/
 | 
| 27 | #define     RXC     0x80    // Bit 7
 | 
| 28 | #define     TXC     0x40    // Bit 6
 | 
| 29 | #define     UDRE    0x20    // Bit 5
 | 
| 30 | #define     FE      0x10    // Bit 4
 | 
| 31 | #define     OVR     0x08    // Bit 3
 | 
| 32 | 
 | 
| 33 | /* UBRR - UART Baudrate Register: Baud Definitionen fuer 4MHz
 | 
| 34 |     ---------------------------------------------------------*/
 | 
| 35 | #define     BAUD_1200     208
 | 
| 36 | #define     BAUD_2400     103
 | 
| 37 | #define     BAUD_9600     25
 | 
| 38 | #define     BAUD_19200    12
 | 
| 39 | 
 | 
| 40 | /* UART Daten-Puffer Definitionen
 | 
| 41 |     ------------------------------*/
 | 
| 42 | #define BUFFER_SIZE     8     // Modulo 2 Groesse: nur 2,4,8,16,32 Bytes
 | 
| 43 | #define BUFFER_MASK     (BUFFER_SIZE-1)
 | 
| 44 | 
 | 
| 45 | /* Allgemeine typ-Definitionen
 | 
| 46 |     -----------------------------------------------------------*/
 | 
| 47 | typedef enum{ FALSE=0, TRUE=1} Boolean_t ;
 | 
| 48 | 
 | 
| 49 | typedef struct{ unsigned char UartData[ BUFFER_SIZE ];
 | 
| 50 |                 unsigned char NumberOfBytes;
 | 
| 51 |                 unsigned char UartStatus; } Uart_t;
 | 
| 52 | 
 | 
| 53 | /* Static Variables
 | 
| 54 |    -------------------*/
 | 
| 55 | static unsigned char                RxBuf[ BUFFER_SIZE ];
 | 
| 56 | static volatile unsigned char       RxProducer;  // Empfang: Int-Service ist der Producer
 | 
| 57 | static volatile unsigned char       RxConsumer;  // Empfang: Hauptprogramm ist Consumer
 | 
| 58 | static unsigned char                TxBuf[ BUFFER_SIZE ];
 | 
| 59 | static volatile unsigned char       TxProducer;  // Senden: Hauptprogramm ist der Producer
 | 
| 60 | static volatile unsigned char       TxConsumer;  // Senden: Int-Service ist Consumer
 | 
| 61 | 
 | 
| 62 | /* Funktion-Prototypen
 | 
| 63 |    ----------------------------*/
 | 
| 64 | void InitUart( unsigned char baudrate );
 | 
| 65 | Boolean_t ReceiveData( Uart_t * Data );
 | 
| 66 | Boolean_t TransmitData( Uart_t * Data );
 | 
| 67 | void Delay( void );
 | 
| 68 | 
 | 
| 69 | /* Input Pins, Port B:               sfrb PINB    = 0x16;
 | 
| 70 |    Data Direction Register, Port B:  sfrb DDRB    = 0x17;
 | 
| 71 |    Data Register, Port B:            sfrb PORTB   = 0x18; */
 | 
| 72 | void Delay( void )  // warte zeit
 | 
| 73 | {
 | 
| 74 |   unsigned int i= 0x7FFF;
 | 
| 75 |   while(--i);
 | 
| 76 | }
 | 
| 77 | 
 | 
| 78 | 
 | 
| 79 | /* Main - ein einfaches Anwendungsbeispiel fuer UART und Timer
 | 
| 80 |    -------------------------------------------------------------*/
 | 
| 81 | void C_task main( void )
 | 
| 82 | {
 | 
| 83 |     Uart_t UartData;
 | 
| 84 | 
 | 
| 85 |     DDRB  = 0xFF ; // Konfiguriert Port B als Ausgang
 | 
| 86 |     PORTB = 0xAA;
 | 
| 87 | 
 | 
| 88 |     InitUart( BAUD_9600 );     // Baudrate = 9600 Baud bei 4MHz Quarz
 | 
| 89 |     _SEI();                      // Freigabe aller Interrupts => Enable UART Interrupts
 | 
| 90 | 
 | 
| 91 |     for( ;; )                  // Endlos-Schleife
 | 
| 92 |     {
 | 
| 93 |         if( ReceiveData( & UartData ) )
 | 
| 94 |         {
 | 
| 95 |           TransmitData( & UartData );     // Echo der empfangenen Bytes
 | 
| 96 |         }
 | 
| 97 | 
 | 
| 98 |         PORTB++; // Nur zum Testen Led schalten
 | 
| 99 |         Delay(); // damit das Programm nicht nur die UART Daten abfragt
 | 
| 100 |     }
 | 
| 101 | }
 | 
| 102 | 
 | 
| 103 | /* Initialisierung der UART
 | 
| 104 |     ------------------------------*/
 | 
| 105 | void InitUart( unsigned char baudrate )
 | 
| 106 | {
 | 
| 107 |     UBRR = baudrate;               // Baudrate setzen
 | 
| 108 | 
 | 
| 109 |                                   // Freigabe der UART Interrupts
 | 
| 110 |     UCR =  TXEN | RXEN | RXCIE;   // ==> Senden/Empfangen/Empf.INT
 | 
| 111 | 
 | 
| 112 |     RxConsumer     = 0;            // Ruecksetzen der Puffer-Index
 | 
| 113 |     RxProducer     = 0;
 | 
| 114 |     TxConsumer     = 0;
 | 
| 115 |     TxProducer     = 0;
 | 
| 116 | }
 | 
| 117 | 
 | 
| 118 | /*  Empfangs-Interrupt Handler
 | 
| 119 |     --------------------------- */
 | 
| 120 | interrupt [UART_RX_vect] void UartRxIntHandler( void )
 | 
| 121 | {
 | 
| 122 |     unsigned char data;
 | 
| 123 | 
 | 
| 124 |     data = UDR;                 // Lesen der Empfangsdaten
 | 
| 125 |     RxBuf[RxProducer] = data;   // Empfangenes Byte in Puffer ablegen
 | 
| 126 |     RxProducer++;               // Bufferindex setzen
 | 
| 127 |     RxProducer &=BUFFER_MASK;   // Index begrenzen und evtl. auf Puffer-Anfang
 | 
| 128 | 
 | 
| 129 |     if (RxProducer == RxConsumer )
 | 
| 130 |     {
 | 
| 131 |         // Fehler! Ueberlauf Empfangspuffer
 | 
| 132 |     }
 | 
| 133 |     if( data =='\r') Wenn return Taste gedruckt
 | 
| 134 |     {
 | 
| 135 |      RxProducer == RxConsumer ; // Überlauf simulieren
 | 
| 136 |      // UCR=~RXCIE; //oder der   interrupt disable
 | 
| 137 |     }
 | 
| 138 | 
 | 
| 139 | }
 | 
| 140 | 
 | 
| 141 | /*  Sende-Interrupt Handler
 | 
| 142 |     --------------------------- */
 | 
| 143 | interrupt [UART_UDRE_vect] void UART_TX_interrupt( void )
 | 
| 144 | {
 | 
| 145 |     // Test ob noch nicht fertig mit Senden
 | 
| 146 |     if ( TxConsumer != TxProducer  ) // Nein, weiter machen mit senden
 | 
| 147 |     {
 | 
| 148 |         ++TxConsumer;               // Pufferindex aktualisieren
 | 
| 149 |         TxConsumer &=BUFFER_MASK;   // Index begrenzen und evtl. auf Puffer-Anfang
 | 
| 150 |         UDR = TxBuf[TxConsumer];    // Uebergabe eines Bytes
 | 
| 151 |      }
 | 
| 152 |         else  // fertig ,senden beenden
 | 
| 153 |     {
 | 
| 154 |         UCR &= ~UDRIE; // Disable UDRE interrupt
 | 
| 155 |     }
 | 
| 156 | }
 | 
| 157 | 
 | 
| 158 | 
 | 
| 159 | /* UART Empfangsfunktion
 | 
| 160 |    --------------------- */
 | 
| 161 | Boolean_t ReceiveData( Uart_t * Data )
 | 
| 162 | {
 | 
| 163 |     unsigned char i=0;
 | 
| 164 | 
 | 
| 165 |     // Schleife zur Uebergabe der empfangenen Daten
 | 
| 166 |     while (( RxConsumer != RxProducer ) && ( i < BUFFER_SIZE ) )
 | 
| 167 |     {
 | 
| 168 |        Data->UartData[i++] = RxBuf[RxConsumer++];
 | 
| 169 | 
 | 
| 170 |        RxConsumer &=BUFFER_MASK;   // Consumer-Index begrenzen und evtl. auf Puffer-Anfang
 | 
| 171 |     }
 | 
| 172 | 
 | 
| 173 |     Data->NumberOfBytes = i ;
 | 
| 174 | 
 | 
| 175 |     if( i ) return TRUE ;
 | 
| 176 |      else return FALSE ;
 | 
| 177 | }
 | 
| 178 | 
 | 
| 179 | /* Sendefunktion
 | 
| 180 |    --------------------- */
 | 
| 181 | Boolean_t TransmitData( Uart_t * Data )
 | 
| 182 | {
 | 
| 183 |     unsigned char i=0;
 | 
| 184 | 
 | 
| 185 |     while (( i < Data->NumberOfBytes ) && ( i < BUFFER_SIZE ) )// Uebergabe Sendendaten
 | 
| 186 |     {
 | 
| 187 |        TxBuf[TxProducer++] = Data->UartData[i++] ;
 | 
| 188 | 
 | 
| 189 |        TxProducer &=BUFFER_MASK;   // Producer-Index begrenzen und evtl. auf Puffer-Anfang
 | 
| 190 |     }
 | 
| 191 | 
 | 
| 192 |     UDR = TxBuf[TxConsumer];        // Senden Anstossen
 | 
| 193 |     ++TxConsumer;
 | 
| 194 |     TxConsumer &=BUFFER_MASK;   // Consumer-Index begrenzen
 | 
| 195 | 
 | 
| 196 |     UCR |=  UDRIE ;
 | 
| 197 |     Data->NumberOfBytes = 0;
 | 
| 198 |     return TRUE ;
 | 
| 199 | }
 |