Forum: Mikrocontroller und Digitale Elektronik SPI-Problem nach ADC-Wandlung


von Benjamin (Gast)


Lesenswert?

Hallo!!!

Ich bin gerade daran eine längere AD-Wandlung zu machen welche gefolgt 
wird von einer SPI-Übertragung zu einem anderen Controller.
Das ganze wird von einer 2 Werte AD-Wandlung nochmal gefolgt.
Wenn die Endlosschleife, in der diese Programmabfolge steht, zum 2. mal 
durchlaufen wird sendet die Spi nicht mehr.
Ich habe daraufhin mehrere Versuche gemacht, nachgelesen usw. und bin 
dann durch probieren darauf gekommen, wenn die AD-Wandlung nach der 
SPI-Übertragung weggelassen wird läuft es.
Kann mir da jemand weiterhelfen?
Ich weiss echt nicht an was das noch liegen könnte.

MfG

Benjamin

von Joerg X. (Gast)


Lesenswert?

< beliebigen Glaskugelwitz einfügen >

wie wär's mit ein bischen mehr Infomationen für die, die dir helfen 
sollen/könnten ?
z.B.:
welche(r) Controller/Programmiersprache/Compiler/ADC/µC-Takt/etc?
Ich hab da scheinbar mehr Fragen als du ;)

von Benjamin (Gast)


Lesenswert?

Sorry verwende einen ATmega8l , programmiere ihn in C (AVR Studio) und 
er hat einen CPU Takt von 3,6864 MHz.
Ist ein komisches Problem, da der erste Durchlauf funtioniert und beim 
2. Durchlauf bleibt er stehen, s.o.

MfG

Benjamin

von Joerg X. (Gast)


Lesenswert?

- gibtst du auch ein bischen Code zum anschauen heraus?
- hast du das Problem mit der Hardware oder dem Simulator (der ja seine 
eigenen Fehler hat) ?
Denn, wenn das ein ganz gewöhnliches Problem wäre, hättest du doch 
bestimmt mit der Foren-suche eine Lösung gefunden ;)

von Benjamin (Gast)


Lesenswert?

Klar gerne, das hilft sicher dem Verständniss :-)
Ich habe die Probleme mit der Hardware.
Die Programmsequenz läuft einmal durch beim 2. mal bleibt er bei der 
SPI-Übertragung stehen (SPI_MasterTramsmitc).
Auf der anderen Seite befindet siche ein anderer Controller, gleichen 
Typs, welcher auch eine Messaufgabe hat und über UART an einen Rechner 
verbunden ist.
Das Ziel wäre nun beide unabhängig voneinander betreiben zu können und 
in der Ruhephase (PinB1 nicht) die Werte eimal über die SPI an den 2. 
Controller zu übergeben und dann gemeinsam mit den anderen Werten an die 
Schnittstelle geben.
Controller 2 mit UART funtioniert einwandfrei und die Übertragung der 
Werte über die SPI an Controller 2 auch (allerdings nur beim ersten 
mal).
Hier nun der wichtigste Sourcecode-Ausschnitt:


void SPI_MasterInit(void)

{
/*Set MOSI and SCK output, all others input */
DDRB |= (1<<PINB3)|(1<<PINB5);
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);

}

void SPI_MasterTransmitc(uint8_t Data)
{
/* Start transmission */
SPDR = Data;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)));
}

uint16_t ReadChannel(uint8_t mux)
{
uint16_t result = 0; //Initialisieren wichtig, da lokale Variablen nicht 
automatisch initialisiert wird

ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler 
setzen auf 8 (1) und ADC aktivieren (1)
ADMUX = mux; // Kanal waehlen

//ADMUX = ADMUX | (1<<REFS1) | (1<<REFS0);

ADMUX |= (0<<REFS1) | (1<<REFS0); // Spannungsversorgung als 
Referenzspannung nutzen nach Aktivieren des ADC wird ein "Dummy-Readout" 
empfohlen,
//man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen 
zu lassen" */

ADCSRA |= (1<<ADSC); // eine ADC-Wandlung

while ( ADCSRA & (1<<ADSC) )
{
; // auf Abschluss der Konvertierung warten
}

ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) )
{
; // auf Abschluss der Konvertierung warten
}
result=ADCW;
return result;
}

int main(void)
{
DDRC=0x00;
DDRB=0xff;
DDRD=0xff;
PORTB = (0<<PB0);
uart_init(tx, rx);
TIFR = (1<<TOV1);
TIMSK = (1<<TOIE1);
TCNT1H=0x1F;
TCNT1L=0;
TCNT2=0;
TCCR1B = (1<<ICES1);
DDRB = (1<<PINB2);
SPI_MasterInit ();
sei();
while(1)
{

  while ((PINB & (1<<PINB1)))
  {
    if (flag_timer)
    {
      TCCR1B |= (0<<CS10)|(0<<CS11)|(0<<CS12);
      TCNT1H=0;
      TCNT1L=0;
      TCNT2 = 0;
      TCCR1B|=(1<<CS10)|(1<<CS11)|(0<<CS12);//Startet Timer 1 (16 Bit)
      for(x=0; x<40000; x++);
      if(!(PINB & (1<<PINB1)))
        break;
      flag_timer=0;
      flag_ausg = 1;
      flag_kurve1 = 1;

    }

    if (flag_kurve1)
    {
      adca0=adc0;
      adc0 = ReadChannel(0);
      if (ms0>adc0)
      {
        if (adc0>adca0)
        {
        }
        else
        {
          DDRB &= (0<<PB0);
          PORTB |= (1<<PB0);
          //while(!(TIFR & (1<<ICF1)));
            //cli();
          wh_k1 = TCNT1H;
          wl_k1 = TCNT1L;
          c_k1 = TCNT2;
            //sei();
          TIFR |= (1<<ICF1);
          DDRB |= (1<<PB0);
          PORTB &= (0<<PB0);
        }
      }
      else
      {
        flag_kurve1 = 0;
        flag_kurve2 = 1;
      }
    }

    if (flag_kurve2)
    {

      adca1=adc1;
      adc1 = ReadChannel(1);
      if (ms1>adc1)
      {
        if (adc1>adca1)
        {
        }
        else
        {
          DDRB &= (0<<PB0);
          PORTB |= (1<<PB0);
          //while(!(TIFR & (1<<ICF1)));
          //cli();
          wh_k2 = TCNT1H;
          wl_k2= TCNT1L;
          c_k2 = TCNT2;
          //sei();

          TIFR |= (1<<ICF1);
          DDRB |= (1<<PB0);
          PORTB &= (0<<PB0);
        }
      }
      else
      {
        flag_kurve1 = 0;
        flag_kurve2 = 0;
      }
    }

  }
    while(!(PINB & (1<<PINB1)))
    {
      if (flag_ausg)
         {
        cli();
        //tl =TCNT1L;
        //th = TCNT1H;
        //tc = TCNT2;
        for(y=0;y<30000;y++);
        if((PINB & (1<<PINB1)))
          break;
        TCCR1B |= (0<<CS10)|(0<<CS11)|(0<<CS12);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('1');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('2');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('3');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('4');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('5');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('6');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('7');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('8');
        for(y=0;y<3000;y++);
        PORTB &= (0<<PINB2);
        SPI_MasterTransmitc('9');
        for(y=0;y<3000;y++);
        TCNT1H=0x1F;
        TCNT1L=0;
        TCNT2 = 0x00;
        sei();
        flag_timer = 1;
        flag_kurve1 = 0;
        flag_kurve2 = 0;
        flag_ausg = 0;
        wh_k1=0;
        wl_k1=0;
        c_k1=0;
        wh_k2=0;
        wl_k2=0;
        c_k2=0;
        tl=0;
        tc=0;

ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler 
setzen auf 8 (1) und ADC aktivieren (1)
ADMUX = 0; // Kanal waehlen
ADMUX |= (0<<REFS1) | (1<<REFS0); // Spannungsversorgung als 
Referenzspannung nutzen nach Aktivieren des ADC wird ein "Dummy-Readout" 
empfohlen,
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC)); // auf Abschluss der Konvertierung warten
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC));
// auf Abschluss der Konvertierung warten
ms0 = ADCW;
        }
      }
    }
}

Hoffe du kannst mir helfen, bin schon über 2 Tage an diesem sch... 
Problem.
Dank!

MfG Benajmin

von Peter D. (peda)


Lesenswert?

Benjamin wrote:

> Controller 2 mit UART funtioniert einwandfrei und die Übertragung der
> Werte über die SPI an Controller 2 auch (allerdings nur beim ersten
> mal).

Woher willst Du das wissen ?

Wenn ich Dein Programm richtig verstehe überträgt es nur den String 
"123456789".



> Hier nun der wichtigste Sourcecode-Ausschnitt:

Ja, da jubeln hier alle, daß sie wieder mal rumraten und sich 
totscrollen dürfen.

Wozu gibt es den "Dateianhang" ?

Richtig, damit man einen kompilierbaren (kein PDF, JPG usw.) 
abgespeckten (aller rauskommentierter Code entfernt), kommentierten 
Sourcecode postet, der den Fehler enthält (geprüft).

Peter

von gast (Gast)


Lesenswert?

Wo hast du den PB2 angeschlossen?

und was soll  z.B.    " DDRB &= (0<<PB0); "
meinst Du damit evtl  " DDRB &= ~(1<<PB0);" ?

von Joerg X. (Gast)


Lesenswert?

OK, solchen Code hatte ich nicht erwartet/erhofft :(
Was macht dieses Programm eigentlich ?
 Es bleibt nämlich nicht viel übrig, falls die Compiler optimierung 
eingeschaltet wird (z.B. leere Schleifen, "0<<n").
es gibt hoffentlich ISRs für den/die?! Timer?
... (sry, aber mir fehlen die Worte)

von Wolfram (Gast)


Lesenswert?

>/*Set MOSI and SCK output, all others input */
>DDRB |= (1<<PINB3)|(1<<PINB5);
setze den SS PIN auf ein definiertes Level am besten Output sonst 
schaltet der Controller in den Slave Modus und wartet (datenblatt lesen)


for(y=0;y<3000;y++);
Ich weiß nicht von wann dein C-Buch ist (1980/85?)
sowas funktioniert schon lange nicht mehr
for(y=0;y<3000;y++); heißt mache 3000 mal nichts
3000 mal nichts machen ist genauso wie nichts machen, damit fällt das 
weg!
zum Rest des Programmes fehlen mir auch die Worte

von Joerg X. (Gast)


Angehängte Dateien:

Lesenswert?

damit du dir nicht so angemacht vorkommst:
bei Problemen sollte ein Programm gepostet werden, dass:
1. nur die Teile enthält, die Probleme machen (in deinem Fall ohne 
Timer!)
2. kompilierbar ist (also Headerdateien, Makros, main() und alle 
aufgerufen Funktionen oder Dummies)
3. sollte die Schaltung beschrieben werden (was hängt an PB1 und PB0?)

Ich hab mal ein Prog angehängt, dass einen ADC-Wert misst und dann 1 2 3 
4 ... per SPI sendet, vor dem Senden wird ein Pin auf 0 gesetzt und 
anschließend wieder auf 1 (wie eben ein klassischer \slaveselect)

( mir stürzt allerdings der Simulator ab, wenn ich die Optimierung 
anschalte :(, bei -O0  geht's aber )

Entschuldigung, dass "wir" erwarten, dass der Fragensteller mitdenkt

von Benjamin (Gast)


Lesenswert?

Werde mich nächstens an die "Regeln" halten.
Danke für die Tipps und das Beispielprogramm, hat mir sehr geholfen.
Mein Problem lag in dem SPI teil des Programms.
Danke nochmals!!!

MfG

Benjamin

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.