Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATEMGA162][C/AVRGCC] Odbiór stringów z uart w przerwaniach

29 Sie 2009 12:25 3045 1
  • Poziom 15  
    Witam,

    Próbuję korzystać z biblioteki Peter Fleury do obsługi usart-u, której listing znajduje się poniżej:

    PLIK uart.c

    Code:
    /*************************************************************************
    
    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


    Plik uart.h



    Code:
    #ifndef UART_H
    
    #define UART_H
    /************************************************************************
    Title:    Interrupt UART library with receive/transmit circular buffers
    Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
    File:     $Id: uart.h,v 1.8.2.1 2007/07/01 11:14:38 peter Exp $
    Software: AVR-GCC 4.1, AVR Libc 1.4
    Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz
    License:  GNU General Public License
    Usage:    see Doxygen manual

    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.
       
    ************************************************************************/

    /**
     *  @defgroup pfleury_uart UART Library
     *  @code #include <uart.h> @endcode
     *
     *  @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers.
     *
     *  This library can be used to transmit and receive data through the built in UART.
     *
     *  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 constants define
     *  the size of the circular buffers in bytes. Note that these constants must be a power of 2.
     *  You may need to adapt this constants to your target and your application by adding
     *  CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile.
     *
     *  @note Based on Atmel Application Note AVR306
     *  @author Peter Fleury pfleury(malpa)gmx.ch  http://jump.to/fleury
     */
     
    /**@{*/


    #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
    #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
    #endif


    /*
    ** constants and macros
    */

    /** @brief  UART Baudrate Expression
     *  @param  xtalcpu  system clock in Mhz, e.g. 4000000L for 4Mhz         
     *  @param  baudrate baudrate in bps, e.g. 1200, 2400, 9600     
     */
    #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)

    /** @brief  UART Baudrate Expression for ATmega double speed mode
     *  @param  xtalcpu  system clock in Mhz, e.g. 4000000L for 4Mhz           
     *  @param  baudrate baudrate in bps, e.g. 1200, 2400, 9600     
     */
    #define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)


    /** Size of the circular receive buffer, must be power of 2 */
    #ifndef UART_RX_BUFFER_SIZE
    #define UART_RX_BUFFER_SIZE 32
    #endif
    /** Size of the circular transmit buffer, must be power of 2 */
    #ifndef UART_TX_BUFFER_SIZE
    #define UART_TX_BUFFER_SIZE 32
    #endif

    /* test if the size of the circular buffers fits into SRAM */
    #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) )
    #error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
    #endif

    /*
    ** high byte error return code of uart_getc()
    */
    #define UART_FRAME_ERROR      0x0800              /* Framing Error by UART       */
    #define UART_OVERRUN_ERROR    0x0400              /* Overrun condition by UART   */
    #define UART_BUFFER_OVERFLOW  0x0200              /* receive ringbuffer overflow */
    #define UART_NO_DATA          0x0100              /* no receive data available   */


    /*
    ** function prototypes
    */

    /**
       @brief   Initialize UART and set baudrate
       @param   baudrate Specify baudrate using macro UART_BAUD_SELECT()
       @return  none
    */
    extern void uart_init(unsigned int baudrate);


    /**
     *  @brief   Get received byte from ringbuffer
     *
     * Returns in the lower byte the received character and in the
     * higher byte the last receive error.
     * UART_NO_DATA is returned when no data is available.
     *
     *  @param   void
     *  @return  lower byte:  received byte from ringbuffer
     *  @return  higher byte: last receive status
     *           - \b 0 successfully received data from UART
     *           - \b UART_NO_DATA           
     *             <br>no receive data available
     *           - \b UART_BUFFER_OVERFLOW   
     *             <br>Receive ringbuffer overflow.
     *             We are not reading the receive buffer fast enough,
     *             one or more received character have been dropped
     *           - \b UART_OVERRUN_ERROR     
     *             <br>Overrun condition by UART.
     *             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.
     *           - \b UART_FRAME_ERROR       
     *             <br>Framing Error by UART
     */
    extern unsigned int uart_getc(void);


    /**
     *  @brief   Put byte to ringbuffer for transmitting via UART
     *  @param   data byte to be transmitted
     *  @return  none
     */
    extern void uart_putc(unsigned char data);


    /**
     *  @brief   Put string to ringbuffer for transmitting via UART
     *
     *  The string is buffered by the uart library in a circular buffer
     *  and one character at a time is transmitted to the UART using interrupts.
     *  Blocks if it can not write the whole string into the circular buffer.
     *
     *  @param   s string to be transmitted
     *  @return  none
     */
    extern void uart_puts(const char *s );


    /**
     * @brief    Put string from program memory to ringbuffer for transmitting via UART.
     *
     * The string is buffered by the uart library in a circular buffer
     * and one character at a time is transmitted to the UART using interrupts.
     * Blocks if it can not write the whole string into the circular buffer.
     *
     * @param    s program memory string to be transmitted
     * @return   none
     * @see      uart_puts_P
     */
    extern void uart_puts_p(const char *s );

    /**
     * @brief    Macro to automatically put a string constant into program memory
     */
    #define uart_puts_P(__s)       uart_puts_p(PSTR(__s))



    /** @brief  Initialize USART1 (only available on selected ATmegas) @see uart_init */
    extern void uart1_init(unsigned int baudrate);
    /** @brief  Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */
    extern unsigned int uart1_getc(void);
    /** @brief  Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */
    extern void uart1_putc(unsigned char data);
    /** @brief  Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */
    extern void uart1_puts(const char *s );
    /** @brief  Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */
    extern void uart1_puts_p(const char *s );
    /** @brief  Macro to automatically put a string constant into program memory */
    #define uart1_puts_P(__s)       uart1_puts_p(PSTR(__s))

    /**@}*/


    #endif // UART_H



    korzystam z przykładowego pliku dołączonego do biblioteki:

    Code:

    /*************************************************************************
    Title:    example program for the Interrupt controlled UART library
    Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
    File:     $Id: test_uart.c,v 1.4 2005/07/10 11:46:30 Peter Exp $
    Software: AVR-GCC 3.3
    Hardware: any AVR with built-in UART, tested on AT90S8515 at 4 Mhz

    DESCRIPTION:
              This example shows how to use the UART library uart.c

    *************************************************************************/
    #include <stdlib.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <avr/pgmspace.h>

    #include "uart.h"


    /* define CPU frequency in Mhz here if not defined in Makefile */
    #ifndef F_CPU
    #define F_CPU 8000000UL
    #endif

    /* 9600 baud */
    #define UART_BAUD_RATE      9600     


    int main(void)
    {
        unsigned int c;
        char buffer[7];
        int  num=134;

       
        /*
         *  Initialize UART library, pass baudrate and AVR cpu clock
         *  with the macro
         *  UART_BAUD_SELECT() (normal speed mode )
         *  or
         *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
         */
        uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
       
        /*
         * now enable interrupt, since UART library is interrupt controlled
         */
        sei();
       
        /*
         *  Transmit string to UART
         *  The string is buffered by the uart library in a circular buffer
         *  and one character at a time is transmitted to the UART using interrupts.
         *  uart_puts() blocks if it can not write the whole string to the circular
         *  buffer
         */
        uart_puts("String stored in SRAM\n\r");
       
        /*
         * Transmit string from program memory to UART
         */
        uart_puts_P("String stored in FLASH\n\r");
       
           
        /*
         * Use standard avr-libc functions to convert numbers into string
         * before transmitting via UART
         */     
        itoa( num, buffer, 10);   // convert interger into string (decimal format)         
        uart_puts(buffer);        // and transmit string to UART

       
        /*
         * Transmit single character to UART
         */
        uart_putc('\r');
       
        for(;;)
        {
            /*
             * 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 );
            }
        }
       
    }


    To co Atmega wysyła, odbieram w konsoli, niestety wygląda na to że program nie odbiera tego co wysyłam z terminala. I drugie pytanie: jak zmodyfikować tą bibliotekę tak, żeby można było odbierać ciąg znaków np. do napotkania ciągu "end" ?

    Proszę o wskazówki
  • Poziom 13  
    Witam, najprościej mozna zrobic tak :

    ISR(SIG_UART_RECV){
    static unsigned char poz_buf_rs_1=0;
    unsigned char Odczyt=UDR;
    static char buf_rs[10];
    buf_rs[poz_buf_rs_1]=Odczyt;
    poz_buf_rs_1++;
    buf_rs[poz_buf_rs_1]=0;

    if(Odczyt==13){

    if(strncmp(buf_rs,"*IDN?",5)==0){
    poz_buf_rs_1=0;
    }
    }
    To jest przykład który po odebraniu ciagu *IDN? wykonuje to co zawarte jest w pętli if.