www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT90CAN128 - UART Interupt Problem


Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @ all,

ich habe folgendes Problem. Ich habe das Atmel DVK90CAN1 
Entwicklungsboard mit dem AT90CAN128 µC und mein USART1 Empfängt nichts.
Der Kontroller besitzt zwei USART aber um LIN Botschaften zu 
senden/empfangen muss der 2 USART (USART1) angesteuert werden, da dieser 
an dem LIN Transceiver angeschlossen ist (RxLIN-->PD2, TxLIN-->PD3, 
NotSleep-->PD7).
Ich kann soweit auch wunderbar Nachrichten vom Board aus LIN Nachrichten 
versenden (USART1 funktioniert in diese Richtung) aber ich kann nichts 
empfangen.
Empfangen werden die Nachrichten über einen Interupt ISR(USART1_RX_vect) 
aber hier kommt nichts an... warum ??

Stimmen meine Einstellungen und wofür genau ist SREG, habe ich noch 
nicht ganz kapiert!

Meine Port-Einstellungen sehen wie folgt aus:
DDRE = 0x0B;  // Pins für Taster auf Port E als Eingang=0 definiert
  PORTE |= (1<<PE7); //Pullup für Taster aktivieren
  
  // Port A (0101 0101)
  DDRA = 0xFF;  // Alle Pins auf Port A (LEDs) als Ausgang definiert
  PORTA |= (1<<PA0)|(1<<PA2)|(1<<PA4)|(1<<PA6); // Einzelne LEDs anschalten

  uart_init(); //Schnittstelle inistiallisiern

// Port D0 als Ausgang für ????  <-- WOFÜR ????????
  // Port D3 als Ausgang für LIN TX
  // Port D7 als Ausgang für NOTSleepLIN <-- LIN Aktivieren
DDRD |= (1<<DDD0) | (1<<DDD3) | (1<<DDD7); // DDR = Data Direction Register
  
  // Port D2 als Eingang für LIN RX
  DDRD &= ~(1<<DDD2);


  // Ports auf HIGH   Pullup
  //      ????      RxLIN    TxLIN     NOTSleepLIN
  PORTD |= (1<<PD0) | (1<<PD2) | (1<<PD3) | (1<<PD7);
      
  SREG |= 0xE0;  // Das "Status Register" aktiviert die externen ISR 
          // für RX,TX,UDR (siehe Seite 197)

sei();  // Globales Interrrupt Flag setzten


Hier noch die UART Init:
void uart_init()
{
  /* set baud rate */
  UBRRH = UBRRVAL >> 8;
  UBRRL = UBRRVAL & 0xff;
  /* set frame format: 8 bit, no parity, 1 bit */
  UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
  
  // Receiver und Transmitter einschalten UND (Transmitt) und Receive Interrupts einschalten
//  UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE); // | (1 << TXCIE);
  
  /* enable serial receiver and transmitter */
  #if !USE_SLEEP
    UCSRB = (1 << RXEN) | (1 << TXEN);
  #else
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
  #endif
}

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

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:

> Stimmen meine Einstellungen und wofür genau ist SREG, habe ich noch
> nicht ganz kapiert!

Das SREG Register geht dich nichts an. Das lässt du in Ruhe!

Wenn du die INterrupts global aktivieren willst, dann rufst du
    sei();
auf, und wenn du die Interrupts global deaktivieren willst, dann rufst 
du
    cli();
auf.


>   SREG |= 0xE0;  // Das "Status Register" aktiviert die externen ISR
>           // für RX,TX,UDR (siehe Seite 197)

Lass das SREG in Ruhe!

  #if !USE_SLEEP
    UCSRB = (1 << RXEN) | (1 << TXEN);
  #else
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
  #endif
Hast du ein #define für USE_SLEEP?

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kalr,

danke für die Antwort!

Ich habe das SREG jetzt auskommentiert aber es hat sich noch immer 
nichts verändert.
Ein DEFINE für USE_SLEEP habe ich (#define USE_SLEEP 1).
ich benutze die UART Lib von Roland Riegel.

Gruß Andreas

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch meine komplette UART.c
Ganz am Ende ist das UART1_Interrupt deklariert aber es wird nicht 
ausgeführt bei Empfang auf dem LIN oder beim Senden mit HTerm
/*
 * Copyright (c) 2006-2009 by Roland Riegel <feedback@roland-riegel.de>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/sfr_defs.h>
#include <avr/sleep.h>

#include "uart.h"
#include "globals.h"

/* some mcus have multiple uarts */
#ifdef UDR1
#define UBRRH UBRR1H
#define UBRRL UBRR1L
#define UDR UDR1

#define UCSRA UCSR1A
//#define UDRE UDRE1


#define UCSRB UCSR1B

#define UCSRC UCSR1C
#define URSEL

#define UCSRC_SELECT 0
#else
#define UCSRC_SELECT (1 << URSEL)
#endif

#ifndef USART_RXC_vect

#if defined(UART1_RX_vect)
#define USART_RXC_vect UART1_RX_vect

#elif defined(UART_RX_vect)
#define USART_RXC_vect UART1_RX_vect

#elif defined(USART1_RX_vect)
#define USART_RXC_vect USART1_RX_vect

#elif defined(USART_RX_vect)
#define USART_RXC_vect USART1_RX_vect

#elif defined(USART1_RXC_vect)
#define USART_RXC_vect USART1_RXC_vect

#elif defined(USART_RXC_vect)
#define USART_RXC_vect USART1_RXC_vect
#else
#error "Uart receive complete interrupt not defined!"
#endif
#endif

#define BAUD 19200UL  // Default 57600UL
#define UBRRVAL (F_CPU/(BAUD*16)-1)
#define USE_SLEEP 1

void uart_init()
{
  // Setze Baudrate
  UBRRH = UBRRVAL >> 8;
  UBRRL = UBRRVAL & 0xFF;
    
  // set frame format: 8 bit, no parity, 1 bit
  UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);

  // Receiver und Transmitter einschalten UND (Transmitt) und Receive Interrupts einschalten
//  UCSRB = (1 << RXEN) | (1 << TXEN);// | (1 << RXCIE); // | (1 << TXCIE);
  
  // enable serial receiver and transmitter
  #if !USE_SLEEP
    UCSRB = (1 << RXEN) | (1 << TXEN);
  #else
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
  #endif

}


void uart_deak()
{
  //UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
  UCSRA=0x00;
  UCSRB=0x00;
  UCSRC=0x00;
}

void uart_putc(uint8_t c)
{
  if (c == '\n')
    uart_putc('\r');

  /* wait until transmit buffer is empty */
  while (!(UCSR1A & (1 << UDRE1)))
    ;

  /* send next byte */
  UDR = c;
}

void uart_putc_hex(uint8_t b)
{
  /* upper nibble */
  if ((b >> 4) < 0x0a)
    uart_putc((b >> 4) + '0');
  else
    uart_putc((b >> 4) - 0x0a + 'a');

  /* lower nibble */
  if ((b & 0x0f) < 0x0a)
    uart_putc((b & 0x0f) + '0');
  else
    uart_putc((b & 0x0f) - 0x0a + 'a');
}

void uart_putw_hex(uint16_t w)
{
  uart_putc_hex((uint8_t) (w >> 8));
  uart_putc_hex((uint8_t) (w & 0xff));
}

void uart_putdw_hex(uint32_t dw)
{
  uart_putw_hex((uint16_t) (dw >> 16));
  uart_putw_hex((uint16_t) (dw & 0xffff));
}

void uart_putw_dec(uint16_t w)
{
  uint16_t num = 10000;
  uint8_t started = 0;

  while (num > 0)
  {
    uint8_t b = w / num;
    if (b > 0 || started || num == 1)
    {
      uart_putc('0' + b);
      started = 1;
    }
    w -= b * num;

    num /= 10;
  }
}

void uart_putdw_dec(uint32_t dw)
{
  uint32_t num = 1000000000;
  uint8_t started = 0;

  while (num > 0)
  {
    uint8_t b = dw / num;
    if (b > 0 || started || num == 1)
    {
      uart_putc('0' + b);
      started = 1;
    }
    dw -= b * num;

    num /= 10;
  }
}

void uart_puts(const char* str)
{
  while (*str)
    uart_putc(*str++);
}

void uart_puts_p(PGM_P str)
{
  while (1)
  {
    uint8_t b = pgm_read_byte_near(str++);
    if (!b)
      break;

    uart_putc(b);
  }
}

uint8_t uart_getc()
{
  /* wait until receive buffer is full */
#if USE_SLEEP
  uint8_t sreg = SREG;
  sei();

  while (!(UCSRA & (1 << RXC)))
  //  sleep_mode();

  SREG = sreg;
#else
  while(!(UCSRA & (1 << RXC)));
#endif

  uint8_t b = UDR;
  if (b == '\r')
    b = '\n';

  return b;
}

void uart_gets(char* Buffer, uint8_t MaxLen)
{
  uint8_t NextChar;
  uint8_t StringLen = 0;

  NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen

  // Sammle solange Zeichen, bis:
  // * entweder das String Ende Zeichen kam
  // * oder das aufnehmende Array voll ist
  while (NextChar != '\n' && StringLen < MaxLen - 1)
  {
    *Buffer++ = NextChar;
    StringLen++;
    NextChar = uart_getc();
  }

  // Noch ein '\0' anhängen um einen Standard
  // C-String daraus zu machen
  *Buffer = '\0';
}

//EMPTY_INTERRUPT(USART_RXC_vect)

ISR (USART1_RXC_vect)   // UART1
{
   PORTA = ~PORTA;
//   sync_flag=1;
//   UCSRA &= ~(1 << RXC);
   
   //U8 u = UDR;
}


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

Bewertung
0 lesenswert
nicht lesenswert
Das hier
#if USE_SLEEP
  uint8_t sreg = SREG;
  sei();

  while (!(UCSRA & (1 << RXC)))
  //  sleep_mode();

  SREG = sreg;

ergibt keinen Sinn. Hast du den Aufruf von sleep_mode() auskommentiert 
und damit die Logik verändert?

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl,
ich habe den Fehler gefunden.... und zwar waren die Jumper auf dem Board 
falsch gesteckt.
Ich dachte ich kann gleichzeitig über den UART empfagnen und per SUB-D 
und HTerm schauen was dort ankommt, geht aber nicht... habe ich Jumper 
umgesetzt und siehe da... ich kann jetzt auch empfangen!!

Danke für die Hilfe!!!!!!!!!

Gruß Andi

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.