www.mikrocontroller.net

Forum: Compiler & IDEs atmega128 receive uart0 funktioniert nicht


Autor: lisa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

ich möchte mit atmega128 ein "start" vom PC1 durch USRT0 empfangen und 
es durch USART1 an PC2 senden.

ich habe eine serielle schnittstelle mit interrupt programme von peter 
fleury genohmen und es für meinem Atgemeag8 angepasst und getestet 
soweit lauft alles super.
 - leider beim versuch mit atmega128,
werden keine interrupts behandelt .... ???

auch wenn ich den block

SIGNAL(__vector_default)
{
    // user code here z.b. led on
}

einbaue geschieht nichts obwohl die serielle schnittstelle funktioniert
(ohne interrupt und auch im polling-betrieb, ggf. auch ohne die ganzen 
buffer --> schon getestet)

was kann das sein (stack.fuse bits ) ???

hier unten den Code

danke
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <string.h>

#define LENGTH 15

#ifndef F_CPU
#warning "F_CPU was not defined yet, now make up with 4000000"
#define F_CPU 4000000L   // Systemtakt in Hz
#endif


#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand


#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematic error in the baud rate more than 1% and thus too high!
#endif


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

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



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


//module global variables

//ATMEGA_USART0
static volatile unsigned char UART0_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART0_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART0_TxHead;
static volatile unsigned char UART0_TxTail;
static volatile unsigned char UART0_RxHead;
static volatile unsigned char UART0_RxTail;
static volatile unsigned char UART0_LastRxError;

//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;



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;
    
    // defined( ATMEGA_USART0 )
    lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
        
    // calculate buffer index
    tmphead = ( UART0_RxHead + 1) & UART_RX_BUFFER_MASK;
    
    if ( tmphead == UART0_RxTail )
        // error: receive buffer overflow
        lastRxError = UART_BUFFER_OVERFLOW >> 8;

    else
  {
        // store new index
        UART0_RxHead = tmphead;
        // store received data in buffer
        UART0_RxBuf[tmphead] = data;
    }

    UART0_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 ( UART0_TxHead != UART0_TxTail)
  {
        // calculate and store new buffer index
        tmptail = (UART0_TxTail + 1) & UART_TX_BUFFER_MASK;
        UART0_TxTail = tmptail;
        // get one byte from buffer and write it to UART
        UART0_DATA = UART0_TxBuf[tmptail];  // start transmission
    }
  else
        // tx buffer empty, disable UDRE interrupt
        UART0_CONTROL &= ~_BV(UART0_UDRIE);
}


/*************************************************************************
Function: uart0_init()
Purpose:  initialize UART and set baudrate
Input:    baudrate using macro UART_BAUD_SELECT()
Returns:  none
**************************************************************************/
void uart0_init(void)
{
    UART0_TxHead = 0;
    UART0_TxTail = 0;
    UART0_RxHead = 0;
    UART0_RxTail = 0;
    

    
  //defined (ATMEGA_USART0 )
    
    UBRR0H = (unsigned char)(UBRR_VAL>>8);
    UBRR0L = (unsigned char) UBRR_VAL;

    // 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)| (1<<UCSZ01)|(1<<UCSZ00);
    #else
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
    #endif 

}// uart_init


/*************************************************************************
Function: uart0_getc()
Purpose:  return byte from ringbuffer  
Returns:  lower byte:  received byte from ringbuffer
          higher byte: last receive error
**************************************************************************/
unsigned char uart0_getc(void)
{    
    unsigned char tmptail;
    unsigned char data;


    if ( UART0_RxHead == UART0_RxTail ) {
        return (unsigned char) UART_NO_DATA;   // no data available
    }
    
    // calculate /store buffer index
    tmptail = (UART0_RxTail + 1) & UART_RX_BUFFER_MASK;
    UART0_RxTail = tmptail; 
    
    // get data from receive buffer
    data = UART0_RxBuf[tmptail];
    
    return (UART0_LastRxError << 8) + data;

}// uart_getc

/*************************************************************************
Function: uart0_gets()
Purpose:  function which receive a String Through usart
Returns:  lower byte:  received byte from ringbuffer
          higher byte: last receive error
**************************************************************************/
void uart0_gets (char* string, unsigned int Length)
{
  uint8_t i;
    char c;
    char* s;
    
    s=string;
    i=0;
    do
    {
      c=uart0_getc();    
      if (c!='\r') 
       {
          *s=c;    
        s++;
        i++;
       }       
    }
    while( i!=Length && c!='\r');  
    *s = '\0';
  
}//end UART_Gets


/*************************************************************************
Function: uart_putc()
Purpose:  write byte to ringbuffer for transmitting via UART
Input:    byte to be transmitted
Returns:  none          
**************************************************************************/
void uart0_putc(unsigned char data)
{
    unsigned char tmphead;

    // calculate /store buffer index
    tmphead  = (UART0_TxHead + 1) & UART_TX_BUFFER_MASK;
    
    while ( tmphead == UART0_TxTail ){
        ;// wait for free space in buffer
    }
    
    UART0_TxBuf[tmphead] = data;
    UART0_TxHead = tmphead;

    // enable UDRE interrupt
    UART0_CONTROL    |= _BV(UART0_UDRIE);

}// uart_putc

/*void USART_Putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE))); // Do nothing until data have been transmited 
    
  UDR = c;                      // Put data into Buffer, sends the data
  _delay_ms(10);   
}//end USART_Putc()*/
/*************************************************************************
Function: uart_puts()
Purpose:  transmit string to UART
Input:    string to be transmitted
Returns:  none          
**************************************************************************/
void uart0_puts(char *s )
{
    while (*s != '\0' ) 
      uart0_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 uart0_puts_p(const char *progmem_s )
{
    register char c;
    
    while ( (c = pgm_read_byte(progmem_s++)) ) 
      uart0_putc(c);

}//uart_puts_p


/*
 * these functions are only for 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()
{
    UART1_TxHead = 0;
    UART1_TxTail = 0;
    UART1_RxHead = 0;
    UART1_RxTail = 0;
    

    UBRR1H = (unsigned char)(UBRR_VAL>>8);
    UBRR1L = (unsigned char) UBRR_VAL;

    // 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 char uart1_getc(void)
{    
    unsigned char tmptail;
    unsigned char data;


    if ( UART1_RxHead == UART1_RxTail ) {
        return (unsigned char) 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_gets()
Purpose:  function which receive a String Through usart
Returns:  lower byte:  received byte from ringbuffer
          higher byte: last receive error
**************************************************************************/
void uart1_gets (char* string, unsigned int Length)
{
  uint8_t i;
    char c;
    char* s;
    
    s=string;
    i=0;
    do
    {
      c=uart1_getc();    
      if (c!='\r') 
       {
          *s=c;    
        s++;
        i++;
       }       
    }
    while( i!=Length && c!='\r');  
    *s = '\0';
  
}//end uart1_gets

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


  
int main(void)
{

  DDRD = 0xFF;    // PORTD auf Eingang
  PORTD = 0xFF;   //Internal pull ups resistance for key inputs  PortD2 and portD3 was activated

  DDRC = 0xFF;       // outputs for LEDs
  PORTC = 0x00;      // LEDs off

  //  Initialize UART library, pass baudrate and AVR cpu clock with the macro
  uart0_init();  
  uart1_init();   
    
  // now enable interrupt, since UART library is interrupt controlled
  sei();

  char Command [LENGTH+1];

  for(;;)
  {
    PORTC = 0xAA;
    
    uart0_gets( Command, LENGTH );
    uart0_puts( Command );
    uart0_puts( "\r\n" );
        

      if(strcmp(Command, "start") == 0)
    {
          PORTC = 0xFA;
      for(int i=0; i<19; i++)
          uart1_puts("start");
      _delay_ms(10);
    }
      else if(strcmp(Command, "exit") == 0)
    {
          PORTC = 0xBA;
      for(int i=0; i<19; i++)
          uart1_puts("exit");
      _delay_ms(10);
      }
  }  
  return 0;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lisa schrieb:

>  - leider beim versuch mit atmega128,
> werden keine interrupts behandelt .... ???

Wie hast du das festgestellt

    PORTC = 0xAA;

kannst du dieses Muster auf dem Port noch feststellen?

Ist das ein nagelneuer Mega128 oder hattest du den schon im Einsatz? Der 
Grund für die Nachfrage: Beim 128 gibt es eine ganz fiese Falle, die 
M103 Fuse. Dies sorgt dafür, dass sich ein nagelneuer M128 wie ein 103 
verhält. Bemerkbar macht sich das aber erst beim ersten Funktionsaufruf, 
der ganz grauslich in die Hose geht, weil der Stack anders liegt.


SIGNAL(UART0_RECEIVE_INTERRUPT)

Das solltest du gegen die neueren ISR Makros austauschen.

Autor: lisa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die schnelle antwort.

>>>  - leider beim versuch mit atmega128,
>>> werden keine interrupts behandelt .... ???

>>Wie hast du das festgestellt
SIGNAL(__vector_default)
{
    // user code here z.b. led on
}

tut nichts

>> PORTC = 0xAA;

>>kannst du dieses Muster auf dem Port noch feststellen?
"Ja"

ohoh!!! habe vergessen zu sagen, dass ich den atmega128 auf dem 
OctopusUSB benutze.

>>Ist das ein nagelneuer Mega128 oder hattest du den schon im Einsatz?
ist ein nagelneuer Octopus --> Mega128
MFG

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lisa schrieb:

>>>Ist das ein nagelneuer Mega128 oder hattest du den schon im Einsatz?
> ist ein nagelneuer Octopus --> Mega128

Im Shop steht:
Der Octopus ist aktuell noch nicht programmiert wenn er ausgeliefert wird.

Also wird es die M103C-Fuse sein.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> lisa schrieb:
>
>>>>Ist das ein nagelneuer Mega128 oder hattest du den schon im Einsatz?
>> ist ein nagelneuer Octopus --> Mega128
>
> Im Shop steht:
>
Der Octopus ist aktuell noch nicht programmiert wenn er
> ausgeliefert wird.
>
> Also wird es die M103C-Fuse sein.

Hmm.
Weiß nicht so recht.
er hat ein paar Funktionsaufrufe, ehe der Port C das 0xAA Muster 
einnimmt. Und das sieht er ja noch.

Auf jeden Fall: Mit einfacheren Tests anfangen. Code reduzieren. Um 
abzuklären ob die Interrupts kommen benötigt man keine Input-Queue etc.

Autor: lisa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Also wird es die M103C-Fuse sein.

M103C ein- oder ausgeschalten bringt keine Lösung.

So sind die Fuse bei mir eingestellt:
EXTENDED: FF
HIGH:FF
LOW:C3

Autor: lisa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok ich versuche es
danke an alle
MFG

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
>> Also wird es die M103C-Fuse sein.
>
> Hmm.
> Weiß nicht so recht.
> er hat ein paar Funktionsaufrufe, ehe der Port C das 0xAA Muster
> einnimmt. Und das sieht er ja noch.

Inlining? ;-)

Dem Shop nach müsste es auf jeden Fall ein "druckfrischer" M128 
(gewesen) sein, denn dort wird beschrieben, was vor der eigentlichen 
Verwendung noch zu erledigen ist, und dort steht auch "Fuses 
programmieren".

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.