www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik warnung:"[variable]may be used uninizialized"


Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich verzewifel hier langsam an dem unten stehenden programmabschnitt
...das ganze soll mal über rs232 nen AD-Wandler-Kanal auswählen und dann 
dauerhaft die werte aus dem gewählten kanal über RS232 an den pc 
senden...

wenn ich mir mit meinem terminalprogramm (HTerm) anschaue was rauskommt 
so sehe ich dass zwar dass daten ankommen, aber ich kann nicht den kanal 
wechseln...

das steuern des PORTB funktioniert, was meiner meineung nach nahe legt 
dass das problem mit folgender warnung zusammenhängt (:-D) :
../ATMega8-UART.c:86: warning: 'adchannel' may be used uninitialized in 
this function

hier der programmabschnitt:
int main(void)
{  
  
  DDRB|= (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB4) | (1<<PB5); //ausgänge für ventilsteuerung angesprochen mit !1...!5 sind pb1...5
  char Line[3];
  char s[20];                            
  uint8_t adchannel;  
  InitUART(9600);
  sei();    
  
  while(1){

    
    uint16_t result = ADC_Read(adchannel);    //senden und wandeln des wertes an channel "adchannel"                                  
    itoa( result, s, 10 );
     uart_puts( s );
        uart_putc('\r');

    uart_gets( Line, sizeof( Line ) );        //verarbeitung eintreffender daten   
    switch(Line[0]){    
      case '!':                 //! meint steuerbefehl 1...5
        switch(Line[1]){  
          case '1':PORTB=0b00000010;  break;
          case '2':PORTB=0b00000100;  break;  
          case '3':PORTB=0b00001000;  break;  
          case '4':PORTB=0b00010000;  break;  
          case '5':PORTB=0b00100000;  break;  
          }
      break;
      
      case '?':               //? meint abfrage des channels 0...7
        switch(Line[1]){  
          case '0':adchannel=0;  break;
          case '1':adchannel=1;  break;
          case '2':adchannel=2;  break;
          case '3':adchannel=3;  break;
          case '4':adchannel=4;  break;
          case '5':adchannel=5;  break;
          case '6':adchannel=6;  break;
          case '7':adchannel=7;  break;          
        }
      
      break;
      
    }

  }return 0;
}

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und wo bekommt adchannel beim ersten Durchlauf seinen Wert her?

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

Bewertung
0 lesenswert
nicht lesenswert
Das hier
 uint8_t adchannel;  
  InitUART(9600);
  sei();    
  
  while(1){

    
    uint16_t result = ADC_Read(adchannel);

Beantworte bitte ganz schnell die Frage:
Beim ersten Aufruf von ADC_Read .... welchen Wert hat da adchannel?

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

Bewertung
0 lesenswert
nicht lesenswert
> das steuern des PORTB funktioniert, was meiner meineung nach nahe legt
> dass das problem mit folgender warnung zusammenhängt (:-D) :
> ../ATMega8-UART.c:86: warning: 'adchannel' may be used uninitialized in
> this function

Eigentlich nicht.
Wenn du wissen willst, was in der Maschine abgeht, dann bau dir 
zusätzliche Ausgaben ein.

zb so
     case '?':               //? meint abfrage des channels 0...7

        usart_puts( "Schalte nach #" );
        usart_putc( Line[1] );
        uasrt_puts( "#\r" );

        switch(Line[1]){  



dann erzählt dir der µC, was er empfangen hat und du kannst rausfinden 
warum die Umschaltung nicht klappt.

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> case '!':                 //! meint steuerbefehl 1...5
>
>         switch(Line[1]){
>
>           case '1':PORTB=0b00000010;  break;
>
>           case '2':PORTB=0b00000100;  break;
>
>           case '3':PORTB=0b00001000;  break;
>
>           case '4':PORTB=0b00010000;  break;
>
>           case '5':PORTB=0b00100000;  break;
>
>           }
>
>       break;
>
>
>
>       case '?':               //? meint abfrage des channels 0...7
>
>         switch(Line[1]){
>
>           case '0':adchannel=0;  break;
>
>           case '1':adchannel=1;  break;
>
>           case '2':adchannel=2;  break;
>
>           case '3':adchannel=3;  break;
>
>           case '4':adchannel=4;  break;
>
>           case '5':adchannel=5;  break;
>
>           case '6':adchannel=6;  break;
>
>           case '7':adchannel=7;  break;
>
>         }

LOOOOLLLL!!!

Wieso nicht so?
if ((Line[1] => '1') && (Line[1] <= '5'))
   PORTB = Line[1] - '0';

\\...

if ((Line[1] => '0') && (Line[1] <= '7'))
   adchannel = Line[1] - '0';



Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wow, das geht ja schnell hier!!!
@kbuchegg: sorry, muss natürlich heissen
DDRB|= (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB4) | (1<<PB5); //ausgänge für ventilsteuerung angesprochen mit !1...!5 sind pb1...5
  char Line[3];
  char s[20];                            
  uint8_t adchannel=0;   //jezt mal default kanal 0, damit hatte ich es auch schon versucht :)
  InitUART(9600);
  sei();    



was natürlich auch die warnung behebt- aber leider nichts daran ändert 
dass die Kanalwahl nicht klappt

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:

> was natürlich auch die warnung behebt- aber leider nichts daran ändert
> dass die Kanalwahl nicht klappt

Wie schon gesagt:
Bau dir zusätzliche Ausgaben ein, damit dir der µC erzählt was er warum 
macht.

Beitrag "Re: warnung:"[variable]may be used uninizialized""

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meinte sO:

if ((Line[1] >= '1') && (Line[1] <= '5'))
   PORTB = Line[1] - '0';

...

if ((Line[1] >= '0') && (Line[1] <= '7'))
   adchannel = Line[1] - '0';

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

Bewertung
0 lesenswert
nicht lesenswert
Immer noch falsch Fabian. SChau dir genau an, was er mit dem PORTB 
macht.
Lass uns bitte erst am Problem arbeiten, ehe wir Vereinfachungen 
vorschlagen. ok?

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Lass uns bitte erst am Problem arbeiten, ehe wir Vereinfachungen
>
> vorschlagen. ok?

Jawohl!

Funktioniert denn überhaupt: ADC_Read(adchannel); richtig? Bzw. woher 
weißt Du, dass der Kanal nicht gewechselt wird?!
Ein häufiges Problem ist, wenn der A/D Kanal gewechselt, aber nicht 
lange genug bis zur Messung gewartet wird. Das S&H Glied muss sich ja 
erstmal umladen.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Immer noch falsch Fabian.
>Lass uns bitte erst am Problem arbeiten, ehe wir Vereinfachungen
>vorschlagen. ok?

Naja, eine halben Stern im Heft hat er sich verdient ;)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie lang sind eigentlich die empfangenen Kommandos?
Zwei Zeichen plus \r?
Dann ist die 3 als Feldlänge zu knapp, wenn noch eine
abschließende 0 dazukommt; ggf. noch eines mehr für \n etc..

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

Bewertung
0 lesenswert
nicht lesenswert
OK
printf( "         *\n"
        "        * \n"
        "       *  \n"
        "    ***   \n"
        "  **      \n"
        "    ***   \n"
        "       *  \n"
        "        * \n"
        "         *\n"
      );

Jetzt warten wir mal, ob sich was ergibt d.h. ob seine Empfangsroutine 
überhaupt richtig arbeitet.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Fabian: wesendlich eleganter, soviel steht fest (mach das noch nicht 
lange) ;)

@kbuchegg: stimmt, ausgabe ist jezt in HTerm 'Schal?LL???1023<\r>' um 
diese meldung herum steht der zu erwartende input von ADC0, nämlich jede 
menge '1023'

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:

> @kbuchegg: stimmt, ausgabe ist jezt in HTerm 'Schal?LL???1023<\r>' um
> diese meldung herum steht der zu erwartende input von ADC0, nämlich jede
> menge '1023'

Wie Klaus schon sagte: Geh erst mal mit dem Line Array höher. Solche 
Felder dimensioniert man nie auf Knirsch, sondern immer mit Reserve. 
Mach da mal 80 draus.

Und dann fügst du nach jedem \r noch ein \n in die Ausgabe ein, damit 
neuer Output den alten nicht überschreibt, sondern eine neue Zeile im 
Terminal angefangen wird, damit man auch was sieht.

Und dann zeigst du deine Empfangsroutine.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> @Fabian: wesendlich eleganter, soviel steht fest (mach das noch nicht
> lange) ;)

Aber bei PORTB falsch.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
antwort auf
uart_puts( "         *\n"
        "        * \n"
        "       *  \n"
        "    ***   \n"
        "  **      \n"
        "    ***   \n"
        "       *  \n"
        "        * \n"
        "         *\n"

ist:

..."1023<\r>         *<\n>        * <\n>   ??LL???1023<\r>1023<\r>"...

bei sendung von "!1"

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> antwort auf
>
> uart_puts( "         *\n"
>         "        * \n"
>         "       *  \n"
>         "    ***   \n"
>         "  **      \n"
>         "    ***   \n"
>         "       *  \n"
>         "        * \n"
>         "         *\n"
> 
>
> ist:


LOL. Das war auch nicht für dich gedacht :-)
Sondern als Antwort auf
Beitrag "Re: warnung:"[variable]may be used uninizialized""
> Naja, eine halben Stern im Heft hat er sich verdient ;)

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, line mit 80 feldern, noch ein \n hinters \r :

ausgabe ist:

<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023 
<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023 
<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023 
<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023 
<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023 
<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023 
<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>1023<\r><\n>

...also wie vorher

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

Bewertung
0 lesenswert
nicht lesenswert
Schalte doch bitte dein HTerm in den Modus, dass es Steuerzeichen 
interpretiert anstelle das es sie hinschreibt. Das die Zahlen stimmen 
glaub ich dir ja. Ich bin am Zusatztext interessiert!

Ich brauch den Text der bei der eingefügten Ausgabe rauskommt.
Hast du eh gesehen, dass die 2te Ausgabe kein uart_puts sondern ein 
uart_putc (ein einzelnes Zeichen) ist?
     case '?':               //? meint abfrage des channels 0...7

        usart_puts( "Schalte nach #" );    // <-  String          S
        usart_putc( Line[1] );             // <-  Einzelzeichen   C
        uasrt_puts( "#\r" );               // <-  String          S

        switch(Line[1]){  


Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vieleicht sollte er den ADC mal initialisieren
und eine Vref Quelle auswählen;)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und vielleicht sind die 1023 ja auch alle richtig; kann ja von mehreren 
Kanälen der gleiche Wert kommen (wenn U über UREF liegt).

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

Bewertung
0 lesenswert
nicht lesenswert
Hmm

Das lässt sich verifizieren, ob man in der ADC_Read weiter suchen muss
 while(1){
    uint16_t result;

    uart_puts( "Sample Kanal " );
    utoa( adchannel, s, 10 );
    uart_puts( s );
    uart_puts( "  -> " );

    result = ADC_Read(adchannel);    //senden und wandeln des wertes an channel "adchannel"                                  

    utoa( result, s, 10 );
    uart_puts( s );
    uart_puts( "\r\n" );

    ....



Ich bin bisher eigentlich von einem Problem in der gets ausgegangen (ein 
\r der irgendwo übrig geblieben ist, oder so was in der Art). Aber auch 
das könnte man verifizieren (was bei Benutzer-Eingaben sowieso immer 
eine gute Idee ist)

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hab das ganze so aufgebaut dass bei interner Uref am ADC0 5V 
anliegen, an ADC1 per spannungsteiler ca 2,5V an den anderen rauschen

ausgabe ist


<\n>1023<\r>
<\n>1023<\r>
<\n>1023<\r>
uswusw

wobei sich bei übertragen von !1 oder anderen nichts ändert

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> ich hab das ganze so aufgebaut dass bei interner Uref am ADC0 5V
und welchen Wet hat die Referenzspannung?

> anliegen, an ADC1 per spannungsteiler ca 2,5V an den anderen rauschen
Wo kommt das Rauschen her? Sind die Pins offen?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so: die Frage ist natürlich noch nicht beantwortet, wie der ADC 
initialisiert wird.

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> ich hab das ganze so aufgebaut dass bei interner Uref am ADC0 5V
> anliegen, an ADC1 per spannungsteiler ca 2,5V an den anderen rauschen
>
> ausgabe ist
>
>
> <\n>1023<\r>
> <\n>1023<\r>
> <\n>1023<\r>
> uswusw
>

nochmal.
Die Zahlen dazwischen sind uninteressant.
INteressant ist, wenn du im HTerm das Kommando absetzt

   ?3

was kommt dann am µC an.
Nur das ist momentan interessant.

> wobei sich bei übertragen von !1 oder anderen nichts ändert


wieso ! ?
Ich denke die ADC Kanalumschaltnug geht nicht. Die hast du aber mit ? 
und nicht mit ! programmiert. ! schaltet den Port B um

du kannst auch in die Hauptschleife erst mal einen
 _delay_ms( 500 );
(und natürlich oben das Header File) einfügen, damit dir der µC nicht so 
den Schirm zumüllt.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
meine (naja, nicht MEINE) ADC_Read sieht volgendermassen aus
  
uint16_t ADC_Read(uint8_t Mux_channel) 
{
  uint8_t i;
  uint16_t result = 0;   
  

    
    
  ADC_Init (Mux_channel);

  ADCSRA |= (1<<ADSC);        //Start conversion
  while(ADCSRA & (1<<ADSC));      //wait until converstion completed
  result = ADCW;            //ADCW must be read once
    result = 0;                    //Otherwise the result of the next transformation is not taken over
                          
  
  //Now reads 4 times the similar tension and selected channel channel 
  //And then calculate the average value divided by 4. Because the ADC measeres 0..1023,
  //And the Port however can only 0..255 show
  for(i=0; i<4; i++) 
  {    
    ADCSRA |= (1<<ADSC);      //A single conversion    
    while(ADCSRA & (1<<ADSC));    //Waiting on conversion closing    
    result += ADCW;
  }
  
  ADCSRA &= (0<<ADEN);          // ADC reanables  
  result /= 4;
    
  return result;
}//End int ADC_Read() 

hierin wird auch der ADC initialisiert -ADC_init():

void ADC_Init (uint8_t Mux_channel)
{
  
  TCNT0 = 5;        //Set Timer/counter
  TIMSK |= (1<<TOIE0);  //Enable Timer/counter0 overflow interrupt
  //TCCR0 |= (1<<CS01);
  TCCR0 |= (1<<CS00);
  TCCR0 |= (1<<CS02);  //Select the clock source to be used by the timer/counter --> CPU Takt  --> 8MHz/1024 
  TIFR |= (1<<TOV0);  //interrupt starts with each overflow 
  
  ADCSRA = (1<<ADEN);         //Enables the ADC
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1);   //Determine the division factor between the XTAL frequency and the input clock to the ADC. 
                    //Activate ADC with Prescaler 64 --> 8Mhz/64 = 125khz -optimum range 50-200 khz
  
  ADMUX = Mux_channel;        //Select pin ADC0 using MUX
  _delay_us(40);
  //warte ();
  ADMUX |= (1<<REFS0) | (1<<REFS1);  //Int. REF Voltage Reference Selection, for extern ARef use ADMUX |= (0<<REFS0) | (0<<REFS1); 
  ADMUX |= (0<<ADLAR);        //The result is right adjusted 
}


Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ich hab das ganze so aufgebaut dass bei interner Uref am ADC0 5V

Was zum Teufel steht in ADC_Read(adchannel)?

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> meine (naja, nicht MEINE) ADC_Read sieht volgendermassen aus

Und.
Hast du sie getestet?

Was passiert, wenn du einfach mal ADC_Read mit 1 aufrufst?
Kriegst du dann den erwarteten Wert?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Vieleicht sollte er den ADC mal initialisieren
>und eine Vref Quelle auswählen;)

>ich hab das ganze so aufgebaut dass bei interner Uref am ADC0 5V
>anliegen, an ADC1 per spannungsteiler ca 2,5V an den anderen rauschen

Und was ist mit dem Prescaler?

MfG Spess

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> ADMUX |= (1<<REFS0) | (1<<REFS1);  //Int. REF Voltage Reference Selection, for 
extern ARef use ADMUX |= (0<<REFS0) | (0<<REFS1);

Wie groß ist interne Referenzspannung?

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
äh sorry, "?1" war gemeint, das resultat ist das selbe wie oben 
gepostet, keine änderung... (auch bei ?3 nicht)

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

Bewertung
0 lesenswert
nicht lesenswert
Gewöhn dir das ganz schnell wieder ab
void ADC_Init (uint8_t Mux_channel)
{
  
  TCNT0 = 5;        //Set Timer/counter
  TIMSK |= (1<<TOIE0);  //Enable Timer/counter0 overflow interrupt
  //TCCR0 |= (1<<CS01);
  TCCR0 |= (1<<CS00);
  TCCR0 |= (1<<CS02);  //Select the clock source to be used by the timer/counter --> CPU Takt  --> 8MHz/1024 
  TIFR |= (1<<TOV0);  //interrupt starts with each overflow 

Die Funktion heißt ADC_Init. Die hat nichts mit dem Timer zu tun. Das 
gehört da nicht heinein.

(ISt jetzt aber nur ein Nebenschauplatz. Du hast doch hoffentlich eine 
ISR für den Timer geschrieben)

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> äh sorry, "?1" war gemeint, das resultat ist das selbe wie oben
> gepostet, keine änderung... (auch bei ?3 nicht)

Nochmal:
Wenn du ?2 im HTerm eingibst .....
.... dann müsste der µC in den Programmteil
    case '?':               //? meint abfrage des channels 0...7

        usart_puts( "Schalte nach #" );
        usart_putc( Line[1] );
        uasrt_puts( "#\r" );

        switch(Line[1]){  
     ....

kommen und dir ausgeben welches 2.te Zeichen er nach dem '?' empfangen 
hat.

Kommt die Ausgabe und wenn ja, welches Zeichen taucht zwischen den # 
auf? Das kann nur ein einzelnes Zeichen sein. Da kann kein #+34z78 
stehen, es sei denn du hast irrtümlich anstelle von

        usart_putc( Line[1] );

ein

        usart_puts( Line[1] );

geschrieben.

Mach dir ein _delay_ms( 1000 ) in die Hauptschleife rein, wenn die 
Zahlen zu schnell durchrauschen und du nichts mehr sehen kannst. Aber 
ehe wir weiter suchen, sollten wir sicherstellen, dass aus deiner 
uart_gets Funktion auch das rauskommt, was du denkst das rauskommen 
sollte.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie groß ist interne Referenzspannung?

Zu klein;)

Ich empfehle die Spannungen an den ADC Eingängen mal
unter 2,56V zu bringen. Oder AVCC als VREF zu nehmen.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
laut datenblatt ist Vref intern  2,56 V. getestet ist die funktion 
ADC_Read - ich habe passende werte erhalten, nur leider nicht mit von 
mir über rs232 steuerbar sondern nur mit einer konstanten statt 
adchannel sprich mit
uint16_t result = ADC_Read(1);    //hier ist die variable "adchannel" mit 1 ersezt                                 
    itoa( result, s, 10 );
     uart_puts( s );
        uart_putc('\r');


das mit dem delay macht das ganze weniger stressig, danke :)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder einfach mal einen Pin auf GND legen, dann wird auch was anderes als 
1023 rauskommen :-)

holger schrieb:
> Ich empfehle die Spannungen an den ADC Eingängen mal
> unter 2,56V zu bringen. Oder AVCC als VREF zu nehmen.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich empfehle die Spannungen an den ADC Eingängen mal
>unter 2,56V zu bringen. Oder AVCC als VREF zu nehmen.

Upps, oder je nach CPU Typ (welcher ist das) sogar unter 1V.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(langsam tut er mir fast leid, jetzt wird er von 3 oder 4 Seiten in die 
Zange genmommen)

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

Bewertung
0 lesenswert
nicht lesenswert
Da muss er durch :-)

Debuggen lernt man nicht über Nacht.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@kbuchegg: wie gesagt, es tut sich nichts

nochmal der code mit den gemachten variationen, diesmal in der gesamten 
"pracht":
/*
Das Programm nuzt die Kanäle ADC0...7 als eingänge des ADC. Ausgänge zur steuerung von wasweissichwas 
sind PB1...5. Der aktuell gemessene AD wert wird über USART verschickt. 
Befehle die angenommen werden: !1...!5 steuert die PB1...5
                   ?0...?7 wählt den zu messenden kanal aus
zu beachtden: nach jedem befehl muss evl ein "null" gesendet werden um das array abzuschliessen, 
geht aber auch jedes andere zeichen (zb !1x)
*/

#define  __AVR_ATmega8__  1
#define OSCSPEED  8000000    /* in Hz */

#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "ADC_USART_Read_adc.h"

void InitUART(uint32_t baud)  /* here a simple int will not suffice*/  
{
  int baudrate=(OSCSPEED/(16*baud))-1; /* as per pg. 133 of the user manual */
  /* Set baud rate */
  UBRRH = (unsigned char)(baudrate>>8);
  UBRRL = (unsigned char)baudrate;
  /* Enable Receiver and Transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 1stop bit */
  UCSRC = (1<<URSEL)|(3<<UCSZ0);  
}

uint8_t uart_getc(void)
{
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
        ;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
}
 
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';
}


int uart_putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
    {
    }                             
 
    UDR = c;                      // sende Zeichen 
    return 0;
}
 
 
/* puts ist unabhaengig vom Controllertyp */
void uart_puts (char *s)
{
    while (*s)
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
        uart_putc(*s);
        s++;
    }
}



int main(void)
{  
  
  DDRB|= (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB4) | (1<<PB5); //ausgänge für ventilsteuerung angesprochen mit !1...!5 sind pb1...5
  char Line[80];
  char s[20];                            
  uint8_t adchannel=0;  
  InitUART(9600);
  sei();    
  
  while(1){

    
    uint16_t result = ADC_Read(adchannel);    //senden und wandeln des wertes an channel "adchannel"                                  
    itoa( result, s, 10 );
     uart_puts( s );
        uart_putc('\r');
    uart_putc('\n');

    uart_gets( Line, sizeof( Line ) );        //verarbeitung eintreffender daten   
    switch(Line[0]){    
      case '!':                 //! meint steuerbefehl 1...5
        switch(Line[1]){  
          case '1':PORTB=0b00000010;  break;
          case '2':PORTB=0b00000100;  break;  
          case '3':PORTB=0b00001000;  break;  
          case '4':PORTB=0b00010000;  break;  
          case '5':PORTB=0b00100000;  break;  
          }
      break;
      
      case '?':               //? meint abfrage des channels 0...7
        
          uart_puts( "Schalte nach #" );    // <-  String          S
          uart_putc( Line[1] );             // <-  Einzelzeichen   C
          uart_puts( "#\r" );               // <-  String          S

    
        
        switch(Line[1]){  
          case '0':adchannel=0;  break;
          case '1':adchannel=1;  break;
          case '2':adchannel=2;  break;
          case '3':adchannel=3;  break;
          case '4':adchannel=4;  break;
          case '5':adchannel=5;  break;
          case '6':adchannel=6;  break;
          case '7':adchannel=7;  break;          
        }
      
      break;
      
    }
  _delay_ms( 500 );
  
  }return 0;
}



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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> @kbuchegg: wie gesagt, es tut sich nichts

Gar nichts?

Dann funktioniert deine uart_gets nicht richtig.

Ändere die mal (Vermutung ins Blaue)
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 ) {
    if( NextChar != '\r' ) {
      *Buffer++ = NextChar;
      StringLen++;
    }
    NextChar = uart_getc();
  } 
                                  // Noch ein '\0' anhängen um einen Standard
                                  // C-String daraus zu machen
  *Buffer = '\0';
}



Moment.
Das ist ein wartendes gets.
Da dürfen überhaupt keine Zahlen in der Hauptschleife durchrauschen, 
weil jedesmal nach dem ADC auslesen darauf gewartet wird, dass du eine 
Zeile vom PC rüberschickst.

<Nachdenk>

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

Bewertung
0 lesenswert
nicht lesenswert
Schmeiss die Timer Initialisierung aus dem ADC_Init raus.

Dein µC resettet sich laufend selber.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>nochmal der code mit den gemachten variationen, diesmal in der gesamten
>"pracht":

Nö.

>  TIMSK |= (1<<TOIE0);  //Enable Timer/counter0 overflow interrupt

Wo ist die Interrupt Routine für Timer0?

>#define  _AVR_ATmega8_  1
>#define OSCSPEED  8000000    /* in Hz */

Auaaaaa...

OSCSPEED interessiert

#include <util/delay.h>

nicht die Bohne.

Die Baustelle ist größer als bisher angenommen;)

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich empfange <\n>1023<\r> ...oft

-bzw eine 1 wenn ichs auf gnd lege bzw rauschen wenn ich den pin offen 
halte , die ADC an sich ist hier denke ich nicht das problem...

was die übertragung von strings angeht,
    while(1){
        uart_puts( "Hallo" );

gibt aus: ????! oder binär: 10000101 10110001 10110001 10111101 00100001

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

Bewertung
0 lesenswert
nicht lesenswert
Poste alles.

Da kommen ein paar Dinge zusammen. Einzeln aussortieren ist nicht.

Aber der wichtigste Punkt ist:

WENN DU KEINE INTERRUPT SERVICE ROUTINE HAST, DANN DARFST DU AUCH FÜR 
DEN TIMER KEINEN INTERRUPT FREIGEBEN!

Und das nächste mal versteckst du keinen Timer in den ADC Funktionen. 
Schon gar nicht, wenn da ein Interrupt dafür freigegeben wird. Da sucht 
man sich nämlich dumm und dämlich danach.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die Interrupt Routine für Timer0 such ich auch grade :D nee aber es ging 
wie gesagt problemlos ohne, dass ich rauschen emfange belegt das meiner 
meinung

util/delay.h musste ich erst durch die while reinnehmen, änderung: 
eingebut wurde #define F_CPU 8000000L

nun bekomm ich nach resetten lauter Hallos wie gewollt also uart_puts 
läuft

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> die Interrupt Routine für Timer0 such ich auch grade :D nee aber es ging
> wie gesagt problemlos ohne,

Nein.
Es geht eben nicht problemlos.
Das hat nur so ausgesehen.
Der gcc Standard ISR Handler hat das Programm alle paar ms neu 
gestartet. Und da du PORTB nicht initialisiert, hat der Wert am PortB 
dieses überlebt.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh äh ok hab mal
TIMSK |= (1<<TOIE0);  //Enable Timer/counter0 overflow interrupt
testweise auf 0 gesezt- resultat war dass nichts mehr gesendet wird...

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> oh äh ok hab mal
> TIMSK |= (1<<TOIE0);  //Enable Timer/counter0 overflow interrupt
> testweise auf 0 gesezt-

Schmeiss es ganz raus.
Timerinitialisierung hat in einer Funktion die den ADC initialisiert 
nichts verloren.

> resultat war dass nichts mehr gesendet wird...

Du meinst ausser dem ersten Messergebnis.

Das ist auch nicht anders zu erwarten.
deine uart_gets wartet darauf, dass sie eine Zeile bekommt. Der 
Programmlauf geht erst dann weiter, wenn die Zeile da ist.

Jetzt nähern wir uns langsam.
Vorschläge was du dagegen tun willst?

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...morgen sicherlich :) danke schonmal bis hier hin, iss ja schon 
ganzschön was zusammengekommen in dem thread ...

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>oh äh ok hab mal
>TIMSK |= (1<<TOIE0);  //Enable Timer/counter0 overflow interrupt
>testweise auf 0 gesezt- resultat war dass nichts mehr gesendet wird...

>Das ist ein wartendes gets.

Passt doch gut zusammen;)

Der fehlende Timer Interrupt hat dein Programm durch
ständige Resets am Leben gehalten.

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:
> ...morgen sicherlich :) danke schonmal bis hier hin, iss ja schon
> ganzschön was zusammengekommen in dem thread ...

Na komm.
Jetzt sind wir auf der Zielgeraden.

Deine uart_gets muss zuerst prüfen, ob überhaupt etwas an der UART 
eingetroffen ist und wenn nicht liefert sie einfach einen leeren String 
zurück.

Ist was da, dann wartet sie bis die Zeile komplett ist und gibt erst 
dann zurück.


Ist zwar nicht optimal, aber schnell umgesetzt.

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

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

  if( UCSRA & (1<<RXC) ) {        // wartet ein Zeichen in der UART?
    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 ) {
      if( NextChar != '\r' ) {
        *Buffer++ = NextChar;
        StringLen++;
      }
      NextChar = uart_getc();
    } 
  }
                                 // Noch ein '\0' anhängen um einen Standard
                                // C-String daraus zu machen
  *Buffer = '\0';
}

Dein ADC misst jetzt solange du am Terminal nichts tust.
Fängst du zu tippen an, dann geht die uart_gets in den Wartemodus. Sie 
wartet bis du fertig getippt hast (Return) und gibt die Zeile zurück. 
Die Zeile wird in der Hauptschleife ausgewetret und weiter gehts in der 
Hauptschleife und da dann die UART wieder leer ist, geht auch uart_gets 
nicht mehr in den Wartemodus und wartet danach nicht mehr. Bis du wieder 
zu tippen anfängst.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noch was anderes:
warum muss bei jedem ADCread der AD-Wandler komplett neu initialisiert 
werden?
Ich würde das nur ein Mal machen.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, änderungen die ich gemacht habe sind: löschen der kompletten 
timerinizialisierung sowie erneuern der uart_gets() nach kbucheggs 
vorschlag(danke!)

...schön ist dass jezt die warteschleife so läuft wie sie soll :)

allerdings resultiert das senden einer abfrage zb ?2 oder auch !2 im 
abbruch der hauptschleife (jedenfalls werden keine werte mehr 
ausgegeben, auchnicht das testweise implementierte "Schalte nach # 
'Line[1]' #")

aber auf jedenfall ist jezt so wie ich das sehe mit der initialisierung 
und den verwendeten funktionen alles im reinen...   ...vorschläge?

Autor: Bakunin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hier nochmal der komplette code im anhang
 - vielleicht hilfts der übersichtlichkeit :)

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sicher, dass du zu dem ?3 auch ein \n schickst? Ansonsten wartet deine 
getchar-Routine darauf, dass das Array voll ist. Und das bedeutet, dass 
du 80 Zeichen schicken musst.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also standardmässig sende ich null (\0) hinterher, \n bewirkt nichts 
anderes (grade getestet)

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok es liegt anscheinend auf jeden fall an der uart_gets() genauer gesagt 
an der bedingung
while( NextChar != '\n' && StringLen < MaxLen - 1 ) {

sobald ich das array Line[] auf 3 felder länge setze läuft alles wies 
soll...  - beötigt man für StringLen zufällig ne bibliothek die ich nich 
implementiert hab oder sowas?

nachtrag zu oben: dass ich standardmässig \0 am ende sende muss nicht 
sein-schöner währ ja ohne :)


aber wir (oder besser ihr) seit schon nah dran denk ich..

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine ganze UART-Empfangsgeschichte sieht für mich sehr komisch aus. Ich 
würde das alles streichen und neu konzipieren ;)

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
um die zu verbessern poste ich dass doch hier :D

"mach neu" ist mir dabei keine grosse hilfe..

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
klar :)

Ich würde das so aufbauen:
switch(getchar()) {
 case '!':
  switch(getchar()){
   '1': ...
  }
 break;
 case '?':
  switch(getchar()){
   '1': ...
  }
 break;
}

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

Bewertung
0 lesenswert
nicht lesenswert
Bakunin schrieb:

> nachtrag zu oben: dass ich standardmässig \0 am ende sende muss nicht
> sein-schöner währ ja ohne :)

Was, oder besser gesagt, wer sendet eigentlich.

Du (an einem Terminal) oder ein anderes Programm.

Ehe du an anderes Programm das Senden übernehmen lässt, solltest du erst 
mal selbst per Hand von einem Terminal aus deinen µC 'füttern'


(die 80 Zeichen können dir nur dann einen Strich durch die Rechnung 
machen, wenn dadurch das SRAM voll ist. Deine 'Lösung' mit Array auf 3 
Zeichen zurückschrauben ist, abgesehen von diesem Sonderfall, keine 
Lösung.


So wie Lasse das vorschlägt, kann man das natürlich auch machen. 
Allerdings ist es zum einen Flucht vor dem Feind, zum anderen wirst du 
deine Debug-Fähigkeiten nie entwickeln wenn du Schwierigkeiten immer nur 
aus dem Weg gehst und zu guter letzt ist eine uart_gets keineswegs eine 
esoterische Funktion, die man nie wieder braucht.

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

Bewertung
0 lesenswert
nicht lesenswert
Du kennst mitlerweile die Techniken, wie man solchen Problemen auf den 
Grund geht:

Bau dir Ausgaben ein!
In deiner uart_gets kommen die Zeichen herein. Also kannst du dir dort 
Ausgaben einbauen, an Hand derer du verfolgen kannst, was deine UART 
eigentlich empfängt.

Autor: Bakunin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Haha ok wie bekloppt- mein terminal-programm war so eingestellt dass \0 
on enter gesendet wird- mit der einstelölung \r on enter läufts 
logischer weise :D
später will ich labview zur steuerung nutzen (da ist es auch nicht 
sonderlich wild eben noch nen carriage return als konstante an den 
befehlsstring anzuhängen)

vielen dank fürs aufräumen meines codes und die verbessenungen!!!

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.