Mit dem ATmega8 Text auf einen Drucker ausgeben klappt nicht.

Gast #1741745
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
#1741768
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...
Gast #1741782
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
}
#1741792
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.
#1741809
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
Gast #1741810
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
#1741886
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.
#1741902
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 :-)
Gast #1742070
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.
Persönliche Seite #1742170
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! ;-)
#1742174
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
Gast #1742321
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.
Gast #1743613
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
#1743626
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.
Gast #1743630
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren