- LiFePO4 Speicher Test         
Ergebnis 1 bis 10 von 15

Thema: Anfänger Quellcode

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Benutzer Stammmitglied Avatar von Matthias 321
    Registriert seit
    09.09.2009
    Ort
    nahe Nürnberg
    Beiträge
    35

    Anfänger Quellcode

    Hallo Leute,
    ich bin ja schon länger im Bereich AVR Programmierung unterwegs. Allerdings bisher in Basic. Jetzt wollte ich ein neues Projekt anfangen (bzw. ein altes wieder aufnehmen), nur dass ich es diesmal in C verwirklichen will. Ich will einen Drucker ansteuern, per Parallel-Port versteht sich, und habe dazu das hier gefunden. Ich hab allerdings ein anderes Board und daher auch eine andere Pinbelegung. Ich als Basicer bin erschlagen von der Komplexität der Sprache C was Port- und Pinzuweisungen angeht, Basic ist eben doch sehr einfach gestaltet. Nun hab ich mich daran gemacht den Quellcode von obigem Link an meine Umgebung anzupassen, und wollte nun von euch wissen, ob ich alles (oder wenigstens etwas...) richtig gemacht hab, bevor ich mir meinen Drucker damit zerschieße.
    Hier mein Code:
    Code:
     //----------------------------------------------------------------------
    #define     F_CPU 16000000  // Taktfrequenz des myAVR-Boards
    #include    <avr\io.h>      // AVR Register und Konstantendefinitionen
    #include    <util/delay.h>
    //----------------------------------------------------------------------
    
    void init_io(void);
    void strobe(void);
    
    int main(void) 
    {
        init_io();
        unsignedchar string[12] = "Hello World!"; //Text string
    
    PINF = (1<<PINF2); //Setzt Strobe auf high
    
    while(PINK == 255); //Wartet auf einen Tastendruck
    for (unsignedchar i = 0; i <= 12; i++) //Liest alle Stellen des String
        {
            PORTA = string[i]; //Legt die Zeichen an den Datenausgang
            strobe(); //Sagt dem Drucker, dass Daten anliegen
    while(PORTB == 1); //Wartet auf die Bestätigung des Druckers, dass Daten empfangen wurden
        }
    
    }
    
    void init_io(void)
    {
        DDRE = 0b11111111; //Datenleitungen DATA0-7
    DDRF = 0b10100111; //Steuerleitungen vom/zum Drucker
    //PF0: nc       Out
    //PF1: nc       Out
    //PF2: Strobe   Out
    //PF3: Busy     In
    //PF4: ACK      In
    //PF5: INIT     Out
    //PF6: ERROR    In
    //PF7: Autofeed Out
    DDRK = 0b00000000; //An alle Pins sind Taster angeschlossen
    PORTK = 0; //Pull-Up nicht setzen
    PORTF |= (1<<PinF7); //Schaltet Autofeed ein
    }
    
    void strobe(void)
    {
        PINF = ~(1<<PINF2); //Setzt Stobe auf low = Drucker soll empfangen
        _delay_ms(1);
        PINF = (1<<PINF2);  //Setzt Strobe wieder auf high
    }
    
    //----------------------------------------------------------------------
    
    Verwendet wird ein ATMega 2560 und das myAVR Workpad. Achja, ich wollte den Code vom ersten Beispiel im Link übersetzen, sollte ich vlt. dazusagen.

    MfG
    Matthias
    Vergesslichkeit ist doch recht nützlich: Man spart viel Zeit

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    33
    Beiträge
    1.192
    Hallo,
    das meiste sollte so passen, allerdings stimmt bei den PORT- und PIN-Registern manches nicht.
    Das ist so gedacht:
    Das DDRx-Register legt fest, ob ein Anschluss Eingang(0) oder Ausgang(1) sein soll.
    Ist der Anschluss als Ausgang eingestellt, kannst du den mit dem PORTx-Register auf High oder Low setzen.
    Ist der Anschluss als Eingang eingestellt, kannst du mit dem PORTx-Register die Pullup-Widerstände aktivieren/deaktivieren.
    Willst du einen Eingang abfragen, musst du das PINx-Register auslesen.

    So müsste das meiner Meinung nach aussehen:
    Code:
     //----------------------------------------------------------------------
    #define     F_CPU 16000000  // Taktfrequenz des myAVR-Boards
    #include    <avr\io.h>      // AVR Register und Konstantendefinitionen
    #include    <util/delay.h>
    //----------------------------------------------------------------------
    
    void init_io(void);
    void strobe(void);
    
    int main(void) 
    {
        init_io();
        unsigned char string[12] = "Hello World!"; //Text string
    
        PORTF = (1<<PF2); //Setzt Strobe auf high
    
        while(PINK == 255); //Wartet auf einen Tastendruck
        for (unsigned char i = 0; i <= 12; i++) //Liest alle Stellen des String
        {
            PORTA = string[i]; //Legt die Zeichen an den Datenausgang
            strobe(); //Sagt dem Drucker, dass Daten anliegen
            while(PINF == 1); //Wartet auf die Bestätigung des Druckers, dass Daten empfangen wurden
        }
       return 0;
    }
    
    void init_io(void)
    {
        DDRE = 0b11111111; //Datenleitungen DATA0-7
        DDRF = 0b10100111; //Steuerleitungen vom/zum Drucker
        //PF0: nc       Out
        //PF1: nc       Out
        //PF2: Strobe   Out
        //PF3: Busy     In
        //PF4: ACK      In
        //PF5: INIT     Out
        //PF6: ERROR    In
        //PF7: Autofeed Out
        DDRK = 0b00000000; //An alle Pins sind Taster angeschlossen
        PORTK = 0; //Pull-Up nicht setzen
        PORTF |= (1<<PF7); //Schaltet Autofeed ein
    }
    
    void strobe(void)
    {
        PORTF = ~(1<<PF2); //Setzt Stobe auf low = Drucker soll empfangen
        _delay_ms(1);
        PORTF = (1<<PF2);  //Setzt Strobe wieder auf high
    }
    
    //----------------------------------------------------------------------
    Vermutlich wird man noch die while-Schleifen anpassen müssen, in der verlinkten Seite wird bei der zweiten while-Schleife das ACK abgefragt, ist bei dir an PF4 ?

    Grüße, Bernhard

  3. #3
    Benutzer Stammmitglied Avatar von Matthias 321
    Registriert seit
    09.09.2009
    Ort
    nahe Nürnberg
    Beiträge
    35
    Ok, vielen Dank! Das System der Pin und Port Register hatte ich noch nicht so recht verstanden.

    Stimmt, um die While-Schleife hab ich mich noch nicht gekümmert. PORTA hat da garnix zu suchen. Und ACK ist an PF4, das ist richtig.
    Vergesslichkeit ist doch recht nützlich: Man spart viel Zeit

  4. #4
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Vielleicht funktioniert es auch nur mit Busy:

    Code:
    // Druckeransteuerung mit AVR über Centronics-Schnittstelle                     mic 7.4.2012
    
    // https://www.roboternetz.de/community/threads/57421-Anf%C3%A4nger-Quellcode
    
    // PORTE ist D0-D7
    // PORTF sind die Steuersigale:
    
    // PF0: Selin    Out Low = Drucker ausgewählt
    // PF1: nc       Out
    // PF2: Strobe   Out fallende Flanke = Datenübernahme
    // PF3: Busy     In  Low = nicht beschäftigt
    // PF4: ACK      In  Low = Übernahmebestätigung
    // PF5: INIT     Out Low = Drucker initialisieren
    // PF6: ERROR    In  Low = Fehler aufgetreten
    // PF7: Autofeed Out Low = Linefeed bei CR
    
    // http://www.hardwareecke.de/berichte/schnittstellen/centronics.php
    // http://de.wikipedia.org/wiki/IEEE_1284
    
    #define     F_CPU 16000000  // Taktfrequenz des myAVR-Boards
    #include    <avr\io.h>      // AVR Register und Konstantendefinitionen
    #include    <util/delay.h>
    
    int main(void)
    {
    	unsigned char i;
    	unsigned char text[14] = "Hello World!\n\r"; //Text string + LFCR
    
    	DDRE = 0b11111111; // Datenleitungen DATA0-7
    	DDRF = 0b10100111; // Steuerleitungen vom/zum Drucker
    	DDRK = 0b00000000; // An alle Pins sind Taster angeschlossen
    	PORTK= 0b00000000; // Wie sind die Taster angeschlossen?
    	//PORTK= 0b11111111; // bei Bedarf Tastenpullups einschalten
    
    	PORTF |= (1<<PF7); //Schaltet Autofeed aus
    	PORTF |= (1<<PF2); //Setzt Strobe auf high
    
    
    	while(PINK == 255); //Wartet auf einen Tastendruck
    
    	for (i = 0; i<14; i++) //Liest alle Stellen des String (Index 0 bis 13!)
    	{
    		while(PINF & (1<<PF3)); // Warten wenn Drucker beschäftigt (busy=high)
    		PORTE = text[i]; // Legt die Zeichen an den Datenausgang
    
    		PORTF &= ~(1<<PF2); // Setzt Stobe auf low = Drucker Daten übernehmen
    		_delay_ms(1);
    		PORTF |= (1<<PF2); // Setzt Strobe wieder auf high
    		_delay_ms(1);
    	}
    
    	while(1); // Programm darf nie beendet werden!
    	return(0);
    }
    (ungetestet)

    Gruß

    mic

    P.S.:
    Achtung, alle nicht extra gesetzte Steuersignale zum Drucker sind low!
    Geändert von radbruch (07.04.2012 um 12:35 Uhr) Grund: LFCR senden + while(PINF & ...
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  5. #5
    Benutzer Stammmitglied Avatar von Matthias 321
    Registriert seit
    09.09.2009
    Ort
    nahe Nürnberg
    Beiträge
    35
    Ok, ich hab genau deinen Code übernommen (außer dass ich keine SelectIn Leitung hab) und folgendes passiert: Der Drucker meldet Error, vermutlich weil die Tinte leer ist, das zeigt er auch an. Strobe ist auf high, passt. Autofeed ist an, passt auch. Allerdings wird der Chip warm (bin ich nicht gewöhnt, kann aber daran liegen, dass er sich in einer Schleife aufhängt, die recht rechenintensiv ist) und, was noch schlimmer ist, der Drucker meldet ständig "Busy", sobald ich ihn anschließ. Und er initialisiert sich, ist auch nicht geplant. Einen richtigen Rest bekomm ich aber nicht hin, da der Chip über den Drucker mit Strom versorgt wird, am Strobe liegt ja eine gewisse Spannung an, mit der der Drucker low erkennt. Aber an sich macht der Drucker nichts, ACK ist auch immer high, selbst wenn der Drucker nicht mit dem Board verbunden ist.

    MfG
    Matthias

    PS: Ich warte mit dieser Schleife auf einen Tastendruck, ist die so richtig? PINK ist lustigerweise rot im Editor ^^ while(!(PINK & (1<<PINK0))); //Wartet auf einen Tastendruck"
    Vergesslichkeit ist doch recht nützlich: Man spart viel Zeit

  6. #6
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Bin ja kurz davor 'nen alten Drucker zu reanimieren. ;)

    Hier nun eine verbesserte Variante:

    Code:
    // Druckeransteuerung mit AVR über Centronics-Schnittstelle                     mic 7.4.2012
    
    // https://www.roboternetz.de/community/threads/57421-Anf%C3%A4nger-Quellcode
    
    // PORTE ist D0-D7
    // PORTF sind die Steuersignale:
    
    // PF0: nc       Out Low = Drucker ausgewählt
    // PF1: nc       Out
    // PF2: Strobe   Out fallende Flanke = Datenübernahme
    // PF3: Busy     In  Low = nicht beschäftigt
    // PF4: ACK      In  Low = Übernahmebestätigung
    // PF5: INIT     Out Low = Drucker initialisieren
    // PF6: ERROR    In  Low = Fehler aufgetreten
    // PF7: Autofeed Out Low = Linefeed bei CR
    
    // http://www.hardwareecke.de/berichte/schnittstellen/centronics.php
    // http://de.wikipedia.org/wiki/IEEE_1284
    
    #define strobe (1<<PF2)
    #define busy (1<<PF3)
    #define ack (1<<PF4)
    #define init (1<<PF5)
    #define error (1<<PF6)
    #define autofeed (1<<PF7)
    
    #define     F_CPU 16000000  // Taktfrequenz des myAVR-Boards
    #include    <avr\io.h>      // AVR Register und Konstantendefinitionen
    #include    <util/delay.h>
    
    int main(void)
    {
    	unsigned char i, t;
    	unsigned char text[14] = "Hello World!\n\r"; //Text string + LFCR
    
    	DDRE = 0b11111111; // Datenleitungen DATA0-7
    
    	DDRF = strobe | init | autofeed; // Steuerleitungen zum Drucker (Ausgänge)
    	PORTF = strobe | init | autofeed; // Kein strobe, kein init und kein autofeed
    	PORTF = busy | ack | error; // PullUps für die Eingangssignale aktivieren
    
    	t=PINK; // Tastenstatus einlesen
    	while(PINK == t); // Hat sich was geändert?
    
    	for (i = 0; i<14; i++) //Liest alle Stellen des String (Index 0 bis 13!)
    	{
    		while(PINF & busy); // Warten wenn Drucker beschäftigt (busy=high)
    		PORTE = text[i]; // Legt die Zeichen an den Datenausgang
    
    		PORTF &= ~strobe; // Setzt Stobe auf low = Drucker Daten übernehmen
    		_delay_ms(1);
    		PORTF |= strobe; // Setzt Strobe wieder auf high
    		_delay_ms(1);
    	}
    
    	while(1); // Programm darf nie beendet werden!
    	return(0);
    }
    (ebenfalls ungetestet)

    Ich vermute, der Drucker wurde dauernd im Init gehalten. Diese Version setzt nun auch das Init-Bit.

    Nach dem Reset ist Port K sowieso Eingang, deshalb braucht man keine zusätzliche Initialisierung. Allerdings weiß ich immer noch nicht, wie die Taster angeschlossen sind. Schalten sie gegen Vcc oder gegen GND? Externe PullUps/PullDowns?

    Der String endet mit LFCR, deshalb kann man das Autofeed beim Drucker deaktivieren. Wenn's mal klappt kannst du das ja ändern...

    Die PullUps an den Eingängen sind eher ein Versuch, scheint mir vernünftig. Port K wird bei mir (KamAVR) akzeptiert.

    Gruß

    mic

    P.S.: Der Mega2560 hat tatsächlich einen Port K: http://www.atmel.com/Images/doc2549.pdf
    (Über 'nen Mega32u4 bin ich noch nicht hinausgekommen...)
    Geändert von radbruch (07.04.2012 um 19:39 Uhr)
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  7. #7
    Benutzer Stammmitglied Avatar von Matthias 321
    Registriert seit
    09.09.2009
    Ort
    nahe Nürnberg
    Beiträge
    35
    Ahhh, ich ich glaub ich habs! "34: error: initializer-string for array of chars is too long" Dieser Fehler hat mich stutzig gemacht, ich dachte du hättest einen Fehler gemacht, da du das in einer 14 "langen" Stringvariable speichern willst, obwohl es ja 16 Lettern sind. \n und \r werden von meinem Compiler/Interpreter oder was auch immer dafür zuständig ist nicht als eigenständiges ASCII Zeichen bzw. Befehl erkannt! In der ersten Version hab ich's einfach "verbessert". Robotik Visionäre soll man nicht anzweifeln...

    Und vielen Dank wegen dem "#define strobe (1<<PF2)", sowas hab ich gebraucht, ist einfach übersichtlicher.

    EDIT: Ganz vergessen: Die Taster sind aktiv high, zumindest schließe ich das aus diesem Datenblatt.
    Vergesslichkeit ist doch recht nützlich: Man spart viel Zeit

Ähnliche Themen

  1. [ERLEDIGT] Ideen zum Quellcode
    Von Tobias Stosius im Forum Asuro
    Antworten: 13
    Letzter Beitrag: 25.05.2011, 15:18
  2. LDR Quellcode
    Von Jada im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 0
    Letzter Beitrag: 03.06.2010, 20:26
  3. Quellcode für Geschwindigkeitsmessung
    Von Tanja1986 im Forum C - Programmierung (GCC u.a.)
    Antworten: 17
    Letzter Beitrag: 12.10.2008, 13:53
  4. Bootloader 1.3 quellcode???
    Von raid_ox im Forum Asuro
    Antworten: 41
    Letzter Beitrag: 10.11.2007, 12:25
  5. Quellcode zu RNKC10
    Von Kjion im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 3
    Letzter Beitrag: 19.06.2005, 16:26

Berechtigungen

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

12V Akku bauen