logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[AVR GCC] UART - Odczyt ciągu znakowego (lini )w przerwaniu

xPatryk 10 Mar 2009 18:10 5993 6
REKLAMA
  • #1 6263090
    xPatryk
    Poziom 15  
    Witajcie,

    w jaki sposób można optymalnie odczytać przesłany (aż do znaku nowej linii / powrotu karetki) ciąg znaków od przerwania otrzymania danych?





    
    /*
     * Sterowanie przez RS232 (main.c)
     */
    
    #include "defines.h"
    
    #include <ctype.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <avr/interrupt.h>
    #include <avr/io.h>
    #include <avr/pgmspace.h>
    
    #include <util/delay.h>
    
    #include "projdat.h"
    #include "lcd.h"
    #include "uart.h"
    
    /*
     * Inicjalizacja
     */
    static void
    ioinit(void)
    {
      InitT2();
      uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
      lcd_init();
      sei();
    }
    
    FILE uart_str = FDEV_SETUP_STREAM(uart_putc, uart_getc, _FDEV_SETUP_RW);
    FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
    
    
    #define MS100_DELAY 5
    #define LCD1s_DELAY 10
    
    // dane :
    
    static void
    delay_1s(void)
    {
      uint8_t i;
    
      for (i = 0; i < 100; i++)
        _delay_ms(10);
    }
    
    int
    main(void)
    {
      uint8_t i;
    
      ioinit();
    
      stdout = stdin = &uart_str;
    
    
    // obsługa pozostałych, nieistotnych z punktu widzenia problemu elementów
    
     // pętla główna
     while (1)
      {
         // coś robimy... 
    
    
         // obsługa flagi ustawionej przez przerwanie:
    
            /*
             * Get received character from ringbuffer
             * uart_getc() returns in the lower byte the received character and 
             * in the higher byte (bitmask) the last receive error
             * UART_NO_DATA is returned when no data is available.
             *
             */
            c = uart_getc();
            if ( c & UART_NO_DATA )
            {
                /* 
                 * no data available from UART 
                 */
            }
            else
            {
                /*
                 * new data available from UART
                 * check for Frame or Overrun error
                 */
                if ( c & UART_FRAME_ERROR )
                {
                    /* Framing Error detected, i.e no stop bit detected */
                    uart_puts_P("UART Frame Error: ");
                }
                if ( c & UART_OVERRUN_ERROR )
                {
                    /* 
                     * Overrun, a character already present in the UART UDR register was 
                     * not read by the interrupt handler before the next character arrived,
                     * one or more received characters have been dropped
                     */
                    uart_puts_P("UART Overrun Error: ");
                }
                if ( c & UART_BUFFER_OVERFLOW )
                {
                    /* 
                     * We are not reading the receive buffer fast enough,
                     * one or more received character have been dropped 
                     */
                    uart_puts_P("Buffer overflow error: ");
                }
                /* 
                 * send received character back
                 */
    
    
                uart_putc( (unsigned char)c );
    
                /* [b]tutaj zamiast wysyłać ponownie otrzymany znak, chciałbym aby zczytana została cała linia do końca, tj. do znaku \r lub \n */
    
            }
      	
    }
    
    


    oraz wykorzystana biblioteka do obsługi portu szeregowego:

    
    /*************************************************************************
    Title:    Interrupt UART library with receive/transmit circular buffers
    Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
    File:     $Id: uart.c,v 1.6.2.1 2007/07/01 11:14:38 peter Exp $
    Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
    Hardware: any AVR with built-in UART, 
    License:  GNU General Public License 
              
    DESCRIPTION:
        An interrupt is generated when the UART has finished transmitting or
        receiving a byte. The interrupt handling routines use circular buffers
        for buffering received and transmitted data.
        
        The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
        the buffer size in bytes. Note that these variables must be a 
        power of 2.
        
    USAGE:
        Refere to the header file uart.h for a description of the routines. 
        See also example test_uart.c.
    
    NOTES:
        Based on Atmel Application Note AVR306
                        
    LICENSE:
        Copyright (C) 2006 Peter Fleury
    
        This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation; either version 2 of the License, or
        any later version.
    
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
                            
    *************************************************************************/
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include "uart.h"
    
    
    /*
     *  constants and macros
     */
    
    /* size of RX/TX buffers */
    #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
    #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
    
    #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
    #error RX buffer size is not a power of 2
    #endif
    #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
    #error TX buffer size is not a power of 2
    #endif
    
    #if defined(__AVR_AT90S2313__) \
     || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
     || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
     || defined(__AVR_ATmega103__)
     /* old AVR classic or ATmega103 with one UART */
     #define AT90_UART
     #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
     #define UART0_STATUS   USR
     #define UART0_CONTROL  UCR
     #define UART0_DATA     UDR  
     #define UART0_UDRIE    UDRIE
    #elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
     /* old AVR classic with one UART */
     #define AT90_UART
     #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
     #define UART0_STATUS   UCSRA
     #define UART0_CONTROL  UCSRB
     #define UART0_DATA     UDR 
     #define UART0_UDRIE    UDRIE
    #elif  defined(__AVR_ATmega8__)  || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
      || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
      || defined(__AVR_ATmega323__)
      /* ATmega with one USART */
     #define ATMEGA_USART
     #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
     #define UART0_STATUS   UCSRA
     #define UART0_CONTROL  UCSRB
     #define UART0_DATA     UDR
     #define UART0_UDRIE    UDRIE
    #elif defined(__AVR_ATmega163__) 
      /* ATmega163 with one UART */
     #define ATMEGA_UART
     #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
     #define UART0_STATUS   UCSRA
     #define UART0_CONTROL  UCSRB
     #define UART0_DATA     UDR
     #define UART0_UDRIE    UDRIE
    #elif defined(__AVR_ATmega162__) 
     /* ATmega with two USART */
     #define ATMEGA_USART0
     #define ATMEGA_USART1
     #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RECV
     #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_DATA
     #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
     #define UART0_STATUS   UCSR0A
     #define UART0_CONTROL  UCSR0B
     #define UART0_DATA     UDR0
     #define UART0_UDRIE    UDRIE0
     #define UART1_STATUS   UCSR1A
     #define UART1_CONTROL  UCSR1B
     #define UART1_DATA     UDR1
     #define UART1_UDRIE    UDRIE1
    #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 
     /* ATmega with two USART */
     #define ATMEGA_USART0
     #define ATMEGA_USART1
     #define UART0_RECEIVE_INTERRUPT   SIG_UART0_RECV
     #define UART1_RECEIVE_INTERRUPT   SIG_UART1_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_UART0_DATA
     #define UART1_TRANSMIT_INTERRUPT  SIG_UART1_DATA
     #define UART0_STATUS   UCSR0A
     #define UART0_CONTROL  UCSR0B
     #define UART0_DATA     UDR0
     #define UART0_UDRIE    UDRIE0
     #define UART1_STATUS   UCSR1A
     #define UART1_CONTROL  UCSR1B
     #define UART1_DATA     UDR1
     #define UART1_UDRIE    UDRIE1
    #elif defined(__AVR_ATmega161__)
     /* ATmega with UART */
     #error "AVR ATmega161 currently not supported by this libaray !"
    #elif defined(__AVR_ATmega169__) 
     /* ATmega with one USART */
     #define ATMEGA_USART
     #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
     #define UART0_STATUS   UCSRA
     #define UART0_CONTROL  UCSRB
     #define UART0_DATA     UDR
     #define UART0_UDRIE    UDRIE
    #elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
     /* ATmega with one USART */
     #define ATMEGA_USART0
     #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
     #define UART0_STATUS   UCSR0A
     #define UART0_CONTROL  UCSR0B
     #define UART0_DATA     UDR0
     #define UART0_UDRIE    UDRIE0
    #elif defined(__AVR_ATtiny2313__)
     #define ATMEGA_USART
     #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RX 
     #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_UDRE
     #define UART0_STATUS   UCSRA
     #define UART0_CONTROL  UCSRB
     #define UART0_DATA     UDR
     #define UART0_UDRIE    UDRIE
    #elif defined(__AVR_ATmega329__) ||defined(__AVR_ATmega3290__) ||\
          defined(__AVR_ATmega649__) ||defined(__AVR_ATmega6490__) ||\
          defined(__AVR_ATmega325__) ||defined(__AVR_ATmega3250__) ||\
          defined(__AVR_ATmega645__) ||defined(__AVR_ATmega6450__)
      /* ATmega with one USART */
      #define ATMEGA_USART0
      #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
      #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
      #define UART0_STATUS   UCSR0A
      #define UART0_CONTROL  UCSR0B
      #define UART0_DATA     UDR0
      #define UART0_UDRIE    UDRIE0
    #elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega640__)
    /* ATmega with two USART */
      #define ATMEGA_USART0
      #define ATMEGA_USART1
      #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RECV
      #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
      #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_DATA
      #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
      #define UART0_STATUS   UCSR0A
      #define UART0_CONTROL  UCSR0B
      #define UART0_DATA     UDR0
      #define UART0_UDRIE    UDRIE0
      #define UART1_STATUS   UCSR1A
      #define UART1_CONTROL  UCSR1B
      #define UART1_DATA     UDR1
      #define UART1_UDRIE    UDRIE1  
    #elif defined(__AVR_ATmega644__)
     /* ATmega with one USART */
     #define ATMEGA_USART0
     #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
     #define UART0_STATUS   UCSR0A
     #define UART0_CONTROL  UCSR0B
     #define UART0_DATA     UDR0
     #define UART0_UDRIE    UDRIE0
    #elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
     /* ATmega with two USART */
     #define ATMEGA_USART0
     #define ATMEGA_USART1
     #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
     #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
     #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
     #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
     #define UART0_STATUS   UCSR0A
     #define UART0_CONTROL  UCSR0B
     #define UART0_DATA     UDR0
     #define UART0_UDRIE    UDRIE0
     #define UART1_STATUS   UCSR1A
     #define UART1_CONTROL  UCSR1B
     #define UART1_DATA     UDR1
     #define UART1_UDRIE    UDRIE1
    #else
     #error "no UART definition for MCU available"
    #endif
    
    
    /*
     *  module global variables
     */
    static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
    static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
    static volatile unsigned char UART_TxHead;
    static volatile unsigned char UART_TxTail;
    static volatile unsigned char UART_RxHead;
    static volatile unsigned char UART_RxTail;
    static volatile unsigned char UART_LastRxError;
    
    #if defined( ATMEGA_USART1 )
    static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
    static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
    static volatile unsigned char UART1_TxHead;
    static volatile unsigned char UART1_TxTail;
    static volatile unsigned char UART1_RxHead;
    static volatile unsigned char UART1_RxTail;
    static volatile unsigned char UART1_LastRxError;
    #endif
    
    
    
    SIGNAL(UART0_RECEIVE_INTERRUPT)
    /*************************************************************************
    Function: UART Receive Complete interrupt
    Purpose:  called when the UART has received a character
    **************************************************************************/
    {
        unsigned char tmphead;
        unsigned char data;
        unsigned char usr;
        unsigned char lastRxError;
     
     
        /* read UART status register and UART data register */ 
        usr  = UART0_STATUS;
        data = UART0_DATA;
        
        /* */
    #if defined( AT90_UART )
        lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
    #elif defined( ATMEGA_USART )
        lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
    #elif defined( ATMEGA_USART0 )
        lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
    #elif defined ( ATMEGA_UART )
        lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
    #endif
            
        /* calculate buffer index */ 
        tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
        
        if ( tmphead == UART_RxTail ) {
            /* error: receive buffer overflow */
            lastRxError = UART_BUFFER_OVERFLOW >> 8;
        }else{
            /* store new index */
            UART_RxHead = tmphead;
            /* store received data in buffer */
            UART_RxBuf[tmphead] = data;
        }
        UART_LastRxError = lastRxError;   
    }
    
    
    SIGNAL(UART0_TRANSMIT_INTERRUPT)
    /*************************************************************************
    Function: UART Data Register Empty interrupt
    Purpose:  called when the UART is ready to transmit the next byte
    **************************************************************************/
    {
        unsigned char tmptail;
    
        
        if ( UART_TxHead != UART_TxTail) {
            /* calculate and store new buffer index */
            tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
            UART_TxTail = tmptail;
            /* get one byte from buffer and write it to UART */
            UART0_DATA = UART_TxBuf[tmptail];  /* start transmission */
        }else{
            /* tx buffer empty, disable UDRE interrupt */
            UART0_CONTROL &= ~_BV(UART0_UDRIE);
        }
    }
    
    
    /*************************************************************************
    Function: uart_init()
    Purpose:  initialize UART and set baudrate
    Input:    baudrate using macro UART_BAUD_SELECT()
    Returns:  none
    **************************************************************************/
    void uart_init(unsigned int baudrate)
    {
        UART_TxHead = 0;
        UART_TxTail = 0;
        UART_RxHead = 0;
        UART_RxTail = 0;
        
    #if defined( AT90_UART )
        /* set baud rate */
        UBRR = (unsigned char)baudrate; 
    
        /* enable UART receiver and transmmitter and receive complete interrupt */
        UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
    
    #elif defined (ATMEGA_USART)
        /* Set baud rate */
        if ( baudrate & 0x8000 )
        {
        	 UART0_STATUS = (1<<U2X);  //Enable 2x speed 
        	 baudrate &= ~0x8000;
        }
        UBRRH = (unsigned char)(baudrate>>8);
        UBRRL = (unsigned char) baudrate;
       
        /* Enable USART receiver and transmitter and receive complete interrupt */
        UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
        
        /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
        #ifdef URSEL
        UCSRC = (1<<URSEL)|(3<<UCSZ0);
        #else
        UCSRC = (3<<UCSZ0);
        #endif 
        
    #elif defined (ATMEGA_USART0 )
        /* Set baud rate */
        if ( baudrate & 0x8000 ) 
        {
       		UART0_STATUS = (1<<U2X0);  //Enable 2x speed 
       		baudrate &= ~0x8000;
       	}
        UBRR0H = (unsigned char)(baudrate>>8);
        UBRR0L = (unsigned char) baudrate;
    
        /* Enable USART receiver and transmitter and receive complete interrupt */
        UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
        
        /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
        #ifdef URSEL0
        UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
        #else
        UCSR0C = (3<<UCSZ00);
        #endif 
    
    #elif defined ( ATMEGA_UART )
        /* set baud rate */
        if ( baudrate & 0x8000 ) 
        {
        	UART0_STATUS = (1<<U2X);  //Enable 2x speed 
        	baudrate &= ~0x8000;
        }
        UBRRHI = (unsigned char)(baudrate>>8);
        UBRR   = (unsigned char) baudrate;
    
        /* Enable UART receiver and transmitter and receive complete interrupt */
        UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
    
    #endif
    
    }/* uart_init */
    
    
    /*************************************************************************
    Function: uart_getc()
    Purpose:  return byte from ringbuffer  
    Returns:  lower byte:  received byte from ringbuffer
              higher byte: last receive error
    **************************************************************************/
    unsigned int uart_getc(void)
    {    
        unsigned char tmptail;
        unsigned char data;
    
    
        if ( UART_RxHead == UART_RxTail ) {
            return UART_NO_DATA;   /* no data available */
        }
        
        /* calculate /store buffer index */
        tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
        UART_RxTail = tmptail; 
        
        /* get data from receive buffer */
        data = UART_RxBuf[tmptail];
        
        return (UART_LastRxError << 8) + data;
    
    }/* uart_getc */
    
    
    /*************************************************************************
    Function: uart_putc()
    Purpose:  write byte to ringbuffer for transmitting via UART
    Input:    byte to be transmitted
    Returns:  none          
    **************************************************************************/
    void uart_putc(unsigned char data)
    {
        unsigned char tmphead;
    
        
        tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
        
        while ( tmphead == UART_TxTail ){
            ;/* wait for free space in buffer */
        }
        
        UART_TxBuf[tmphead] = data;
        UART_TxHead = tmphead;
    
        /* enable UDRE interrupt */
        UART0_CONTROL    |= _BV(UART0_UDRIE);
    
    }/* uart_putc */
    
    
    /*************************************************************************
    Function: uart_puts()
    Purpose:  transmit string to UART
    Input:    string to be transmitted
    Returns:  none          
    **************************************************************************/
    void uart_puts(const char *s )
    {
        while (*s) 
          uart_putc(*s++);
    
    }/* uart_puts */
    
    
    /*************************************************************************
    Function: uart_puts_p()
    Purpose:  transmit string from program memory to UART
    Input:    program memory string to be transmitted
    Returns:  none
    **************************************************************************/
    void uart_puts_p(const char *progmem_s )
    {
        register char c;
        
        while ( (c = pgm_read_byte(progmem_s++)) ) 
          uart_putc(c);
    
    }/* uart_puts_p */
    
    
    /*
     * these functions are only for ATmegas with two USART
     */
    #if defined( ATMEGA_USART1 )
    
    SIGNAL(UART1_RECEIVE_INTERRUPT)
    /*************************************************************************
    Function: UART1 Receive Complete interrupt
    Purpose:  called when the UART1 has received a character
    **************************************************************************/
    {
        unsigned char tmphead;
        unsigned char data;
        unsigned char usr;
        unsigned char lastRxError;
     
     
        /* read UART status register and UART data register */ 
        usr  = UART1_STATUS;
        data = UART1_DATA;
        
        /* */
        lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
            
        /* calculate buffer index */ 
        tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
        
        if ( tmphead == UART1_RxTail ) {
            /* error: receive buffer overflow */
            lastRxError = UART_BUFFER_OVERFLOW >> 8;
        }else{
            /* store new index */
            UART1_RxHead = tmphead;
            /* store received data in buffer */
            UART1_RxBuf[tmphead] = data;
        }
        UART1_LastRxError = lastRxError;   
    }
    
    
    SIGNAL(UART1_TRANSMIT_INTERRUPT)
    /*************************************************************************
    Function: UART1 Data Register Empty interrupt
    Purpose:  called when the UART1 is ready to transmit the next byte
    **************************************************************************/
    {
        unsigned char tmptail;
    
        
        if ( UART1_TxHead != UART1_TxTail) {
            /* calculate and store new buffer index */
            tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
            UART1_TxTail = tmptail;
            /* get one byte from buffer and write it to UART */
            UART1_DATA = UART1_TxBuf[tmptail];  /* start transmission */
        }else{
            /* tx buffer empty, disable UDRE interrupt */
            UART1_CONTROL &= ~_BV(UART1_UDRIE);
        }
    }
    
    
    /*************************************************************************
    Function: uart1_init()
    Purpose:  initialize UART1 and set baudrate
    Input:    baudrate using macro UART_BAUD_SELECT()
    Returns:  none
    **************************************************************************/
    void uart1_init(unsigned int baudrate)
    {
        UART1_TxHead = 0;
        UART1_TxTail = 0;
        UART1_RxHead = 0;
        UART1_RxTail = 0;
        
    
        /* Set baud rate */
        if ( baudrate & 0x8000 ) 
        {
        	UART1_STATUS = (1<<U2X1);  //Enable 2x speed 
          baudrate &= ~0x8000;
        }
        UBRR1H = (unsigned char)(baudrate>>8);
        UBRR1L = (unsigned char) baudrate;
    
        /* Enable USART receiver and transmitter and receive complete interrupt */
        UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
        
        /* Set frame format: asynchronous, 8data, no parity, 1stop bit */   
        #ifdef URSEL1
        UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
        #else
        UCSR1C = (3<<UCSZ10);
        #endif 
    }/* uart_init */
    
    
    /*************************************************************************
    Function: uart1_getc()
    Purpose:  return byte from ringbuffer  
    Returns:  lower byte:  received byte from ringbuffer
              higher byte: last receive error
    **************************************************************************/
    unsigned int uart1_getc(void)
    {    
        unsigned char tmptail;
        unsigned char data;
    
    
        if ( UART1_RxHead == UART1_RxTail ) {
            return UART_NO_DATA;   /* no data available */
        }
        
        /* calculate /store buffer index */
        tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
        UART1_RxTail = tmptail; 
        
        /* get data from receive buffer */
        data = UART1_RxBuf[tmptail];
        
        return (UART1_LastRxError << 8) + data;
    
    }/* uart1_getc */
    
    
    /*************************************************************************
    Function: uart1_putc()
    Purpose:  write byte to ringbuffer for transmitting via UART
    Input:    byte to be transmitted
    Returns:  none          
    **************************************************************************/
    void uart1_putc(unsigned char data)
    {
        unsigned char tmphead;
    
        
        tmphead  = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
        
        while ( tmphead == UART1_TxTail ){
            ;/* wait for free space in buffer */
        }
        
        UART1_TxBuf[tmphead] = data;
        UART1_TxHead = tmphead;
    
        /* enable UDRE interrupt */
        UART1_CONTROL    |= _BV(UART1_UDRIE);
    
    }/* uart1_putc */
    
    
    /*************************************************************************
    Function: uart1_puts()
    Purpose:  transmit string to UART1
    Input:    string to be transmitted
    Returns:  none          
    **************************************************************************/
    void uart1_puts(const char *s )
    {
        while (*s) 
          uart1_putc(*s++);
    
    }/* uart1_puts */
    
    
    /*************************************************************************
    Function: uart1_puts_p()
    Purpose:  transmit string from program memory to UART1
    Input:    program memory string to be transmitted
    Returns:  none
    **************************************************************************/
    void uart1_puts_p(const char *progmem_s )
    {
        register char c;
        
        while ( (c = pgm_read_byte(progmem_s++)) ) 
          uart1_putc(c);
    
    }/* uart1_puts_p */
    
    
    
    #endif
    
    


    Pozdrawiam i proszę o wskazówki / przykład kodu,
    Patryk
  • REKLAMA
  • #2 6263274
    _Robak_
    Poziom 33  
    Nie wiem czy rozumiem o co Ci chodzi do konca. Normalnie w przerwaniach odczytujesz znaki kolejne i wrzucasz je na bufor ( robisz jakas tablice jednowymiarowa). W trakcie programu odczytujesz znaki juz z tego bufora a nie z z samego przerwania. Przerwania juz cie nie interesuja, one same sobie tam sa wywolywane i wrzucane w nich sa znaki na nasz bufor. Jesli chcesz odczytac znaki, dopiero po odebraniu jakiegos konretengo znaku, to po prostu sprawdzasz jaki znak odkladasz na bufor i jesli nadejdzie interesujacy ciebie znak zapalasz sobie gdzies flage i wtedy odbierasz caly ciag.
  • REKLAMA
  • #3 6263493
    xPatryk
    Poziom 15  
    hmm...

    Czyli jeśli dobrze zrozumiałem, tworzę zmienną tablicową, np. char bufor[100], dłuższą od najdłuższej linii, którą chce odczytać, a następnie przy każdym następnym przerwaniu wczytuję wszystkie odebrane znaki, kolejno do tej tablicy, aż napotkam znak '\r' lub podobny, tak?

    Ale co w sytuacji, gdy nim przetworzę dany ciąg znaków, i wyczyszczę bufor, nadejdzie następny?

    Czy do czasu, gdy nie będzie można zapisać do zmiennej bufor[] (będzie ustawiona jakaś flaga zajętości), przerwanie zatrzyma wykonywanie programu (przez co bufor nigdy się nie zwolni?)

    Ponadto, czy w sytuacji - gdy j/w - obsługa odczytu po stwierdzeniu ustawienia flagi wystąpienia przerwania w pętli, będzie przez kilka cykli oczekiwać na zwolnienie buforu, a w tym czasie nadejdą nowe dane, zostaną one utracone, czy może przechowane w jakimś wewnętrznym buforze procesora? (przykładowo AtMega32).

    Czy istnieją jakieś dopracowane rozwiązania tego problemu - np. dynamicznie tworzone i usuwane z pamięci bufory?

    Pozdrawiam,
    Patryk
  • REKLAMA
  • #4 6263616
    _Robak_
    Poziom 33  
    Jesli chcesz pisac sam obsluge buforow to musisz przeanalizowac jak zrobic zeby bylo dobrze:)
    Masz tutaj kod, co prawda dla PICkow ale to jedno i to samo )

    
    // ++++++ wysylanie +++++++++++
    #int_tbe
    void t_serial_isr() {
       putc(t_buffer[t_next_out]);
       t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
       if(t_next_in==t_next_out)
         disable_interrupts(int_tbe);
    }
    
    void bputc(char c) {
       short restart;
       int ni;
    
       restart=t_next_in==t_next_out;
       t_buffer[t_next_in]=c;
       ni=(t_next_in+1) % T_BUFFER_SIZE;
       while(ni==t_next_out);
       t_next_in=ni;
       if(restart)
         enable_interrupts(int_tbe);
    }
    
    // ++++++ odbieranie +++++++++++
    #define BUFFER_SIZE 32
    BYTE buffer[BUFFER_SIZE];
    BYTE next_in = 0;
    BYTE next_out = 0;
    
    #int_rda
    void r_serial_isr() {
       int t;
    
       buffer[next_in]=getc();
       t=next_in;
       next_in=(next_in+1) % BUFFER_SIZE;
       if(next_in==next_out)
         next_in=t;           // Buffer full !!
    }
    
    #define bkbhit (next_in!=next_out)
    
    BYTE bgetc() {
       BYTE c;
    
       while(!bkbhit) ;
       c=buffer[next_out];
       next_out=(next_out+1) % BUFFER_SIZE;
       return(c);
    }
    

    zmienna bkbhit opisuje czy jest jakis znak do odebrania z bufora
  • REKLAMA
  • #6 6263860
    _Robak_
    Poziom 33  
    Heh.. ;)
    Jesli dostaniesz dwa znaki a nie zapiszesz zmiennej byte gdzies indziej to juz twoje rozwiazanie idzie w piach
  • #7 6263925
    Piotr Kania
    Poziom 15  
    no to prawda to działa tylko w terminalu. Mam taki problem że musze jakoś zapisać nr z at+clip i go porównywać z innym w uP moze ktoś wie jak to zrobić :D
REKLAMA