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
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
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
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
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!!!
> 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.
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
Antwort 1: Ja, bei einer Taktfrequenz von 16 Hz. Antwort 2: Nein, du musst eine Schleife bauen so wie ich es geschrieben habe.
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
Habe mal die Datei so eingefügt. Das wORT wird nun 4 Mal ausgegeben und dann bleibt alles stehen.... Was das wohl wieder ist ?????
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
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
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
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.
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
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.
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
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
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
Muß man das aufm PIC wirklich immer so umständlich machen oder geht das nicht auch einfacher ? Z.B. beim 8051 schreibe ich einfach:
1 | mainloop: |
2 | call out_text |
3 | db 'Hallo Welt', 0Ah, 0Dh |
4 | db 0 ;end mark |
5 | |
6 | call delay_ms |
7 | dw 10000 |
8 | |
9 | 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
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.
@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.
~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 .
~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.
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
1 | ;______________________________ Transmit Byte ___________________________ |
2 | |
3 | ;input: ACC = byte to send |
4 | |
5 | putchar: |
6 | jnb TI, $ ;wait until last transmit finished |
7 | clr TI |
8 | mov sbuf, a |
9 | ret |
10 | ;______________________________ Transmit String _________________________ |
11 | |
12 | ;input: 0-terminated string after call |
13 | |
14 | puts: |
15 | pop dph ;get address of string |
16 | pop dpl |
17 | sjmp ?put2 |
18 | ?put1: |
19 | call putchar ;send byte |
20 | inc dptr ;point to next address |
21 | ?put2: |
22 | clr a |
23 | movc a, @a+dptr ;get byte pointed by DPTR |
24 | jnz ?put1 ;send it if not zero |
25 | 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
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?
@ 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 ?
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
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
" 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.
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.
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
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:
1 | Del0 equ 0x20 ; Variable anlegen |
2 | Del1 equ 0x21 ; Variable anlegen |
3 | Del2 equ 0x22 ; Variable anlegen |
4 | |
5 | main: |
6 | ... |
7 | ... |
8 | ... |
9 | movlw 100 ;100*256*256*2 Zyklen |
10 | movwf Del2 |
11 | delay: |
12 | decfsz Del0,f |
13 | goto delay |
14 | decfsz Del1,f |
15 | goto delay |
16 | decfsz Del2,f |
17 | goto delay |
18 | goto main |
Und beim 8051 würde das so aussehen
1 | main: |
2 | ... |
3 | ... |
4 | ... |
5 | mov r2, #100 |
6 | delay: |
7 | djnz r0, delay |
8 | djnz r1, delay |
9 | djnz r2, delay |
10 | jmp main |
Peter
>
1 | > Del0 equ 0x20 ; Variable anlegen |
2 | > Del1 equ 0x21 ; Variable anlegen |
3 | > Del2 equ 0x22 ; Variable anlegen |
4 | > |
5 | > main: |
6 | > ... |
7 | > ... |
8 | > ... |
9 | > movlw 100 ;100*256*256*2 Zyklen |
10 | > movwf Del2 |
11 | > delay: |
12 | > decfsz Del0,f |
13 | > goto delay |
14 | > decfsz Del1,f |
15 | > goto delay |
16 | > decfsz Del2,f |
17 | > goto delay |
18 | > goto main |
19 | > |
>
Genau daswar die Lösung!!!! Jetzt kann ich den Intervall
so wählen wie ich ihn gerne hätte !!!!! Vielen Dank
Gruß Thorsten
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.