Forum: Mikrocontroller und Digitale Elektronik Baudrate erkennen C


von Michael B. (minimichi)


Lesenswert?

Guten tag,
Ich bin neu hier und dieses Forum hat mir schon sehr geholfen.
Nun komm ich allerdings ohne einen eigenen Beitrag zu erstellen nicht 
weiter.


Ich habe folgendes Problem mit meiner momentanen Arbeit.
Ich bin dabei für ein Programm eine Funktion zu schreiben, die es mir 
ermöglicht die Baudrate eines Senders zu ermitteln.
Ich habe hierzu eine ISR die bei jedem logischen wechsel auslöst und 
dies weitergibt. Mit einem Timer der im Hintergrund läuft, wird somit 
zwischen den logischen wechsel die "Ticks" aus dem 16bit Counter 
Register entnommen und in ein Array geschrieben von dem aus ich dann die 
Zeit berechnen will.
Mein Problem ist, dass in dem Array was anderes steht, als eigentlich 
soll.

hier mein Code:
1
//define
2
#define F_CPU 18432000        //set cpu clock for delay calculation in delay.h
3
4
//including header files
5
#include <avr/io.h>          //standard i/o
6
#include <util/delay.h>        //delay header file
7
#include <avr/interrupt.h>      //interrupt header file to enable ISR
8
  
9
char times_arr[25];          //for measured times
10
int isrtick = 0;          //shows if the INT0ISR has ticked
11
int waitfull = 0;          //variable for waiting if times_arr full
12
int timecount = 0;          //variable for counting times in times_arr
13
    
14
int main(void)
15
{  
16
  
17
  //EICRA – External Interrupt Control Register A
18
  EICRA |= (1 << ISC00);    //logical change on INT0 generates an interrupt request  (falling/rising edge)
19
  //EIMSK – External Interrupt Mask Register
20
  EIMSK |= (1 << INT0);      //external Interrupt Request 0 Enable
21
  
22
  sei();              //enables global interrupts
23
  
24
25
  while(!waitfull)          //mainloop1: inside this loop until enough times are collected
26
  {
27
    while(isrtick)          //wait until ISR INT0 sending a 1
28
    {
29
      isrtick = 0;        //reseting value from ISR INT0
30
      if (timecount == 0)      //if its the first logical input from ISR INT0
31
      {
32
        TCCR1B |= (1 << CS10 );  //Start Timer1 using crystal frequency (18,432MHz)
33
        timecount++;      //set the counter to 1, so times can be saved in the array
34
        TCNT1 = 0;        //set timer value to 0
35
      }
36
      else
37
      {
38
        times_arr[timecount-1] = TCNT1;  //saves a time into the array position of timecount
39
        TCNT1 = 0;        //reset timer value to 0
40
        if (timecount >= 24)  //if enough times are collected
41
        {
42
          waitfull = 1;    //closing the mainloop1
43
          timecount = 0;    //resetting the counter
44
        }
45
        else          //if we need more times
46
        {
47
          timecount++;    //adding 1 to the counter
48
        }
49
      }
50
    }
51
    
52
  }
53
  waitfull = 0;            //resetting the variable for mainloop1  
54
  
55
}
56
  
57
  
58
ISR (INT0_vect)
59
{
60
  isrtick = 1;
61
}
Mein Controller läuft mit einer Frequenz von 18,432MHz

Wenn ich das ganze in der Theorie durch gehe sollte ich bei einer 
Baudrate von 9600, zwischen zwei logischen wechsel, eine Tickanzahl des 
Timers von 1929 haben. In meinem Array steht allerdings ca 100 bis 130.

Bei meiner Frequenz, Zeit pro Tick in mikrosekunden
   (1*10E6)/18432000  =  0,054

Zeit pro bit bei 9600Baud in mikrosekunden
   (1/9600)*10E6  =  104

Ticks des Timers zwischen dem kürzesten logischen Wechsel bei 9600Baud
   104/0,054   =   1929 Ticks


Ich bitte dringend um Hilfe, da ich einfach nicht weiter komme.
Danke im voraus
Grüße: Michael

von Karl H. (kbuchegg)


Lesenswert?

Michael Bennebach schrieb:

> Timers von 1929 haben. In meinem Array steht allerdings ca 100 bis 130.


Du hast 100.
Du solltest haben 1929

das ist ungefähr ein Faktor 18


Deine µC-Taktfrequenz sollte 18Mhz sein.

Hmmm.
Ich behaupte mal, dein µC läuft mit 1Mhz und nicht mit 18Mhz´.
Und schon stimmt alles was du gemessen hast.
Nur die 18.xxMhz stimmen nicht.

von Andreas B. (bitverdreher)


Lesenswert?

Sicher, daß int ein 16 bit Datentyp ist? ;-)

von Karl H. (kbuchegg)


Lesenswert?

> int isrtick = 0;          //shows if the INT0ISR has ticked

sollte sein

volatile uint8_t isrtick = 0;


auf einem µC wie den AVR willst du int nicht verwenden wenn es nicht 
sein muss. Für so Dinge wie Flags benutzt du lieber 8-Bit Variablen. Die 
können von sich aus atomar gelesen werden, ohne dass du Vorkehrungen 
treffen musst.

Aber kontrollier erst mal die Fuses. Deine Zahlen deuten ganz klar 
darauf hin, dass dein µC mit 1Mhz läuft.

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Lesenswert?

>In meinem Array steht allerdings ca 100 bis 130.
naja, in einem char array kann nur -128 bis +127 drinstehen. Schau mal 
ob's da nicht overflowed.

Grüsse

von Karl H. (kbuchegg)


Lesenswert?

Gebhard Raich schrieb:
>>In meinem Array steht allerdings ca 100 bis 130.
> naja, in einem char array kann nur -128 bis +127 drinstehen. Schau mal
> ob's da nicht overflowed.

Autsch.
Das hab ich übersehen. Hab mich auf die Zahlen gestürzt und die haben 
einfach zu gut gepasst.

von Uwe (Gast)


Lesenswert?

> wird somit zwischen den logischen wechsel
Welche logischen wechsel ?
Wenn du  eine 0x00 sendest
Kommt nen Startbit dann die 8 Datenbits danach das Stopbit.

Sieht dann so aus
S=Startbit
D=Daten
P=Stopbit

              SDDDDDDDDP
000000000000001000000001000000000000

Wenn de 0x55 sendest :
              SDDDDDDDDP
000000000000001010101011000000000000

von Uwe (Gast)


Lesenswert?

Was sendest du denn nu ?

von Michael B. (minimichi)


Lesenswert?

Wow super, da geht man kurz weg und schon sind so viele Hilfsbereite zur 
Stelle. Danke an ALLE!


Karl Heinz Buchegger schrieb:
> Ich behaupte mal, dein µC läuft mit 1Mhz und nicht mit 18Mhz´.
> Und schon stimmt alles was du gemessen hast.
> Nur die 18.xxMhz stimmen nicht.

das hatte ich schon überprüft, ich bin bei meiner Frequenz von 
18,432Mhz, sonst würden andere Funktionen auch nicht klappen :D


Uwe schrieb:
> Was sendest du denn nu ?

Ich habe keinen Einfluss was gesendet wird, ich nehmen einfach die 
Zeiten zwischen den ersten 24 logischen Wechel (von 1 auf 0 und 
umgekehrt).


Gebhard Raich schrieb:
>>In meinem Array steht allerdings ca 100 bis 130.
> naja, in einem char array kann nur -128 bis +127 drinstehen. Schau mal
> ob's da nicht overflowed.

Jap und genau mit dem hab ich mir wieder ins eigene Bein geschossen ^^, 
es sind halt die kleinen dinge, die mich immer wieder zur Verzweiflung 
bringen....
Ich danke die vielmals, denn dass war die Lösung meines Problems.


Nochmals vielen Dank an alle.
Gruß Michael

von Dietrich L. (dietrichl)


Lesenswert?

Uwe schrieb:
> Wenn de 0x55 sendest :
>               SDDDDDDDDP
> 000000000000001010101011000000000000
  111111111111110101010101111111111111

Das wäre meine Version, siehe: 
http://de.wikipedia.org/wiki/UART#Funktion

Gruß Dietrich

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.