mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Ausgabe eines Wortes auf die RS232


Autor: Thorsten Fischer (thorstencux)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich heiße Thorsten und würde gerne etwas mehr
mit PIC Prozessoren machen und lernen.
Ich hoffe hier kann mir etwas geholfen werden.
Ich sitze seit Tagen an einem Projekt mit einem PIC 16F84A.

Eigentlich möchte ich nur einen Text auf die RS232 senden.
Ich habe einen asm code bei www.sprut.de gefunden. Dieser gibt
den Buchstaben "A" immer wieder aus. Als erstes Versuchsprogramm
dachte das das ganz nett wäre. Leider bekomme ich es nicht hin aus dem 
"A"
ein Wort zu machen. Ich denke da fehlt das ein oder andere noch im 
Programm.
Ist es möglich das mir hier mal jemand etwas hilft?

Kann man mir bei diesem Problem helfen??

Eine kurze email wäre toll!!!


Gruß Thorsten

Autor: Worschtsupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde es mal so probieren:

Loop
  movlw  'H'
         call  Send_RS
        movlw  'a'
         call  Send_RS
        movlw  'l'
         call  Send_RS
        movlw  'l'
         call  Send_RS
        movlw  'o'
         call  Send_RS

  goto  Loop

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen vielen Dank !!!!
Das haut ja schon super hin.

Würde es eigentlich gehen, wenn ich dort noch ein nop
einfüge, daß die Wiederholrate etwas langsamer wird ???

Gruß und 1000 Dank Thorsten


Loop
  movlw  'H'
         call  Send_RS
        movlw  'a'
         call  Send_RS
        movlw  'l'
         call  Send_RS
        movlw  'l'
         call  Send_RS
        movlw  'o'
         call  Send_RS
        nop
        nop
  goto  Loop

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ja, geht. Aaaaber: schau mal nach, wieviele Takte Dein PIC für einen 
nop-Befehl braucht. Dann rechne mit Deiner benutzten Taktfrequenz die 
Zeit für einen nop aus.
Dann versinke in tiefes Nchdenken. ;)

Denkaufgabe: wie programmiere ich eine Warteschleife bestimmter Dauer...

Gruß aus Berlin
Michael

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michael,

du hast natürlich recht.
Das wären dann 6 Zyclen Schleife.
Ich würde natürlich gerne eine Warteschleife von etwa 10sec
programmieren. Aber wie schon gesagt ich lerne gerade erst das
Stehen. vom Laufen und rennen bin ich noch sehr weit entfernt.
Mein Lösungsversuch würde so aussehen:

Wait250
        movlw   D'10000'  ; 10sec Pause


Hoffe ich bin da auf dem richtige Weg .....

Grüße aus dem Norden!!!

Autor: Worschtsupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hoffe ich bin da auf dem richtige Weg .....

Nicht ganz, denn du mußt noch berücksichtigen, dass 'W' 8 Bit breit ist. 
D. h. es geht höchstens ein

movlw D'255'

Also mußt du da mehrmals ineinander schachteln, am besten unter 
Zuhilfenahme weiterer Register. Aber das schöne ist ja, dass du mit 
MPLAB sehr genau simulieren kannst. Viel Spaß :)

Kleiner Tip noch zu PICs: http://www.sprut.de

Dort gibts auch massenhaft guter Infos.

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenigstens mal jemand der relativ klein anfängt. Lobenswert.

Um ne Verzögerung zu bekommen machst du am einfachsten sowas in der Art:

DelayCounter equ 0x20 ; Variable anlegen


main
   ...
   ...
   ...
   movlw 0xFF
   movwf DelayCounter
   call delay
   ...



delay
    decfsz  DelayCounter,f
    goto delay
    return


was immer wichtig ist: mitrechnen wie lange die ganze Aktion dauert, 
dass man ein Gefühl dafür bekommt.



@ Worschtsupp
Hast du den ersten Post gelesen g

Autor: Worschtsupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups :) Ja da war was...

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reicht dieser eine Befehl aus um 250ms zu verzögern????

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Antwort 1:
Ja, bei einer Taktfrequenz von 16 Hz.

Antwort 2:
Nein, du musst eine Schleife bauen so wie ich es geschrieben habe.

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun habe ich ( Ihr ) es also hinbekommen das das Wort hallo immer wieder 
wiederholt wird.
Das ist schon fast das was ich haben wollte.
Wie geht aber nun ein Zeilenumbruch. Also so sieht es jetzt aus:
hallohallohallohallo   usw.
Ich würde es aber gerne -

hallo
hallo
hallo
hallo
haben.

@ willivonbienemaya:

DelayCounter equ 0x20 ; Variable anlegen
main
   ...
   ...
   ...
   movlw 0xFF
   movwf DelayCounter
   call delay
   ...
delay
    decfsz  DelayCounter,f
    goto delay
    return

Das habe ich noch nicht  so ganz verstanden.
Wo kann ich denn den Wert für die Verzögerung eingeben?

Gruß Thorsten

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mal die Datei so eingefügt.
Das wORT wird nun 4 Mal ausgegeben und dann bleibt alles stehen....

Was das wohl wieder ist ?????

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir das Programm mal an.
Das ist nicht schwer zu verstehen.

Die Variable in Counter wird einfach runtergezählt bis sie null ist. 
erst dann gehts weiter.

du kannst also die verzögerung hier verändern: movlw 0xFF

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zu dem Problem mit der neuen Zeile musst du nur das ascii zeichen für 
Carriage Return raussuchen und ein PC terminal benutzen dass es 
unterstützt.

http://de.wikipedia.org/wiki/ASCII

Du brauchst 0x0D

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
willivonbienemaya wrote:
> Schau dir das Programm mal an.
> Das ist nicht schwer zu verstehen.
>
> Die Variable in Counter wird einfach runtergezählt bis sie null ist.
> erst dann gehts weiter.
>
> du kannst also die verzögerung hier verändern: movlw 0xFF

movlw 0xFF    <--- hmm grübel grübel.....

könntest Du mir bitte mal ein Beispiel für 2Sek geben???

Und wie bekomme ich den Zeilenumbruch hin???


Gruß und Danke Thorsten

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst dir etwas mehr Zeit zum Grübeln lassen glaube ich.

wieviel takte musst du verbraten um auf zwei sekunden zu kommen?
ich kann es nicht wissen, da ich nicht weiss wie schnell dein controller 
läuft.

den zeilenumbruch bekommst du auch hin.

einzelne zeichen kannst du doch senden.

probier doch einfach mal aus was passsiert wenn du das zeichen 0x0D 
sendest.

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also mein Professor läuft mit 4MHz Takt.
Das mit dem 0x0D habe ich schon probiert.
Ich weiß nur nicht wie ich es senden soll.
Zur Zeit sieht es ja so aus:

Loop
  movlw  'H'
         call  Send_RS
        movlw  'a'
         call  Send_RS
        movlw  'l'
         call  Send_RS
        movlw  'l'
         call  Send_RS
        movlw  'o'
         call  Send_RS

Soll ich hier so eine Zeile einfügen???

call Send_0x0D


  goto  Loop

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du weisst noch nicht so ganz was du da eiegntlich tust.

ein stück deines codes:
  movlw  'H'
  call  Send_RS

du lädst 0x48 ins W Register udn rufst dann ein Unterprogramm auf.
das solltest du verstehen.
nimm dir zeit dafür.

dann kannst du auch eine 0x0D senden.



4 MHz bedeutet, dass er für einen Takt 1µs brauchst.
Den Rest müsstest du hinbekommen.

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal....

Das mit der Verzögerung habe ich tatsächlich hinbekommen.
Nur ich bekomme einfach keinen Zusammenhang mit dem return Befehl
( 0x0D ) zustande.
MPLap zeigt mir auch keinen Fehler. Aber es wird halt immer nur das
Hallo hintereinander ausgegeben.

vieleicht noch so : putcUSART(0x0D)

Wie gesagt ich tappe da VOLL im dunkeln.
Bekomme auch erst morgen meine beiden Bücher über PIC´s

Gruß Thorsten

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thorsten Fischer wrote:
> Hallo nochmal....
>
> Das mit der Verzögerung habe ich tatsächlich hinbekommen.
> Nur ich bekomme einfach keinen Zusammenhang mit dem return Befehl
> ( 0x0D ) zustande.
> MPLap zeigt mir auch keinen Fehler. Aber es wird halt immer nur das
> Hallo hintereinander ausgegeben.
>
> vieleicht noch so : movlw  'h '
                      call  Send_RS
                      movlw  0x0d
                      call  Send_RS
>
> Wie gesagt ich tappe da VOLL im dunkeln.
> Bekomme auch erst morgen meine beiden Bücher über PIC´s
>
> Gruß Thorsten

Autor: Dieter Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ASCII Zeichensatz besteht aus darstellbaren Zeichen und 
Steuerzeichen.
Die darstellbaren Zeichen kann man (wie oben schon zu sehen) mit
movlw 'X' in das W-Register laden.

Für das Steuerzeichen "return" geht das etwas anders, nämlich
  movlw  0x0D    und danach
  call  Send_RS

Unter Umständen benötigt man auch noch ein "line feed"
  movlw  0x0A
  call  Send_RS

Viel Erfolg

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muß man das aufm PIC wirklich immer so umständlich machen oder geht das 
nicht auch einfacher ?


Z.B. beim 8051 schreibe ich einfach:
mainloop:
        call    out_text
        db      'Hallo Welt', 0Ah, 0Dh
        db      0                      ;end mark

        call    delay_ms
        dw      10000

        jmp     mainloop

Und out_text bzw. delay_ms POPen sich dann einfach vom Stack die 
Returnadresse als Pointer auf die konstanten Daten, machen was damit und 
kehren dann hinter die Daten zurück.

Man hat doch öfters Texte auszugeben und möchte die auch bequem ändern 
können.


Peter

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist keine Möglichkeit bekannt wie das mit dem mini Befehlssatz der 
16er PIC´s möglich ist. Er beherrscht ja nur 35 Befehler soweit ich mich 
erinnere, da sieht vieles kompliziert aus.
Aber ich lasse mich gerne eines besseren belehren.


Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@peter
wie findet denn dein Programm nach call out_text call delay_ms? Müsste 
doch nach ret im Nirwana landen? Ist ne Weile her, aber das scheint mir 
suspekt.

Autor: Winfried J. (Firma: Nisch-Aufzüge) (winne)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
~willivonbienemaya
Das ist bei anderen Prozessoren nicht anders, einer Routine / eines 
makros bedarf es zur Stringausgabe immer. Und wenn der Pic nicht zählen, 
vergleichen und schubsen könnte wäre er längst tot. Aber mehr bedarf es 
zur Stringasgabe nicht .

Autor: Winfried J. (Firma: Nisch-Aufzüge) (winne)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
~crazy horse

denk mal nach,

out_text findet auf dem stack den Beginn des Strings.
Klappert den durch und findet am stringende die null. Nun pusht es die 
auf das Stringende folgende und durch mitzählen ermittelte Adresse auf 
den Stack und Springt mit Return dort hin.
Das wars.

delay, dito

peter hat hier nur DB 0
hinter dem asciistring für die Zeitangabe vergessen oder vewendet ne int 
oder long mit festem format.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
crazy horse wrote:
> @peter
> wie findet denn dein Programm nach call out_text call delay_ms? Müsste
> doch nach ret im Nirwana landen? Ist ne Weile her, aber das scheint mir
> suspekt.

Hab ne Weile gebraucht, es auszugraben.
Der Trick ist das abschließende 0-Byte hinter dem Text
;______________________________  Transmit Byte ___________________________

;input: ACC = byte to send

putchar:
  jnb TI, $  ;wait until last transmit finished 
  clr TI
  mov sbuf, a
  ret
;______________________________  Transmit String _________________________

;input: 0-terminated string after call

puts:
  pop dph         ;get address of string
  pop dpl
  sjmp ?put2
?put1:
  call putchar    ;send byte
  inc dptr        ;point to next address
?put2:
  clr a
  movc a, @a+dptr ;get byte pointed by DPTR
  jnz ?put1       ;send it if not zero
  jmp @a+dptr     ;jump back behind zero byte


Und das delay_ms nimmt sich immer genau 2 Bytes und springt nach 
Ausführung zurück, erhöht um 2.


Peter

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, so macht es Sinn. Kann man nur in Verbindung mit der "Intelligenz" 
der UPs verstehen, nicht als Eigenschaft des 8051. Wie gesagt, lange (10 
Jahre) her, dass ich sowas gemacht habe.
Aber irgendwas ähnliches müsste doch auch mit dem PIC machbar sein?

Autor: Winfried J. (Firma: Nisch-Aufzüge) (winne)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Peter,

springst du wirklich direkt??

warum pusht du nicht den stack und gehst wie es sich gehört mit nem ret 
aus der routine?


das riecht mir ja verschärft nach spaghetti carbonara , hätt ich von dir 
nicht erwaret.

tricky ja aber so ?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Winfried Jaeckel wrote:

> springst du wirklich direkt??

Nein, indirekt.


> warum pusht du nicht den stack und gehst wie es sich gehört mit nem ret
> aus der routine?

Warum soll ich 3 Befehle nehmen, wenn ich einen hab, der das alles 
zusammen macht ?

Die Umstände mit push+push+ret müßte man nur machen, wenn es keinen 
indirekten Sprungbefehl gäbe.

Und auch der AVR hat ja dafür den IJMP-Befehl.


Peter

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also erst einmal vielen Dank für die Hilfe!!!

Es funzt alles sehr gut.
Ich habe nur Probleme noch mit der Ausgabe.
Die ist nämlich etwas schnell.
Ich würde gerne alle 2Sek das Wort Hallo darstellen.
bringe ich aber die Warteschleife mit hinein, dann
gibt der PIC mir 5 MAl das Wort HALLO aus und dann kommt nichts
mehr.

Kann es sein das das Timing dann nicht mehr stimmt? Ich meine die
2400Baud. Da darf ja nur 5% Abweichung sein.

Ansonsten mußte ich noch hinter dem return eine neue Zeile setzen.
Das habe ich dann so gemacht:

        movlw  'H'
         call  Send_RS
        movlw  'A'
         call  Send_RS
        movlw  'L'
         call  Send_RS
        movlw  'L '
        call  Send_RS
        movlw  'O'
         call  Send_RS
        movlw  0x0d
         call  Send_RS
        movlw  0x0a
         call  Send_RS


Und genau hier sollte jetzt eine Pause von 2Sek sein und danach sollte 
das zweite Mal HALLO ausgegeben werden.

Hat jemand noch eine  Idee??

Gruß Thorsten

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat niemand eine Idee ????


Gruß aus dem Norden!

Autor: willivonbienemaya (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"
Kann es sein das das Timing dann nicht mehr stimmt? Ich meine die
2400Baud. Da darf ja nur 5% Abweichung sein.
"

Da hier niemand weiss wieviel takte die Funktion Send_RS benötigt, wird 
dir keiner helfen können.

Du kannst als debugger den siumlator auswählen und mit der Stopwatch 
schauen wie lange was dauert. dann kannst du dir deine genaue Baudrate 
ausrechnen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
willivonbienemaya wrote:
> "
> Kann es sein das das Timing dann nicht mehr stimmt? Ich meine die
> 2400Baud. Da darf ja nur 5% Abweichung sein.
> "
>
> Da hier niemand weiss wieviel takte die Funktion Send_RS benötigt, wird
> dir keiner helfen können.

Interessant wäre auch, ob das eine Hardware UART darstellt
oder ob der PIC das alles in Software machen muss.

Aber prinzipiell:
Solange du an SendRS nichts veränderst, kannst du das Timing
der UART nicht dadurch stören, dass irgendwo anders eine
Warteschleife eingeführt wird.

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

da ich an der Baudrate nicht viel verändern kann für meine Zwecke,
muß ich mir also etwas anderes einfallen lassen.

Wie könnte ich denn noch softwaremäßig ein langsameres ausgeben der
Bauchstaben erreichen?

Gruß Thorsten

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thorsten Fischer wrote:

> Wie könnte ich denn noch softwaremäßig ein langsameres ausgeben der
> Bauchstaben erreichen?

Indem Du einen Taschenrechner nimmst.

Dein obiges Delay müßte richtig sein, aber schau mal ins Datenblatt, 
wieviel Zyklen die beiden Instruktionen brauchen.

Bei 2 Instruktionen und einem Byte als Schleifenzähler kommst Du auf 
gerade mal 512 Zyklen. Und nun greif mal zum Taschenrechenr, welcher 
kurzen Zeit das entspricht.



...



Richtig, das ist hoffnungslos zu kurz.
Aber keine Angst, nimmste eben noch und nochn Byte und verschachtelst 
die Schleifen ineinander. Schon kommst Du bis zu 256*256*256*2 Zyklen, 
sollte also reichen. Wenns zu lang ist, lädste eben den äußeren Zähler 
nicht mit 256 (0), sondern weniger.


Und wende jetzt noch fragst, wie schachtelt man:
Del0 equ 0x20 ; Variable anlegen
Del1 equ 0x21 ; Variable anlegen
Del2 equ 0x22 ; Variable anlegen

main:
   ...
   ...
   ...
   movlw 100 ;100*256*256*2 Zyklen
   movwf Del2
delay:
    decfsz  Del0,f
    goto delay
    decfsz  Del1,f
    goto delay
    decfsz  Del2,f
    goto delay
    goto main


Und beim 8051 würde das so aussehen
main:
   ...
   ...
   ...
   mov r2, #100
delay:
   djnz r0, delay
   djnz r1, delay
   djnz r2, delay
   jmp main


Peter

Autor: Thorsten Fischer (thorstencux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>
> Del0 equ 0x20 ; Variable anlegen
> Del1 equ 0x21 ; Variable anlegen
> Del2 equ 0x22 ; Variable anlegen
> 
> main:
>    ...
>    ...
>    ...
>    movlw 100 ;100*256*256*2 Zyklen
>    movwf Del2
> delay:
>     decfsz  Del0,f
>     goto delay
>     decfsz  Del1,f
>     goto delay
>     decfsz  Del2,f
>     goto delay
>     goto main
> 
>
Genau daswar die Lösung!!!! Jetzt kann ich den Intervall
so wählen wie ich ihn gerne hätte !!!!! Vielen Dank


Gruß Thorsten

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.