-         

Ergebnis 1 bis 3 von 3

Thema: Software PWM 4-Kanal

  1. #1

    Software PWM 4-Kanal

    Anzeige

    Hallo Robotikfreaks,

    Was AVRs angeht bin ich ein ziemlicher NOOB!
    Habe mir vor kurzem ein atmega16 Testboard bei ebay gekauft und habe es geschafft mal was über USART am PC auszugeben.

    Ich habe das fertige C-Skript von Christian Schifferle angepasst, und man sollte eigentlich über ein Terminal Programm eine Eingabe der Form:

    <Kanal 1..4>:<Wert von 0...255>

    machen. die an den Ausgängen angeschlossenen LEDs sollten dann heller oder dunkler leuchten, aber bei mir sind sie die ganze Zeit "mittelhell" egal welchen Wert ich eingebe.

    Hier das Skript:
    Code:
    #include <avr/io.h>	
    #include <stdint.h>    // Wir brauchen Zugriff auf die I/O's des Controllers
    #include <string.h> // und eine Stringfunktion (strchr)
    #include <stdlib.h> // sowie die Standardfunktion atoi aus stdlib
    
    
    #define USART_BAUD_RATE 9600      /* 9600 baud */
    
    // Berechnung des Inhalts des UBBR-Registers
    #define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16l)-1)
    
    
    // Datentypdefinitionen
    typedef unsigned char		BYTE;
    typedef unsigned short	WORD;
    
    #define CR 0x0d       // Definition für Carriage Return
    #define CHANNELS 4          // Anzahl PWM-Kanäle
    #define MAX_BUFFER 15         // Maximal 15 Zeichen lange Befehlszeile zulassen
    
    BYTE szBuffer[MAX_BUFFER+1];    // Puffer mit maximal 15 Zeichen plus Nullbyte
    BYTE nBuffer;                   // Anzahl Zeichen im Puffer
    BYTE nChannels[CHANNELS];       // PWM-Werte der 4 Kanäle
    
    
    // Prototypen der lokalen Funktionen
    void HdlBuffer (void);
    void USART_Init(void);
    void USART_transmit (unsigned char c);
    unsigned char USART_receive (void);
    void USART_transmit_string (unsigned char *string);
    
    int main (void)
    /****************************************************************************
        Hier ist der Programmeinstiegspunkt.
    */
    {
        register BYTE c;       // Letztes empfangenes Zeichen
        register BYTE nCnt;    // Aktueller Zählerwert
        register BYTE n;       // Hilfsvariable
        register BYTE nPortB;  // Hilfsvariable
    
    
        /* UART Control Register laden. Wir verwenden (immer noch)
           keine Interrupts. Hier wollen wir nur empfangen, also wird
           nur das Receiver Enable Flag gesetzt. */
        
    USART_Init();
              
    
        // Port B der Einfachheit halber komplett als Ausgang konfigurieren
        DDRB=0xff;
    	
        // Timer/Counter0 (8-Bit-Timer) initialisieren
        // Wir verwenden den Vorzähler 1024. Warum? Einfach so.
        // Wenn wir einen zu kleinen Vorteiler wählen, dann kommt unser Programm nicht
        // mehr mit und die Ausgangsignale werden unstabil.
        TCCR0|=(1<<CS02)|(1<<CS00); // Vorzaehler = 1024
    	
    	USART_transmit_string("Bitte Kanal:Wert eingeben\r\n");
    	
        // Und jetzt in die Hauptschleife
        for (;;) {
            // Prüfen, ob ein Zeichen empfangen wurde.
            if ((UCSRA) & (1 << RXC)) {     // Bit RXC im USR gesetzt ?
                // Zeichen einlesen
                c = UDR;
    
                // Falls CR, dann Empfangspuffer auswerten, sonst Zeichen speichern,
                // wenn der Puffer nicht bereits überlaufen ist.
                if (c == CR) {
                    // Puffer auswerten
                    szBuffer[nBuffer] = '\0';  // Abschliessendes Nullbyte eintragen
                    HdlBuffer ();
                    nBuffer = 0;    // Puffer wieder initialisieren
                }
                else {
                    if (nBuffer < MAX_BUFFER) {
                       szBuffer[nBuffer++] = c;
                    }
                }
            }
    
            // Zählerwert abfragen
            nCnt = TCNT0;
            nPortB = 0;     // Portinhalt mit 0 initialisieren
            for (n=0; n<CHANNELS; n++) {
               if (nChannels[n] >= nCnt) {
                   // Portbit setzen
                   nPortB |= (1 << n);
               }
            }
            // Resultat auf Port B ausgeben
            PORTB=nPortB;
        }
    
    } /* end of main */
    
    void HdlBuffer (void)
    {
        BYTE *pColon;    // Position des Doppelpunktes
        BYTE nChannel, nVal;
    
        // Doppelpunkt suchen, wenn keiner da ist -> Fehler
        pColon = strchr (szBuffer, ':');
        if (pColon) {
            // Kanal bestimmen
            nChannel = atoi (szBuffer);
            // PWM-Wert bestimmen
            nVal = atoi (pColon + 1);
            // Die Kanalnummer wird zwischen 1 und 4 erwartet
            if (nChannel >= 1 && nChannel <= 4) {
                // und im Array abgespeichert.
                // Achtung: Array-Indizes beginnen immer bei 0, deshalb das - 1
                nChannels[nChannel-1] = nVal;
            }
        }
    
    } /* end of HdlBuffer */
    
    	void USART_Init(void) {
    	    UCSRB = (1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN);
    		UCSRB =  (1<<RXEN) | (1<<TXEN);
    		UBRRL = (unsigned char) USART_BAUD_SELECT;
    	}
    	
    	void USART_transmit (unsigned char c) {
    		while (!(UCSRA & (1<<UDRE))) {}
    		UDR = c;
    	}
    	
    	unsigned char USART_receive (void) {
    		while(!(UCSRA & (1<<RXC))) {}
    		return UDR;
    	}
    	
    	void USART_transmit_string (unsigned char *string) {
    		while (!(UCSRA & (1<<UDRE))) {}
    		while ( *string)
    			USART_transmit (*string++);
    	}
    bitte helft mir!

  2. #2
    oooookay.... dann frag ich mal sorum:

    Wenn ich über den PC (Terminal-Programm) eingegebene Strings im MC auswerten möchte wie muss ich da vorgehen?

    Ist es prinzipiell wie oben oder mit Interrupts?

    ist die USART-Initialisierung so richtig?

    Code:
    #define BAUD 9600      /* 9600 baud */ 
    #define MYUBRR (F_CPU/(BAUD*16L)-1) 
    .
    .
    .
    USART_Init(MYUBRR);
    .
    .
    .
       void USART_Init(unsigned int ubrr)
    {
    	UBRRH=(unsigned char) (ubrr>>8);
    	UBRRL=(unsigned char) ubrr;
    	
    	UCSRB=(1<<RXEN)|(1<<TXEN);
    }
    Ich vermute, dass der MC keine Werte bekommt... aber warum flackern dann die LEDs ganz dunkel?

  3. #3
    Kann mir denn keiner helfen???

Berechtigungen

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