Forum: Mikrocontroller und Digitale Elektronik Mit dem ATmega8 Text auf einen Drucker ausgeben klappt nicht.


von Dussel (Gast)


Lesenswert?

Ich will mit dem ATmega 8 Daten statt auf ein Display auf einen alten 
Star LC10 Drucker mit Parallelport ausgeben.

Zum Verständnis der Parallelschnittstelle habe ich mir ein Board 
gebastelt mit 8 kleinen Schalterchen und einem Taster.

Wenn ich nun die 13 einstelle und den Taster auf Strobe drücke, dann 
zuckt der Drucker, stelle ich die 11 ein, drücke den Taster und dann die 
13 macht der Drucker einen Zeilenvorschub.

Genauso geht das, wenn ich z.B. die 63 einstelle, Taster drücke, usw.
Der Drucker druckt dann auch ein a.

Das Prinzip habe ich also verstanden. Was ich nun aber nicht verstanden 
habe ist die Umsetzung, wie ich das Tasterdrücken in C programmiere und 
wie ich weiß, ob der Drucker mich "verstanden" hat.

Richtigen C Code gibt es noch keinen, weil ich zwar weiß, wie ich 8 Bit 
auf einen Port des ATmega 8 lege, aber dann hört es schon auf, weil ich 
nicht weiß wie ich einen Impuls erzeugen soll _delay_ms(3)    ~PortC(1) 
_delayms(3)    nächstes Byte auf den Augabeport, usw. ...

In der Codesammlung finde ich da auch keinen richtigen Ansatz.

Hat jemand da mal ein nachvollziehbares Beispiel eine Function, von mir 
aus auch als Pseudocode, mit ich dann versuchen kann den ich C zu 
schreiben und zu nutzen.

Danke schon einmal ... Sollte mein erstes, eigenes Projekt mit dem Mega 
8 werden, das ich nicht aus dem Netz nehme und modifiziere ... Leider 
scheitert es schon wieder an irgendwelchen Verständnisschwierigkeiten.

Der Dussel

von Mario G. (mario)


Lesenswert?

Hast du schon mal ein kleines Programm geschrieben á la LED blinken 
lassen oder so?
Nun ja, ich würde doch empfehlen etwas C zu lernen. Du mußt dich auch 
mit dem AVRStudio und WinAVR auseinandersetzen. Die alten Drucker kann 
man auch mit Escape-Zeichenfolgen steuern (wenn du das alte Handbuch 
noch hast, da steht es drin).

Ein Code-snippet zur Ausgabe könnte wie folgt aussehen:
1
char text[32] = {"Hallo Welt"};
2
3
// Todo: Ports einrichten, Variablen definieren usw...
4
5
DDRA   = 0xFF;                   // Daten-Port
6
DDRC  |= (1<<STROBE_PIN)         // Strobe-Port
7
PORTC |= (1<<STROBE_PIN);
8
9
for(i=0; i<strlen(text); ++i)
10
{
11
   PORTA = text[i];
12
   PORTC &= ~(1<<STROBE_PIN);
13
   _delay_ms(3);
14
   PORTC |= (1<<STROBE_PIN);
15
}

bitte nur als Anregung mitnehmen...

von Smarti (Gast)


Lesenswert?

Hallo Dussel,

also das ganze hört sich recht interessant an, also da wäre doch 
naheliegend ne PS/2 Tastatur her zu nehmen und das ganze zur ner 
elektronichen Schreibmaschine zu erweitern ggf. später schreib Buffer 
und mit LCD Display :D

Zum C-Code hier mal ein paar Ansätze:

1. was du ausgeben willst in n array
2. erst mal dein Register auf Ausgang setzten
3. for schleife

1
// ist nur quick and dirty pseudo code, schon ne weile nix mehr mit c gemacht
2
3
main ()
4
{
5
  // var festlegen
6
  char Text[10]="Hallo World";
7
  int i;
8
9
  // controller ini, portb als ausgang
10
  PORTB = 0xff;
11
12
  //schleife
13
14
  for(i=0, i<10, i++)
15
  {
16
     PORTB = Text[i];
17
  }
18
}

von Smarti (Gast)


Lesenswert?

aahh da war jemand schneller, und ich hab das DDRx vergessen... nun ja 
der gute wille zählt :P

von Karl H. (kbuchegg)


Lesenswert?

Smarti schrieb:
> aahh da war jemand schneller, und ich hab das DDRx vergessen...

Du hast noch mehr vergessen :-)

von Karl H. (kbuchegg)


Lesenswert?

Dussel schrieb:

> Richtigen C Code gibt es noch keinen, weil ich zwar weiß, wie ich 8 Bit
> auf einen Port des ATmega 8 lege, aber dann hört es schon auf, weil ich
> nicht weiß wie ich einen Impuls erzeugen soll _delay_ms(3)    ~PortC(1)
> _delayms(3)    nächstes Byte auf den Augabeport, usw. ...

klingt so doch nicht schlecht

> In der Codesammlung finde ich da auch keinen richtigen Ansatz.

Na ja. Für jede Kleinigkeit wirst du dort auch nichts finden.

Was ist den ein Puls?

Eine Leitung liegt auf 0
dann wird se auf 1 gesetzt und kurz darauf wieder auf 0

Und schon hast du einen Puls. Genau das was du mit deinem Taster auch 
gemacht hast.

von Falk B. (falk)


Lesenswert?

@  Dussel (Gast)

>Richtigen C Code gibt es noch keinen, weil ich zwar weiß, wie ich 8 Bit
>auf einen Port des ATmega 8 lege,

Na immerhin.

> aber dann hört es schon auf, weil ich
>nicht weiß wie ich einen Impuls erzeugen soll _delay_ms(3)    ~PortC(1)
>_delayms(3)    nächstes Byte auf den Augabeport, usw. ...

Genau so.

>In der Codesammlung finde ich da auch keinen richtigen Ansatz.

Warum auch. Dad sind so elementare Grundlagen, die findest du 
bestenfalls im tutorial. Aber auch dort ganz sicher nicht als fertige 
Lösung speziell für dein Problem.

>Hat jemand da mal ein nachvollziehbares Beispiel eine Function, von mir
>aus auch als Pseudocode, mit ich dann versuchen kann den ich C zu
>schreiben und zu nutzen.

Alles Stringausgaben, z.B. hier

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

Einfach in der Routinge lcd_string nach jedem Zeichen ein Strobe 
generieren und eine Pause machen. Fertig.

>scheitert es schon wieder an irgendwelchen Verständnisschwierigkeiten.

Dann beschäftige dich mal mit deinem C-Buch und dem Tutorial. Dir fehlen 
noch viele Grundlagen. Ohne die wirst du nicht weit kommen.

MFG
Falk

von pre-increment? (Gast)


Lesenswert?

Mario Grafe schrieb:
1
> char text[32] = {"Hallo Welt"};
2
> 
3
> // Todo: Ports einrichten, Variablen definieren usw...
4
> 
5
> DDRA   = 0xFF;                   // Daten-Port
6
> DDRC  |= (1<<STROBE_PIN)         // Strobe-Port
7
> PORTC |= (1<<STROBE_PIN);
8
> 
9
> for(i=0; i<strlen(text); ++i)
10
> {
11
>    PORTA = text[i];
12
>    PORTC &= ~(1<<STROBE_PIN);
13
>    _delay_ms(3);
14
>    PORTC |= (1<<STROBE_PIN);
15
> }


das wuerde aber "allo Welt" ausgeben?
also wegen dem ++i in der for schleife

von Mario G. (mario)


Lesenswert?

dann eben "i++"... :)

von Karl H. (kbuchegg)


Lesenswert?

pre-increment? schrieb:

> das wuerde aber "allo Welt" ausgeben?

Nein, würde es nicht.
Auch hier sei wieder der Hinweis auf ein C Buch angebracht:
Wann genau wird denn der Inkrement ausgeführt?
Macht es daher einen Unterschied, ob man an dieser Stelle ++i oder i++ 
benutzt?

Trotzdem ist das eine Funktion, die man so nicht schreibt. Aus mehreren 
Gründen.

So würde man das machen
1
#define PRINTER_DATA_PORT      PORTA
2
#define PRINTER_STROBE_PORT    PORTB
3
#define STROBE_PIN             PB3
4
5
void printer_putc( char c )
6
{
7
  PRINTER_DATA_PORT = c;
8
  PRINTER_STROBE_PORT &= ~(1<<STROBE_PIN);
9
  delay_ms( 3 );
10
  PRINTER_STROBE_PORT |=  (1<<STROBE_PIN);
11
  delay_ms( 3 );
12
}
13
14
void printer_puts( const char* text )
15
{
16
  while( *text )
17
    printer_putc( *text++ );
18
}

wobei ich mir jetzt nicht sicher bin, ob der Strobe ein Positivpuls oder 
ein Negativpuls ist. Ich lass es mal so, wie Mario das vorgegeben hat. 
Und natürlich sollte man vorher tunlichst auch noch die Statusleitung 
abfragen, mit der der Printer bekannt gibt, das er aufnahmebereit ist. 
Das kann sonst bei einem Seitenvorschub zu ganz unliebsamen 
Überraschungen führen, wenn man dem Printer seinen internen Cache 
Speicher vollballert.


Aber das schreiben wir dem TO nicht, denn ein wenig C muss er dann schon 
auch selbst lernen wenn er kreativ Programmieren möchte und nicht immer 
nur in vorhandenen Programmen Kleinigkeiten ändern will.
Sein Ansatz, die Dinge zuerst händisch mittels einem Taster 
auszuprobieren, gefällt mir grundsätzlich. Nur den Schritt der Analyse, 
welchen Pegel daher eine Leitung hat und wie man das mit Bit setzen bzw. 
löschen in einem Programm nachbildet, den muss er noch machen. Obwohl: 
genau das ist doch eigentlich die erste Übung in der µC Programmiererei: 
Einen Pin gezielt auf 1 oder 0 zu setzen. Nur hängt halt bei den ersten 
Übungen eine LED an diesem Pin und kein Drucker der auf den Puls wartet. 
Aber das Prinzip ist genau das gleiche.

von Peter (Gast)


Lesenswert?

pre-increment? schrieb:
> das wuerde aber "allo Welt" ausgeben?
> also wegen dem ++i in der for schleife

ihr bringt ja na völlig durcheinandern, aber es ist an dieser stelle 
egal ob ++i oder i++ steht. Es wird immer nach dem schleifendurchlauf 
gerechnet.

(wenn ich mich irre, liegt es an den 30Grad im Zimmer)

von Falk B. (falk)


Lesenswert?

@Karl heinz Buchegger (kbuchegg) (Moderator)

>Aber das schreiben wir dem TO nicht, denn ein wenig C muss er dann schon
>auch selbst lernen wenn er kreativ Programmieren möchte

Ähhh, Karl, du führst Selbstgespräche mit offenem Mund . . .

von Karl H. (kbuchegg)


Lesenswert?

Falk Brunner schrieb:
> @Karl heinz Buchegger (kbuchegg) (Moderator)
>
>>Aber das schreiben wir dem TO nicht, denn ein wenig C muss er dann schon
>>auch selbst lernen wenn er kreativ Programmieren möchte
>
> Ähhh, Karl, du führst Selbstgespräche mit offenem Mund . . .

Das ist eines meiner Markenzeichen.
Meine Kollegen haben sich schon daran gewöhnt, dass ich in 
Nachdenkphasen schon mal durch die Gänge schlürfe und mir selbst das 
Problem erkläre.

Sie amüsieren sich jetzt nur noch darüber, dass ich bei 
Geometrieproblemen auch noch Armverrenkungen dazu mache :-)

von bix (Gast)


Lesenswert?

Dussel schrieb:
> und
> wie ich weiß, ob der Drucker mich "verstanden" hat.

Da möchte ich noch das Stichwort "Handshake" in the Schredd werfen. Der 
Drucker signalisiert damit, dass er ein Byte empfangen hat. (Wartezeiten 
mittels _delay_ms() sind damit überflüssig und man weiß ja nie, ob das 
gewählte delay nich doch mal zu kurz gewählt ist)

Es gibt auch noch andere interessante Signale am Printer Port. Man kann 
z.B. erkennen ob der Drucker "offline" ist oder ob Papier fehlt.

von Simon K. (simon) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Falk Brunner schrieb:
>> @Karl heinz Buchegger (kbuchegg) (Moderator)
>>
>>>Aber das schreiben wir dem TO nicht, denn ein wenig C muss er dann schon
>>>auch selbst lernen wenn er kreativ Programmieren möchte
>>
>> Ähhh, Karl, du führst Selbstgespräche mit offenem Mund . . .
>
> Das ist eines meiner Markenzeichen.
> Meine Kollegen haben sich schon daran gewöhnt, dass ich in
> Nachdenkphasen schon mal durch die Gänge schlürfe und mir selbst das
> Problem erkläre.

Das zeugt ja auch von einem belebten Geist! ;-)

von Wolfgang S. (wsm)


Lesenswert?

Strobe ist negativ.

Ob der Drucker Daten empfangen kann oder Busy ist muss abgefragt werden.

Im Netz findet man viele Diagramme für den Parallelport.

Das 8. Bit muss natürlich in der Regel "0" sein.

Im folgenden Programm wird eine Reihe von Zeichen aus einem Array 
ausgegeben. Bit 7 wird als Strobe benutzt und extern auf "0" gesetzt.
1
 'S-Ausgaben an Plotter
2
 'Mit Gosub  OUTSTRING aufrufen
3
4
Ms:
5
       S = " MS 0" : Goto Outstring               'Maßstab festlegen
6
Ap_100_100:
7
      S = "AP 100 100" : Goto Outstring
8
Ss:
9
      S = "SS" : Goto Outstring                   'Stift senken
10
Sh:
11
      S = "SH"                                    'Stift Heben
12
13
Outstring:
14
Pos = 0 : L = Len(s)
15
Do
16
      Do : Loop Until Pinc.5 = 0                  'Warten bis BUSY=0
17
      Waitms 5
18
      Incr Pos
19
20
      Portd = S_byte(pos) Or 128                  'Ausgabe des Bytes
21
      Gosub Wait50                                'Strobe erzeugen
22
      Portd.7 = 0
23
      Gosub Wait50
24
      Portd.7 = 1
25
Loop Until L = Pos
26
27
      Do : Loop Until Pinc.5 = 0                  'Warten bis BUSY=0
28
      Waitms 5
29
      Ch = 13 + 128                               ' 0D ausgeben
30
      Portd = Ch
31
      Gosub Wait50
32
                     'Strobe erzeugen
33
      Portd.7 = 0
34
      Gosub Wait50
35
      Portd.7 = 1
36
      Waitms 5
37
38
Return
39
40
Wait50:
41
      Waitus 50
42
Return

von sven (Gast)


Lesenswert?

frage nebenbei gibt es auch eine vergleichbar simple lösung für nen usb 
drucker ?
mfg

von ... (Gast)


Lesenswert?

Simpel? Eher nicht.
Erstens brauchst Du einen USB-Host (oder OTG). Und zweitens muß irgendwo 
auch der USB-Protokollstack laufen.
Keine Ahnung, ob sowas eventuell mit einem der USB-AVR geht, aber simpel 
mit ziemlicher Sicherheit nicht.
Am ehesten wohl noch mit einem der größeren µC auf denen Linux läuft 
(AVR32,ARM,...).

von Fer T. (fer_t)


Lesenswert?

Sicher nicht simpel, weil USB selber schon recht komplex ist, und ich 
denke man braucht da echt was "großes" wie ein ARM...

von ... (Gast)


Lesenswert?

Achso noch vergessen.
USB-Drucker sind oft reine GDI-Drucker. Das komplette Rastern der 
Ausgabe erfolgt im Druckertreiber auf dem PC und der Drucker bekommt im 
Prinzip nur noch ein riesen Bitmap vorgesetzt.
Wenn Du Glück hast, versteht der Drucker wenigstens noch PCL, oder wenn 
er teuer genug ist, eventuell auch Postscript. Würde die Sache zwar 
erheblich vereinfachen, simpel ist das aber trotzdem noch lange nicht.

von Dussel (Gast)


Lesenswert?

Mensch Danke an euch ...

mit LED an den restlichen Leitungen kann ich tatsächlich erkennen, ob 
Paper Out, Busy (Die blitzt kurz, wenn ich meinen Strobe Taster 
(Schaltet Masse auf den Pin und ist mit 10 kOhm gegen Plus im 
Ruhezustand), Offline ...

Habe mir in der Bibliothek mal den Kerningham Richie besorgt ... C ist 
ganz schön kompliziert. Vor allem, wenn man sich das AVR C Tutorial hier 
im Forum anschaut und dann versucht den Code zu verstehen.

Gibt es eigentlich eine deutsche Version der Beschreibung für die AVR C 
Funktionen aus der Bibliothek ?

Ich habe mir die bei Sourceforge mal runtergeladen und dann 
durchgeforstet. Wenn ich das richtig sehe, dann ist bei einem Programm 
für den AVR eigentlich mehr das Verständnis für die AVR Lib gefragt, als 
das Verständnis für C.

Ab morgen habe ich frei bis Montag. Dann werde ich mich mit dem Code aus 
dem Thread hier beschäftigen und vor allem mit den Anderen Signalen auf 
dem Parallelport.

Ich gehe nun auf Nachschicht.

Der Dussel

von Karl H. (kbuchegg)


Lesenswert?

Dussel schrieb:

> Habe mir in der Bibliothek mal den Kerningham Richie besorgt ...

Eine kluge Entscheidung!


> Ich habe mir die bei Sourceforge mal runtergeladen und dann
> durchgeforstet. Wenn ich das richtig sehe, dann ist bei einem Programm
> für den AVR eigentlich mehr das Verständnis für die AVR Lib gefragt, als
> das Verständnis für C.

Kommt drauf an.
Auf der Ebene, auf der du momentan arbeitest, brauchst du im 
wesentlichen momentan nur das Veständnis wie man einen Portpin auf 1 
bzw. wieder auf 0 setzt.
Das ist zwar im Grunde auch nur Standard-C, allerdings kommt das in der 
Programmierung ausserhalb der µC selten vor, so dass sich in der 
Standardliteratur da eher wenig darüber findet. Und genau da setzt dann 
das AVR-GCC-Tutorial ein. Es baut darauf auf, das C Kenntnise schon 
vorhanden sind und erklärt die Besonderheiten in der µC Programmierung.

Und ja: spätestens dann, wenn es darum geht, die im µC eingebaute 
Hardware zu benutzen, dann dann sind die Standardwerke logischerweise am 
Ende. Dann gilt nur noch das Datenblatt, bzw. die aus dem Datenblatt 
aufbereitete Form im Tutorial.

von Blackmore (Gast)


Lesenswert?

Interessantes Projekt, könnt ich später auch gebrauchen...

Im Moment brauch ich jedoch die andere Richtung, Daten, die am 
parallelen Ausgang rauskommen mit'm Mega abfangen, auf SDCard speichern, 
auf nem LCD ausgeben und auf Tastendruck auf nem angeschlossenen Drucker 
ausgeben...

Aber das ist noch Zukunftsmusik...

Gruß Blackmore

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.