mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [AVR] Controller reagiert auf falsche Zahl.


Autor: Mike Strangelove (drseltsam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich habe hier ein kleines Gerät, was auf das Senden einer bestimmten 
Zahl über USB mittels einem FT245R eine Reaktion, das Senden eines 
Triggerpulses, reagieren soll.
Ich habe es so programmiert, dass er auf 128 reagiert. Nur dummerweise 
reagiert er stattdessen auf alle Zahlen zwischen 64 und 127 ! Was zur 
Hölle hab ich denn da verbockt? Ist mein erstes GCC Programm...
//Program to run the USB-Trigger box

#include <avr/io.h>          

int main (void) {            

unsigned char stat = 0;
unsigned char dat = 0;

DDRD = 0x00; //all input (Byte from FT245R)
DDRB = 0b01000010; //only PB1 and PB6 are output
DDRC = 0x03; //both BNC outputs enabled

PORTB |= (1<<PB1); //read strobe to high 
PORTB &= ~(1<<PB6);   

   while(1) {                
     
  if(PINB &= (1<<PINB0) && stat==1) { //falling edge

    PORTB &= ~(1<<PB1);
    dat=5*5; //waste some time

    dat= ~PIND; // read PORTD
    
    PORTB |= (1<<PB1); //reset

    if(dat==128) { //trigger condition
      PORTC |= (1<<PC0); //trigger pulse
      PORTB |= (1<<PB6); //light LED      

    }
    else PORTB &= ~(1<<PB6); //darken 
  
  };
  stat=PINB0; //save last read status to compare in next cycle
  PORTC &= ~(1<<PC0);; //reset trigger channel

   
   } 
 
   
   return 0;
}

Autor: Albert ... (albert-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast keine Pullups für die Output Pins bei PORTB aktiviert.
PORTB |= ~((1<<PB0) | (1<<PB6)); //activate all Pullups except PB1 and PB6
Dasselbe für PORTD. Oder hat es im FT245 an den Ausgängen welche?

Autor: Mike Strangelove (drseltsam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brauche ich da Pullups? Das sind doch Output Pins vom FT245, die müssten 
doch einen definierten State haben. Wenn nix ankommt, sind sie 
jedenfalls high.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  if(PINB &= (1<<PINB0) && stat==1) { //falling edge

Da ist ein = zuviel drin.

Autor: Albert ... (albert-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und zwar das "=" bei "&=". Du willst ja eine UND-Verknüpfung und keine 
zuweisung

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  stat=PINB0; //save last read status to compare in next cycle

Der ist auch gut. PINB0 ist eine Konstante;)

Autor: Mike Strangelove (drseltsam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich habe etwas Fortschritt gemacht. Mit einem Bascom Programm geht 
es, aber nicht in GCC. Hier ist der neue Code. Das Problem ist, er 
durchläuft die if-Schleife nach der fallenden Flanke problemlos. Bei der 
zweiten if-Abfrage if(dat==123) spinnt er rum. Wenn ich auf dat==0 
teste, geht er bei jeder gesendeten Zahl an. Egal welche. Teste ich aber 
auf eine von 0 verschiedene Zahl funktioniert es nicht mehr. Mit Bascom 
erkennt er die Zahlen aber problemlos. Die Bascom Variante ist ganz 
unten.


//Program to run the USB-Trigger box

#include <avr/io.h>          

int main (void) {            

unsigned char dat = 0;

DDRD = 0x00; //all input (Byte from FT245R)
DDRB = 0b01000010; //only PB1 and PB6 are output
DDRC = 0x03; //both BNC outputs enabled

PORTB |= (1<<PB1); //read strobe to high 
PORTB &= ~(1<<PB6);   //LED off

   while(1) {  
                 
  if(!(PINB & (1<<PB0))) { //falling edge
    
    
    PORTB &= ~(1<<PB1); //read low
    

    dat=PIND; // read PORTD
    
    PORTB |= (1<<PB1); //reset

    if(dat==123) { //trigger condition HIER IST PROBLEM
      PORTC |= (1<<PC0); //trigger pulse
      PORTB |= (1<<PB6); //light LED      

    }
    else {
    
    PORTB &= ~(1<<PB6); //darken 
    }
  
  }

  PORTC &= ~(1<<PC0); //reset trigger channel

     
   } 
 
   
   return 0;
}
Do

Pb = Pinb.0


If Pb = 0 Then                                              'falling edge


  Portb.1 = 0                                               'shift data out

  Dat = 5 * 5                                               'waste some time

  Dat = Pind

  Portb.1 = 1

  If Dat = 123 Then

  Portb.6 = 1
  Else
  Portb.6 = 0

  End If
                                                 'reset


End If

Loop
End

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

Bewertung
0 lesenswert
nicht lesenswert
Mike Strangelove schrieb:

Du solltest noch beschreiben, was an welchem Pin hängt und wie die Logik 
der einzelnen Pins lautet. Wenn du einen Ausganbepin auf High/Low setzt, 
dann bewirkt das ja etwas. Nur was?

> #include <avr/io.h>
>
> int main (void) {
>
> unsigned char dat = 0;
>
> DDRD = 0x00; //all input (Byte from FT245R)
> DDRB = 0b01000010; //only PB1 and PB6 are output
> DDRC = 0x03; //both BNC outputs enabled
>
> PORTB |= (1<<PB1); //read strobe to high
> PORTB &= ~(1<<PB6);   //LED off
>
>    while(1) {
>
>   if(!(PINB & (1<<PB0))) { //falling edge

Das ist kein Flankendetektor.
Wenn der Körper deines if schneller abgearbeitet wird, als das externe 
Gerät Zeit braucht um den Pin wieder auf high zu ziehen, dann wertest du 
xxxx ein zweites mal aus

>
>     PORTB &= ~(1<<PB1); //read low

Startet das irgendeinen Vorgang?
>
>
>     dat=PIND; // read PORTD

Woher weißt du, dass jetzt die Daten schon am PIND abholbereit 
vorliegen?

>
>     PORTB |= (1<<PB1); //reset
>
>     if(dat==123) { //trigger condition HIER IST PROBLEM

ziemlich sicher ist hier nicht das Problem.
Du siehst an dieser Stelle die Symptome, aber das bedeutet nicht das 
hier das Problem liegt. Das wird wohl weiter oben schon sein, nur ohne 
Datenblatt mit einem Timingdiagramm kann ich nicht sagen, ob du 
Timingvorschriften verletzt hast, bzw. wie eigentlich das Zusammenspiel 
der Pins funktionieren soll

(Und noch was: So was

    dat=5*5; //waste some time

schmeisst dir jeder noch so grindige C Compiler raus. Wenn du ein wenig 
warten willst, dann benutze die _delay_xx Funktionen. Dafür sind sie 
da.)

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mike Strangelove schrieb:
>     PORTB &= ~(1<<PB1); //read low
>     dat=PIND; // read PORTD

Das kannst Du nicht machen.  Damit ein Wert gültig eingelesen wird, muss 
er zwischen einem halben und eineinhalb AVR-Takte vor dem Einlesen 
angelegen haben.  Du setzt aber Deinen Read-Puls low im ersten Takt und 
liest bereits gleich danach im zweiten ein.  Am einfachsten schreibst Du 
die dat=PIND - Zeile zweimal hintereinander hin, dann sollte es passen.

Ansonsten ist der FT245R so schnell, dass ich die anderen Bedenken nicht 
teile.  Auch ist es nicht notwendig, eine RXF-Flanke zu erkennen; dort 
ist der Kommentar falsch, nicht die Aktion.

Du hättest es uns allen viel leichter gemacht, wenn Du z.B. statt PB0 
ein RXF hingeschrieben (und natürlich vorher #define'd) hättest, also 
die Hardware-Bitnamen verwendet hättest.  Auch ist Dein Quellcode 
eingerückt wie Kraut und Rüben, statt die Blockstruktur erkennbar zu 
machen.

Autor: John Doe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

VIelen Dank für Deine Hilfe!


> Du solltest noch beschreiben, was an welchem Pin hängt und wie die Logik
> der einzelnen Pins lautet.

An PB6 hängt eine LED die bei 1 angeht
An PB0 kommt eine fallende Flanke wenn Daten abhlbereit sind
An PB1 muss ich eine fallende Flanke setzen um die Daten an PIND 8 bit 
breit senden zu lassen. Wenn PB1 wieder high geht, wird der Ausgang 
undefiniert und PB0 bekommt wieder high-Pegel vom FT245.


>>   if(!(PINB & (1<<PB0))) { //falling edge
>
> Das ist kein Flankendetektor.
> Wenn der Körper deines if schneller abgearbeitet wird, als das externe
> Gerät Zeit braucht um den Pin wieder auf high zu ziehen, dann wertest du
> xxxx ein zweites mal aus

Ich hatte erst einen Flankendetektor, hab den aber rausgenommen, da mit 
PORTB |= (1<<PB1) der FT245 schnell wieder high zieht, bevor der ganze 
Kram einmal durch ist.

>>     PORTB &= ~(1<<PB1); //read low
>
> Startet das irgendeinen Vorgang?

Das schiebt das angekommene Byte an den 8-bit Port des FT245 der mit 
PIND verbunden ist.

>>     dat=PIND; // read PORTD
>
> Woher weißt du, dass jetzt die Daten schon am PIND abholbereit
> vorliegen?

Das ist genau der Knackpunkt. Im Datenblatt stehen 20 ns, der MC läuft 
mit 8 Mhz. Ich habe da noch eine sinnlose Multiplikation mit 
reingepackt, um das Problem zu umgehen, hat aber nix genützt.

>>     PORTB |= (1<<PB1); //reset
>>
>>     if(dat==123) { //trigger condition HIER IST PROBLEM
>
> ziemlich sicher ist hier nicht das Problem.
> Du siehst an dieser Stelle die Symptome, aber das bedeutet nicht das
> hier das Problem liegt. Das wird wohl weiter oben schon sein, nur ohne
> Datenblatt mit einem Timingdiagramm kann ich nicht sagen, ob du
> Timingvorschriften verletzt hast, bzw. wie eigentlich das Zusammenspiel
> der Pins funktionieren soll

Das ist möglich. Aber eben dieser Loop wird nicht korrekt abgearbeitet. 
Entweder die Daten kommen nicht richtig zu PIND rein, oder da habe ich 
den falschen Operator benutzt etc...

>
> (Und noch was: So was
>
>     dat=5*5; //waste some time
>
> schmeisst dir jeder noch so grindige C Compiler raus. Wenn du ein wenig
> warten willst, dann benutze die _delay_xx Funktionen. Dafür sind sie
> da.)

Hmm, das ist ein sehr guter Punkt. Danke, ich dachte der macht das 
einfach mit und erzeugt einen Delay ohne dass ich _delay einbinden muss.
Angenommen Bascom schmeisst das nicht raus, könnte in diesem 
Zeitunterschied das Problem liegen.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
John Doe schrieb:
>> Woher weißt du, dass jetzt die Daten schon am PIND abholbereit
>> vorliegen?
>
> Das ist genau der Knackpunkt. Im Datenblatt stehen 20 ns,

Nur zur Verdeutlichung, wie man Datenblätter liest:  Dort stehen zwei 
Werte: min. 20 ns und max. 50 ns.  Für Dich sind natürlich die 50 ns 
maßgebend (denn erst dann hast Du garantiert Daten anliegen) und die 20 
kannst Du vergessen.

Im vorliegenden Fall spielt der Unterschied nur deshalb keine Rolle, 
weil die Zeit des AVR-Input-Synchronizers sowieso viel größer ist.

Autor: Mike Strangelove (drseltsam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jupp, das war's. Die Zahl war noch nicht da, als der MC schon lesen 
wollte. Kleine Pause erledigt das Problem. Danke Euch!

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.