www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit UART @ ATMega16


Autor: Matthias S. (bruteforce)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich baue seit einiger Zeit an einer kleinen Kiste die irgendwann mal das 
CLIP-Signal meiner Telefonanlage auswerten soll.
Ich benutze dazu einen ATMega16 mit dem CMX602B (hier im Forum gefunden 
bei suche nach "clip") und ein Dot-Matrix-Display.
Das Display läuft auch schon wunderbar. Nun stehe ich seit längerem vor 
einem Problem:
Der CMX hat ein internes 8-Bit Schieberegister. Wenn das voll ist, wird 
eine Leitung auf 0 gezogen und man kann die Bits seriell (durch Takt 
anlegen) rausbekommen. Ist ja einfach dachte ich. Als ich das 
ausprobiert habe, bekamm ich
1. viel zu wenig Zeichen (ich rechne mit ca. 50, es kamen aber nur 10 
oder so...) und
2. waren diese nicht lesbar. (Das Signal sollte mit einigen "U"s 
anfangen (10101010) und dann kommt nach ein paar steuerzeichen die 
Telefonnummer im ascii-code.)
Das habe ich dann erstmal auf fehler die ich beim programmieren gemacht 
habe geschoben. Um zu testen, ob überhaupt gescheite Daten ankommen, 
habe ich das interne register ausgeschaltet und die datenleitung (ist 
dann eine serielle 1200 baud Übertragung 1 Stoppbit, keine Parität) auf 
das UART des ATMegas gelegt. (zusätzlich noch über MAX232 auf den PC)
Auf dem PC war alles super. Ich konnte die Steuerzeichen im Hexeditor 
alle wunderbar lesen und auch die tel-nr wurde einwandfrei übertragen. 
Aber am ATMega kommt wieder nur müll an.
Ich habe mir dann ein Oszilloskop geliehen um mal das Signal anzusehen. 
Die Pegel liegen sauber bei 0/5V. Das einzige was mir aufgefallen ist, 
ist das die Bit-Zeit (kein plan ob man das so nennt :) Halt die Zeit, 
die ein Bit stabil anliegt) relativ stark schwankt (ca im Bereich 740µs 
bis 860µs, sollte eiggentlich auf 833µs sein) aber im Mittel, z.b. über 
10 Bit betrachtet nurnoch wenig Abweichung (8.32ms) vorhanden ist. Nun 
meine Frage:
Reagiert der ATMega so empfindlich auf schwankngen, oder bin ich einfach 
nur unfähig zu Programmieren? ;)

Hier der interressante Teil aus meinem Programm (enthalten, aber 
auskommentiert ist auch noch der Teil mit dem manuellen Austakten)
Timer0 macht ein bisschen PWM für die Hintergrundbeleuchtung des 
Displays (hab natürlich beim layouten verpennt die PWM-Engine des ATMega 
zu benutzen :)
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lcd.h"
#include "tools.h"
#include "CMX_ports.h"


static void avr_init(void);

uint8_t duty=0x00;
uint8_t blup=1;  //Backlight UP (false/true)

char lcd_data[2][20] ={{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}};
uint8_t pointer=0;


ISR (TIMER0_OVF_vect)
{
   //Backlight steuerung
}

ISR (TIMER0_COMP_vect)
{
   // noch mehr PWM-rummel... :)
}


//wird gerufen, wenn ein Anruf erkannt wird.
//der CMX wird aus dem SLEEP geholt.
ISR (INT0_vect)  // DET
{
  while (PIND & (1 << CMX_DET));
  PORTD &= ~(1<<CMX_ZP);  //CMX Aufwecken
  PORTD |= (1<<CMX_MODE); //ZP=0, MODE=1 -> FSK-Receiver
  
  //GICR |= (1<<INT1);
}

/*
ISR (INT1_vect)  // IRQN, low, wenn 8-Bit Schieberegister volgelaufen ist
{
  uint8_t idx;
  uint8_t zeile, spalte;
  delay(10);
  if (pointer >= 40)
  {
    pointer = 0;
  }
  zeile=pointer / 20;
  spalte = pointer % 20;
  pointer++;
  lcd_data[zeile][spalte]=0;
  //8 Bit über RXCK austakten, RXD enthät aktuelles Bit
  for (idx=0; idx < 8; idx++)
  {
    if (PIND & (1 << CMX_RXD))
      lcd_data[zeile][spalte] |= (1 << idx);
    PORTD |= (1 << CMX_RXCK);
    delay (10);
    PORTD &= ~(1 << CMX_RXCK);
    delay (10);
  }
} */


ISR (USART_RXC_vect)  //USART Zeichen empfangen
{  
  uint8_t zeile, spalte;

        // Fehler anzeigen
  if (UCSRA & (1<<FE))
    lcd_data[1][19]='E';
  if (UCSRA & (1<<DOR))
    lcd_data[1][19]='D';
        // Daten anzeigen
  if (pointer >= 39)
  {
    pointer = 0;
  }
  zeile=pointer / 20;
  spalte = pointer % 20;
  pointer++;
  lcd_data[zeile][spalte]=UDR;
}

int main(void)
{
  uint8_t l,s;
    avr_init();
  backlight_on();
  lcd_puts("CLIPPER v0.2");
  for (l=0; l<150; l++)
    delay(10000);
    for(;;)
    {
    for (l=0; l<2; l++)
    {
      lcd_gotoxy(0,l);
      for (s=0; s<20; s++)
      {
        lcd_putc(lcd_data[l][s]);
      }

    }
    delay (10);
    }
    
    return(0);
}



static void avr_init(void)
{
    lcd_init();
//Ports
    DDRC |= 0b00010000;
  DDRD = 0b11010000;
  PORTD =0b11111111;

//Timer
  TCCR0 &= 0b11111000;  //Stop Timer
  //TCCR0 |= 0b00000100;  //Timer0 clk/256

    TIMSK |= (1<<OCIE0) | (1<<TOIE0);  // Timer 0 Output Compare Int 
                     // und Timer0 Overflow Int setzen

//Externe Interrupts
  MCUCR |= (1<<ISC00) | (1<<ISC01); // rising edge on INT0 -> interrupt
//  MCUCR &= ~(1<<ISC10);    // falling edge on INT1
//  MCUCR |= (1<<ISC11);    //    ^^
  
  GICR |= (1<<INT0);    // INT0 aktivieren

//USART
  UBRRH = (unsigned char)(MYUBRR >> 8);  // Baud Rate Timer Hight Byte
  UBRRL = (unsigned char)MYUBRR;      // Low Byte

  UCSRB |= (1<<RXCIE) | (1<<RXEN); // Receiver Interrupt und Receiver an


  sei();
    return;
}
Die tools.h enthält auch die Definiton der Baud-Rate:
#ifndef __TOOLS_H__
#define __TOOLS_H__

#define XTAL 12000000
#define delay(us)  _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 )

#define BAUD 1200
#define MYUBRR (XTAL/16/BAUD-1)

extern inline void _delayFourCycles(unsigned int __count);

#endif
Ich hoffe ihr könnt mir ein paar Tipps geben. :)

Danke im Voraus!
Matthias

Autor: Matthias S. (bruteforce)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal.
Mir ist noch was aufegefallen. Ich habe mein Programm so modifiziert, 
das die FrameErrors und Data OverRun Errors gezählt werden. Dabei ist 
mir aufgefallen, das es zu ein paar Data OverRun Errors kommt. Aber nur 
so 1-2 während der übertragung der Daten. Wie kann es überhaupt zu so 
einem Fehler kommen, wenn das URD direkt im Interrupt gelesen wird? So 
schnell kann doch noch kein neues Byte angekommen sein, oder?
Ich hoffe mir ist noch zu Helfen ;)

Matthias

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

#define MYUBRR (XTAL/16/BAUD-1) falsch
#define MYUBRR (XTAL/16*BAUD-1) richtig

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder
#define MYUBRR XTAL/((16*BAUD)-1)

Autor: Matthias S. (bruteforce)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Danke Für deine Antwort :)

Aber die Definition von MYUBBR steht doch so wie ich sie hab im 
Datenblatt (S. 151 im C-Example)
Und das stimmt auch mit der Formel UBBR=(Fosc/(16*BAUD))-1 (weiter oben 
im Datenblatt) überein, wenn mich meine Mathe-Kenntnisse jetzt nicht im 
Stich lassen. Oder habe ich da was Falsch verstanden?

Matthias

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.