-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: A/D Werte ausgeben

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    24.01.2006
    Alter
    39
    Beiträge
    6

    A/D Werte ausgeben

    Anzeige

    Hallo Leute,

    ich hab ein riesen Problem. Ich hock schon seit Tagen vor meinem Rechner und versuch die A/D Werte die mein Atmega32 ins ADC Register schreibt über UART auf meinem PC auszugeben, aber leider vergeblich. Das einzige was auf meinem Bildschirm erscheint sind Unmengen an Buchstaben und Ziffern, also muss doch irgendwas mit itoa oder der UART-Übertragung nicht stimmen. In meinem Programm versuch ich durch drücken einer Taste ein bestimmtes LED zum leuchten zu bringen und zugleich die A/D Werte auszuspucken, die Funktion um die LEDs zum leuchten zu bringen funzt einwandfrei aber bei der UART-Übertragung ist der Wurm drin. Also ich wäre über jede Hilfe dankbar, ist bestimmt ein Witz für euch.

    Hier ist mein Code
    Code:
    #include <avr/io.h> 
    #include "wchar.h"
    #include <stdlib.h>
    
    #define SYSCLK   14756000 
    
    void init(void); 
    unsigned int get_key(void); 
    
    /* 
     * Hauptprogramm 
     */ 
    int main(void) 
    { 
       unsigned int i=0; 
       char buffer[100];
       
       init(); 
        
       while(1) 
       { 
          /* Ergebnis auslesen und anzeigen */ 
    	  
    	  if(i != 0xff)
    	  {
    	  itoa(i,buffer,2);
    	  write(buffer);
          }
    	  
    	  i = get_key(); 
    
           
          if (i != 0xff) 
    		 PORTC = ~(1<<i) & 0x7f; 
          else 
             PORTC = 0x7f; 
       } 
        
       return 0;    
    } 
    
    /* 
     * Initialisierung des µC 
     */ 
    void init(void) 
    { 
       DDRA = 0x00;      /* Port als Eingang deklarieren ( A/D-Wandler Eingänge ) */ 
       PORTA = 0x80; 
        
       DDRB = 0xff;      /* Port als Ausgang deklarieren */ 
       PORTB = 0x00; 
        
       DDRC = 0xff;      /* Port als Ausgang deklarieren */ 
       PORTC = 0x00; 
        
       DDRD = 0xff;      /* Port als Ausgang deklarieren */ 
       PORTD = 0x00; 
        
       /* Analog zu Digital Wandler aktivieren ( Prescaler = 128, interne +5V Referenz, "8-Bit" Ergebnis ) */ 
       ADMUX = (1<<REFS0)|(1<<ADLAR);  
       ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); 
    } 
    
    /** 
     * Fragt die Tasten an AD-Port 7 ab, kann nicht erkennen ob zwei Tasten gleichzeitig gedrückt werden 
     * 
     *   255  keine Taste gedrückt 
       0    Taste 1 gedrückt 
       1    Taste 2 gedrückt 
       2    Taste 3 gedrückt 
       3    Taste 4 gedrückt 
       4    Taste 5 gedrückt 
     */ 
    unsigned int get_key(void) 
    { 
       unsigned int i, taste = 0xff; 
        
       /* ADC7 mit Vcc als Referenzspannung */ 
       ADMUX = (1<<REFS0)|(1<<ADLAR)|0x07; 
        
       /* AD Wandler starten */ 
       ADCSRA |= (1<<ADSC); 
        
       /* Warten bis das Ergebniss zur Verfügung steht */ 
       while(!(ADCSRA & (1<<ADIF))); 
        
       /* Ergebnis auslesen und anzeigen */ 
       
       i = ADCH; 
    
       
       if (i < 36) 
          taste = 4; 
       else if (i < 57) 
          taste = 3; 
       else if (i < 76) 
          taste = 2; 
       else if (i < 94) 
          taste = 1; 
       else if (i < 150) 
          taste = 0; 
        
       return taste; 
    }
    und noch der Code der Verantwortlich ist für die Ausgabe

    Code:
    #include <avr/io.h>
    #include <string.h>
    #include <inttypes.h>
    
    void uart_init(void);
    
    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 text[])
    {
    	char *s;
    	s=&(text[0]);
    	while (*s)
        {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
            uart_putc(*s);
            s++;
        }
    }
    
    void write(char text[])
    {
    	/*Den UART initialisieren*/
    	uart_init();
    	uart_puts(text);
    
    }
    
    void uart_init(void)
    {
      /* USART-Init 19200 Baud bei 16MHz für Mega32 */
      UCSRB |= ( 1 << TXEN );			// UART TX einschalten
      UCSRC |= ( 1 << URSEL )|( 3<<UCSZ0 );	        // Asynchron 8N1
      UBRRH  = 0;                                   // Highbyte ist 0
      UBRRL  = 51;                                  // Lowbyte ist 51 ( dezimal )
    }
    Vielen Dank schon mal im voraus für eure Bemühungen
    Gruss
    Torsten

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    -- Dein Kommentar zur Clock passt nicht zu dem Define. Sind es nun 16MHz oder 14.***? Das Ausrechnen solltest du dem Compiler überlassen, sonst musst du immer die Quelle nachpinseln, wenn sich die CPU-Frequqnz ändert.
    -- Du wandelst den ADC-Wert nach binär um, zu erwarten ist also eine Folge wie 00001010101111001



    http://people.freenet.de/gjl/helferl...t-rechner.html
    Disclaimer: none. Sue me.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    24.01.2006
    Alter
    39
    Beiträge
    6
    Danke schon mal für deine rasche Antwort.

    -was muss ich dafür angeben, dass der Compiler die Clock selbst berechnet. Ich hab bei define jetzt mal 16000000 angegeben.

    -ich habs bei itoa auch schon mit 10 ausprobiert aber bei der Ausgabe kommen immer unendlich viele Zeichen.

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    11.11.2005
    Beiträge
    321
    du musst die mfile für die make richtig benutzen...

    Castle

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Im Wiki-Beispiel UART wird der UBRR-Wert von GCC berechnet. Dazu muss er natürlich zur Compilezeit bekannt sein.

    Ansonsten kann ich mit meinem Debugger Brain v0.9 nix schlimmes erkennen, nur daß ich den Text nicht als char text[] übergeben würde, sonden als char *text.
    Disclaimer: none. Sue me.

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    11.11.2005
    Beiträge
    321
    mal eine zusammengestellte hilfe.

    winavr-c-programm:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <avr/io.h>
    #include <stdint.h>
    #include <string.h>
    #include <avr/pgmspace.h>
    #include "adc.h"
    
    #define delay_us_(us)  _delayFourCycles_( ( ( 1*(F_CPU/4000) )*us)/2005 )
    
    static inline void _delayFourCycles_(uint16_t z)
    {
    	uint16_t i;
    	
        for (i=0; i<z; i++)
        asm volatile("nop");
    }
    
    static inline void delay_ms_(uint16_t z)
    {
    	uint16_t i;
    	
    	for (i=0; i<z; i++)
        delay_us_(999);
    }	
    				
    int main(void)
    {
    
    uint16_t x=0;
    char buffer[7];
    
    ADCinit;
    ADCprescaler_16;
    //Aktivierung des ADC, festlegen eines Prescalers von 16 
      
    while (1)
    	{
    	ADCchannel_1;
    	//Aktivierung des Pins , an ihm soll die zu messende Spannung liegen
    		
    	ADCstart;
    	//Start einer Konvertierung
    	
    	x=getadc();	
        itoa( x , buffer, 10);
        //routine zum senden an ein display oder RS232 
        delay_ms_(200);
    	}
    }

    die adc.h :

    Code:
    #define ADCchannel_init   DDRA=0x00                 // ADC Port als Eingang deklarieren
    #define ADCinit           ADCSRA|=_BV(ADEN)         // Teilt dem Board mit das der jeweilige Port für ADC verwendet wird
    #define ADCdisable        ADCSRA &=~_BV(ADEN)       // machs das vorherige wieder rückgänig
    #define ADCstart          ADCSRA|=_BV(ADSC)         // startet eine konvertierung auf dem gewünschten Kannal/Pin
    #define ADCfree           ADCSRA|=_BV(ADATE)        // schaltet den freilaufenden Modus ein
    #define ADCvintern        ADMUX|=_BV(REFS0)     // interne Spannungsversorgung
    #define ADCinterrupt_on   ADCSRA|=_BV(ADIE)                // ADC interrupt wird freigeschalten
    #define ADCprescaler_2    ADCSRA |=_BV(ADPS0)              // gewünschter Teilungsfaktor/Prescaler 
    #define ADCprescaler_4    ADCSRA|=_BV(ADPS1)
    #define ADCprescaler_8    ADCSRA=_BV(ADPS1) | _BV(ADPS0)
    #define ADCprescaler_16   ADCSRA|=_BV(ADPS2)
    #define ADCprescaler_32   ADCSRA=_BV(ADPS2) | _BV(ADPS0)
    #define ADCprescaler_64   ADCSRA=_BV(ADPS2) | _BV(ADPS1)
    #define ADCprescaler_128  ADCSRA=_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0)
    #define ADCprescaler_reset ADCSRA = ~_BV(ADPS2) & ~_BV(ADPS1) & ~_BV(ADPS0)        
    #define ADCchannel_1                                      //gewünschter Kannal z.B bei ATmega32 PINA0 - PINA7
    #define ADCchannel_2      ADMUX|=_BV(MUX0)                // bei nicht freilaufen muss ADCchannel_x vor
    #define ADCchannel_3      ADMUX|=_BV(MUX1)                // ADCstart kommen dann kann man mit getadc() der 
    #define ADCchannel_4      ADMUX= _BV(MUX1) | _BV(MUX0)    // Adcwert des gewählten Kannals auslesen
    #define ADCchannel_5      ADMUX|=_BV(MUX2)
    #define ADCchannel_6      ADMUX= _BV(MUX2) | _BV(MUX0)
    #define ADCchannel_7      ADMUX= _BV(MUX2) | _BV(MUX1)
    #define ADCchannel_8      ADMUX= _BV(MUX2) | _BV(MUX1) | _BV(MUX0)
    #define ADCchannel_reset  ADMUX= ~_BV(MUX2) & ~_BV(MUX1) & ~_BV(MUX0)
    
    uint16_t getadc(void)
    {
       while (ADCSRA & _BV(ADSC)) {}
       return ADC;
    }

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    24.01.2006
    Alter
    39
    Beiträge
    6
    Vielen Dank super_castle,

    bevor ich mit meinem Programm weitermach werd ich das lieber mal gründlich studieren.

    Gruss
    Torsten

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo toraX,
    wenn ich das richtig sehe, dann holst du in der Funktion get_key() ja den ADC-Wert in die Variable i.
    Diese Variable hast du in der Funktion LOKAL definiert. So weit ist es noch OK.
    In deiner main()-Funktion hast du eine WEITERE LOKALE i-Variable angelegt.
    Es sieht so aus, dass du erwartest, dass i aus get_key() in main() den gleichen Inhalt hat.
    In main() bekommst du aber den Wert, den du in get_key() über 'return taste' zurückgibst. Da taste in get_key() aber nur die Werte 0xff, 4, 3, 2, 1, und 0 annehmen kann, sollte dein write() immer nur diese Werte senden.

    Um den ADC-Wert aus get_key() nach main() zu bekommen kannst du eine GLOBALE Variable ausserhalb aller Funktion anlegen.
    Z.B.:
    Code:
    unsigned int adc_wert;
    
    int main (void)
    {
       to was;
    
       atoi (adc_wert, buffer, 2);
       write (buffer);
    
       to was anderes;
    }
    
    unsigned int get_key(void)
    {
       tu hier auch was;
    
       adc_wert = ADCH;
    
       if (adc_wert < 36)
          taste = 4;
       ...
    
       return taste;
    }
    Lieber Asuro programieren als arbeiten gehen.

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018

    Re: A/D Werte ausgeben

    Noch ein Hinweis zu:
    Zitat Zitat von toraX
    Das einzige was auf meinem Bildschirm erscheint sind Unmengen an Buchstaben und Ziffern, ...
    Da der Kontroller recht flott ist, und dein main() natürlich in einer Schleife läuft, sendest du ununterbrochen. Ist das tatsächlich gewünscht?
    Wenn nein, solltest du evl. nur bei einer Änderung des ADC-Wertes senden, und dann evl. mit einem Trennzeichen zwischen den einzelnen Werten.
    Beispielhaft:
    Code:
    unsigned int adc_wert;
    
    int main (void)
    {
       unsigned int adc_wert_last = 0;
    
       while ()
       {
          tu was;
    
          if (adc_wert != adc_wert_last)
          {
             atoi (adc_wert, buffer, 2);
             write (buffer);
             write ("\n\r");
             adc_wert_last = adc_wert;
          }
    
          mach hier weiter;
       }
       return 0;
    }
    [highlight=red:37fc6e945f][/highlight:37fc6e945f]
    Lieber Asuro programieren als arbeiten gehen.

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    24.01.2006
    Alter
    39
    Beiträge
    6
    Oh man, auf das Problem mit der lokalen Variable hätte ich auch selber kommen können.
    Vielen Dank Sternthaler!!!

    Ich hab nun eine globale Variable eingeführt, die auch nur ausgegeben wird wenn eine Taste gedrückt wird, aber leider hab ich immer noch ein kleines Problem mit der Ausgabe.
    Es scheint aber zumindestens, dass jetzt 2 Tasten richtig ausgegeben werden und ich hab zum Glück lauter neue Anregungen und Tipps um weiterzumachen.

    Nochmals vielen Dank für eure Hilfe.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •