PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PIC-Lernbeispiel: RS232-Interface



iClou
31.05.2005, 16:43
Hallo

Ich möchte das folgende Lernbeispiel von sprut.de zum laufen bringen:
http://sprut.de/electronic/pic/programm/rs232.htm

Die Schaltung habe ich erfolgreich zusammengebaut.
Das Programm ser_rx.asm habe ich insofern erweitert, dass am Anfang eine LED 2x blinkt.

Ich schicke nun vom PC via RS232 Kabel Daten an die Testschaltung, aber nichts geschieht.

Ich habe das PC inteface separat getestet, da läuft alles ok, d.h. Baud 9600, 8 databit, 1 stopbit und parity none.
Das RS232 Kabel ist 2m lang.

Wer kann mir einen Tipp geben, was evt falsch ist od wie kann ich den Fehler finden?

Danke für jegliche Hilfe.
Gruss
Sam

TomHumpen
02.06.2005, 09:47
Hast du 4Mhz als frequenz am Pic?

So long...

iClou
02.06.2005, 09:56
Hast du 4Mhz als frequenz am Pic?



Ja ich habe 4MHZ am PIC.

Ich benutze den PIC 16F628; kann ich mit diesem evt nur via USART kommunizieren?

Danke, Gruss
Sam

TomHumpen
02.06.2005, 11:46
Die Software Variante müßte in jedem Fall gehen, da du nur 2 IO Pins benutzt und das auswerten kein Problem macht. Wenn er USART on Board hat würde ich es nehmen, da mit einem MAX232 weniger Fehler, weil keine Berechnung der Abstände der Bits nötig sind. Auch sinbd die Pins hier schon am Pic vorgesehen.

Ansonsten: Hast du als Eingang (RS232 RX auch Pin A3 genommen wie im Sprut-Prog?). Ich kann auch nur raten und überprüf nochmal ob du die Portbelegung, wie Sprut sie nahm auch angelötet hast. Viel erfolg!

So long...

Goblin
02.06.2005, 15:08
versuch erstmal, vom pic daten an den pc zu senden. ist imho einfacher, weil du dann am pc sachen wir baudrate und so einfacher ändern kannst, falls sie falsch ist. ausserdem siehst du, ob du überhaupt irgend nen signal bekommst. wenn du deinen pic so geproggt hast, dass er z.b. bei einem empfangenen "A" ne led anmacht und er irgendein sonderzeichen wegen störungen, falscher baudrate oder wasweissich kriegt, dann kann dabei ja nix rauskommen. also einfach mal ne schleife schreiben, mit der der pic immer wieder nen wort oder nen zeichen sendet. und dann kannst du in aller ruhe an deiner schaltung und an der verbindung und an den einstellungen basteln, bis du was brauchbares reinbekommst.

Goblin
07.06.2005, 21:02
darf ich fragen, was dabei jetzt rausgekommen ist?

iClou
30.06.2005, 07:58
Ich habe die nachfolgende Schaltung genommen, einen 4MHZ Quartz angehängt und nun läuft alles super - echt genial!
http://www.oz1bxm.dk/PIC/628uart.htm

Nun 'kämfpe' ich aber mit der folgenden Frage...
https://www.roboternetz.de/phpBB2/viewtopic.php?t=10507

--
Gruss
Sam

05.07.2005, 08:25
Moin Moin,
habe mich in letzten Wochen bißchen versucht einzuarbeiten tutorials geleesen und so allerdings habe ich noch nit die möglich direkt zu testen da ich erst alles Theoretisch fertig haben soll.
Soweit so gut habe auch das Beispiel genommen und wollte sogar den PIC 16F628 benutzen.
Ich soll ein bestimmtes Signal das ich Einstellen kann abfangen und ein Relais durchschalten.
Habe denke auch soweit lauf fähig nur finde ich nichts um das Signal zu vergleichen das ich von der RS232 schnittstelle bekomme.
Wenn ich zum beispiel in einer Speicherzellespeicher und dann mit einer anderen vergleichen will oder so ?!
hat da jemand ne idee oder ahnung ?

mfg oxmox

Mobius
06.07.2005, 12:51
Sicher, es ist eigentlich einfach... Du hast zwei Werte, die übereinstimmen sollen, welche, sag ma in einer Speicherzelle s und dem Arbeitsregister abgelegt sind:

Du musst dich fragen, wie vergleichst du z.B.: zwei Zahlen, ob sie identisch sind, wenn du "nur" addieren und subtrahieren zur Verfügung hast. Du subtrahierst die beiden Zahlen voneinander und schaust, ob das Ergebniss 0 ist. Wenn ja, sind beide Zahlen identisch.



movlw D'64'
subwf s
BZ identisch


MfG
Mobius

06.07.2005, 13:56
LIST P=16F628, R=DEC
#include "P16F628.INC"

CBLOCK 0x20 ; Declare variable addresses starting at 0x20
dataL
ENDC

ORG 0x000 ; Program starts at 0x000
;
; --------------------------------
; SET ANALOG/DIGITAL INPUTS PORT A
; --------------------------------
;
movlw 7
movwf CMCON

; ----------------
; INITIALIZE PORTS
; ----------------
;
movlw b'00000000'
movwf PORTA

movlw b'00000100'
movwf PORTB

bsf STATUS,RP0
movlw 0xFF
movwf TRISA
movlw b'11110010'
movwf TRISB

; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit
;
movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw b'00000100' ; brgh = high (2)
movwf TXSTA ; schaltet brgh high ein

bcf STATUS,RP0 ; RAM PAGE 0

movlw b'10010000' ; schaltet seriellen port ein
movwf RCSTA
;
; ------------------------------------
; PROVIDE A SETTLING TIME FOR START UP
; ------------------------------------
;
clrf dataL
settle decfsz dataL,F
goto settle

movf RCREG,W
movf RCREG,W
movf RCREG,W ; flush receive buffer
;
; ---------
; MAIN LOOP
; ---------
;

loop call receive ; wait for a char
call vergleich
goto loop
;
; -------------------------------------------
; SIGNALE VON DER RSR232 SCHNITTSTELLE EMPFANGEN
; -------------------------------------------
; This routine does not return until a character is received.
;
receive btfss PIR1,RCIF ; (5) check for received data
goto receive

movf RCREG,W ; speichert das empfangende in W
return
;
; -------------------------------------------------------------
;AUSWERTEN
; -------------------------------------------------------------
;

vergleich

BTFSS W,b'00000001'
goto receive
bsf PORTA,b'00000001'
goto vergleich

END


da ich ja das eingangs signal bestimmen kann hab ich es so gelöst ;)
allerdings habe ich noch ne verständniss frage undzwar:

habe ja datenblatt durchforstet habe soweit alle register verstanden allerdings noch nicht ganz was folgendes soll:



movlw 7
movwf CMCON

was iss das CMCON genau verstehe das was sie im datenblatt sagen wolle nicht genau im datenblatt steht auch nur When CM2:CM0: = 001 und einmal 010 aber in dem beispiel sind alle auf 111.

Und selbst wenn nun 010 wäre was soll heißen C1 Vin- connetcs to RA0

und das mit den muss ich noch rausfinden

bsf STATUS,RP0

aber das finde ich selbst noch raus ;)

mfg vielen dank schonmal für die letzte hilfe oxmox

Mobius
06.07.2005, 18:23
Also, das CMCON ist der interne Comparator. hier (https://www.roboternetz.de/phpBB2/viewtopic.php?t=10435) ist es erklärt ;). Kurz gesagt, beim reset des PICs ist der Comparator auf RA0 und 1 geschalten, was echt nervend ist, wenn man versucht etwas auf den zwei Pins einzulesen.

Und "bsf STATUS,RP0" ist, dass Bank1 gewählt werden soll (lies dir dazu den Abschnitt "Memory Organisation" im Datasheet durch, dann wird verständlich ^_^).

Naja, deine Lösung funzt auch, nur wird es dann schwierig, wenn du z.B.: verschiedenste Buchstaben unterscheiden musst (wenn du, z.B.: ein Protokoll auswerten musst). Deshalb ist es immer gut, zu wissen, wie man auch "größere" Zahlen vergleichen kann.

MfG
Mobius

07.07.2005, 06:57
jupp vielen dank
habe viele tutorials durchgelesen aber wirklich am meisten,
um die ganzen hintergründe und register zu verstehen bringt das datenblatt auch wenn einige englische worte in den übersetzer mussten ;)
der code iss noch nicht ganz fertig weil ich am besten den code in einer bestimmten zeit öfter haben soll und noch einsignal zum ausschalten aber wird schon ;)

mfg nochmal danke oxmox

07.07.2005, 09:52
habe ein problem beim durchlaufen loopt sich tot ^^
was genau heißt folgendes : finde dataL nirgends und auch CBLOCK nicht ! auch imt datenblatt nicht und weiß ansich nicht was der befehl bringt
clrf heißt ja speicherzelle löschen aber habe doch nirgends eine definiert dafür ?! würds ja einfach rausnehmen, aber weil wie gesagt mein erste prog ist und ich nach beispiel arbeiten wollte lass ich das erstmal so


CBLOCK 0x20 ; Declare variable addresses starting at 0x20
dataL
ENDC

; PROVIDE A SETTLING TIME FOR START UP
; ------------------------------------
;
clrf dataL
settle decfsz dataL,F
goto settle

movf RCREG,W
movf RCREG,W
movf RCREG,W ; flush receive buffer
;

Mobius
07.07.2005, 16:10
nein, du hast dataL ja definiert ;) Mit CBLOCK kannst du einfach und schnell Variablen definieren:

dataL org 0x20
dump org 0x21
dump1 org 0x22

ist das gleiche wie

CBLOCK 0x20
dataL
dump
dump1
ENDC

Das loop ist irgendwie blöd gelöst: Du löscht den Register, dann fängst du an aus 0 so lange 1 abzuziehen, bis es wieder 0 ist. Du erzeugst einen Überlauf und dann sollte das Ganze 255-mal durchlaufen. Am Besten schaust du den Register mit einem Watch an, während du debugst.
Mobius

DHigh
08.07.2005, 09:36
jo vielen dank nochmal :)
nu klappts auch mit dem PIC Simulator



LIST P=16F628, R=DEC ; Use the PIC16F628 and decimal system

#include "P16F628.INC" ; Include header file




ORG 0x000 ; Program starts at 0x000
;
; --------------------------------
; SET ANALOG/DIGITAL INPUTS PORT A
; --------------------------------
;
movlw 7 ; lädt 7 in das W-Register
movwf CMCON ; 0x1F = 7

; ----------------
; INITIALIZE PORTS
; ----------------
;
movlw b'00100000' ;
movwf PIE1 ; USART Receive Interrupt Enable Bit

movlw b'00000000' ; lädt 0 in das W-Rgeister
movwf PORTA ; alle low an PORTA

movlw b'00000100' ; W-Register
movwf PORTB ; lädt in 0x06

bsf STATUS,RP0 ; im Register Status wird das RP0 bit auf 1 gesetzt

movlw 0xFE ; schreibt den wert FE in W
movwf TRISA ; bis auf RA0 alle Eingäng(high)
movlw 0xFF ; alle Eingänge RB1(RX)=Eingang
movwf TRISB

; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit
;
movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw b'00000100' ; brgh = high (2)
movwf TXSTA ; schaltet brgh high ein
bcf STATUS,RP0 ; RAM PAGE 0

movlw b'10010000' ; schaltet seriellen port ein
movwf RCSTA


;
; ---------
; MAIN LOOP
; ---------
;

loop call receive ; wait for a char
call vergleich
goto loop
;
; -------------------------------------------
; SIGNALE VON DER RSR232 SCHNITTSTELLE EMPFANGEN
; -------------------------------------------
; This routine does not return until a character is received.
;
receive btfss PIR1,RCIF ; checkt ob im register PIR1 das RCIF bit (USART Receive Interrupt Flagbit) wenn der receive buffer voll ist geht weiter
goto receive

movf RCREG,W ; speichert das empfangende in W
return
;
; -------------------------------------------------------------
; "VERGLEICHT" DIE BEIDEN SIGNALE
; -------------------------------------------------------------
;

vergleich
sublw 1
bcf PORTA,0x0
btfss STATUS,Z ;könnte auch mit einer Speicherzelle subtrahier
return

bsf PORTA,0x0
return

END


ist echt besser so zu vergleiche so kann eigentlich jedes bit auswerten
bin mal gespant wie das in der praxis klappt...

in dem code steht ja 1 stopbit no parity ist das standart oder kann man das wo einstellen ?
und sonn watchdog timer sollte man das mit reinnehmen ?

mfg DHigh

Mobius
08.07.2005, 11:22
@Watchdog: würde ich bei so einem kleinen Programm nicht einschalten, bringt sich einfach nicht. Ich hab es noch (fast) nie gebraucht, bzw. wenn einmal der PIC abfriert dann wird es fast sicher wegen eines Programmierfehlers sein, d.h. der Watchdog hilft nichts, wenn er den PIC resetet, es wird wieder an der gleichen Stelle absaufen. Wenn du es verwendest, dnn musst du ihn jede ~53 ms resetten (clrwdt), ansonsten läuft er über und du hast den Salat mit einem neustartenden PIC ^_^.

Ich hab ihn nur einmal gebraucht, als es um eine Applikation ging, bei der der PIC regelmäßig und ohne externe Signale aus dem Sleep geholt werden musste und ein Signal zu setzten. Da bot sich der WDT, der bei 4V und 128 Vorteiler ca. jede 2. Sekunde überlief an.

Und den USART kannst du eigentlich so einstellen, wie du möchtest, einfach den Register angucken und das Datasheet durchlesen. Aber, wenn ich mich recht entsinne, ist es fast standard, dass Stopbits verwendet werden, ich glaub, beim PIC kannst auch nur zwischen Stop- oder Startbits unterscheiden. Bin mir aber nicht so sicher...

MfG
Mobius

DHigh
14.07.2005, 11:53
falls es jemanden interessiert habe nun folgenden code:



LIST P=16F628, R=DEC ; Use the PIC16F628 and decimal system

#include "P16F628.INC" ; Include header file




ORG 0x000 ; Program starts at 0x000

; --------------------------------
; SET ANALOG/DIGITAL INPUTS PORT A
; --------------------------------

movlw 7 ; lädt 7 in das W-Register
movwf CMCON ; 0x1F = 7

; ----------------
; INITIALIZE PORTS
; ----------------

movlw b'00100000'
movwf PIE1 ; USART Receive Interrupt Enable Bit

movlw b'00000000' ; lädt 0 in das W-Rgeister
movwf PORTA ; alle low an PORTA

movlw b'00000100' ; W-Register
movwf PORTB ; lädt in 0x06

bsf STATUS,RP0 ; im Register Status wird das RP0 bit auf 1 gesetzt

movlw 0xFC ; schreibt den wert FE in W
movwf TRISA ; bis auf RA0,RA1 alle Eingäng(high)
movlw 0xFF ; alle Eingänge RB1(RX)=Eingang
movwf TRISB

; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit

movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw b'00000100' ; brgh = high (2)
movwf TXSTA ; schaltet brgh high ein
bcf STATUS,RP0 ; RAM PAGE 0

movlw b'10010000' ; schaltet seriellen port ein
movwf RCSTA

; ---------
; MAIN LOOP
; ---------

loop call receive
call vergleich
call vergleich2
call vergleich3
call vergleich4
goto loop

; -------------------------------------------
; SIGNALE VON DER RSR232 SCHNITTSTELLE EMPFANGEN
; -------------------------------------------

receive btfss PIR1,RCIF ; checkt ob im register PIR1 das RCIF bit (USART Receive Interrupt Flagbit) wenn der receive buffer voll ist geht weiter
goto receive
movf RCREG,0 ; speichert das Empfangende in W
movwf 0x7F ; speichert das Empfangene in Speicherzelle 7F
return

; -------------------------------------------------------------
; "VERGLEICHT" DIE BEIDEN SIGNALE
; -------------------------------------------------------------

vergleich
movf 0x7F,0 ; das aus der RS232 Empfange Byte in W schreiben
sublw 1 ; das Signal wird mit 1 subtrahiert, wenn 0 herraus kommt wird Zero Bit gesetzt
btfss STATUS,Z ; wenn Zerobit gesetzt wurde, wird nächster befehl übersprungen
return

bsf PORTA,0 ; PORTA Bit 0 wird gesetzt
return

vergleich2
movf 0x7F,0 ; das aus der RS232 Empfange Byte in W schreiben
sublw 2 ; das Signal wird mit 2 subtrahiert, wenn 0 herraus kommt wird Zero Bit gesetzt
btfss STATUS,Z ; wenn Zerobit gesetzt wurde, wird nächster befehl übersprungen
return

bsf PORTA,1 ; PORTA Bit 1 wird gesetzt
return

vergleich3
movf 0x7F,0 ; das aus der RS232 Empfange Byte in W schreiben
sublw 3 ; das Signal wird mit 3 subtrahiert, wenn 0 herraus kommt wird Zero Bit gesetzt
btfss STATUS,Z ; wenn Zerobit gesetzt wurde, wird nächster befehl übersprungen
return

bcf PORTA,0 ; PORTA Bit 0 wird gelöscht
return

vergleich4
movf 0x7F,0 ; das aus der RS232 Empfange Byte in W schreiben
sublw 4 ; das Signal wird mit 4 subtrahiert, wenn 0 herraus kommt wird Zero Bit gesetzt
btfss STATUS,Z ; wenn Zerobit gesetzt wurde, wird nächster befehl übersprungen
return

bcf PORTA,1 ; PORTA Bit 1 wird gelöscht
return

END


damit kann ich über RS232 Schnittstelle 2 Relaisschalten
einzeld an und einzeld aus
also zumindestens kalppts mit dem PIC Simulator
leider ist der PIC noch nicht angekommen

MFG vielen Dank für die Hilfe hier DHigh

impact
02.11.2006, 18:15
Hallo, ich bastel nochnicht lange mit PICs rum, habe das Programm was du oben beschrieben hast jedoch getestet.

Leider klappt das Programm bei mir ganz und garnicht, weder mit Simulator und "echter" Hardware.

Habe nen 16F627 @ 10Mhz Takt

Achja, ein "Echo" auf Zeichen bekomm ich manchmal, jedoch passiert bei dem senden des Zeichens "1","2","3","4" nichts an den RA-Outputs :(

edit: Achja er meint beim vergleichen, das <btfss STATUS,Z> wohl net 1 ist obwohlich eindeutig ne 1 bzw 2 sende...

Mobius
02.11.2006, 23:56
Eine genauere Fehlerstellung wäre hilfreich. So kann ich leider nur raten, wo der Fehler liegen kann.

Vorsicht, wenn du den 16F bei 10MHz betreibst, musst du den Register SPBRG mit einem anderen Wert initialisieren, ansonsten stimmen deine Baud-Raten nicht mehr und du erhällst bei dem Empfang der Bits nur noch nonsence (der Empfänger kommt aus dem Synchron).

Ich hab jetzt die Datenblätter nicht parat, aber hast du geschaut, in wie weit sich die 627 von den 628 unterscheiden? Vor allem musst du den Source auch anpassen, was die Include und Processor-Defines betrifft. Prüf mal den Punkt nach, wenn sie sich zu sehr unterscheiden wird das nicht wirklich laufen können.

Beim Simulator wird das Programm auch schwerlich funktionieren, den Mplab hat keinen virtuellen seriellen Port, von dem ich wüsste :). Wenn du da etwas mit der seriellen Schnittstelle simulieren willst, kommst du nciht drüber hinweg die "empfangenen" Daten direkt in den betreffenden Register (bei dir RCREG) hineinzuschreiben (einfach beim watch auf den Wert klicken) und das Bit PIR1,RCIF genauso zu setzten.

Ansonsten, dürftest du bei diesem Programm kein Echo auf der Seriellen Schnittstelle haben, das Tx-Teil ist nicht einmal aktiviert.
Läuft dein PIC eigentlich, also halt, schreib einmal ein Programm, dass dir ein Rechteckssignal auf einem Port ausgibt und mess mal mit nem Osci nach (wenn du keinen hast, ein Voltmesser, wenn du etwas anderes als 5V oder 0V misst, müsste es funktionieren).
MfG
Mobius

impact
03.11.2006, 15:07
ich beutze den PIC simulator von ohsonsoft der hat Rs232 unterstützung ect.

ich hab mal rumprobiert, er empfängt daten. wenn ich vor dem Step wo subrathiert wird abfrage und z.b. nen augang dann schalte leuchtet dieser auch:



bsf PORTA,0
call DELAY_ROUTINE
bcf PORTA,0
movf 0x7F,0
sublw 0x30
btfss STATUS,Z
return

bsf PORTA,0
return


BTFSS meint wohl, das wert a- wert b nicht = 0 ist und setzt somit das Zero bit nicht (hab da wenig rumprobiert deswegen die abweichung vom orginal ( 0 => 0x30))
Das programm springt einfach wieder zurück und setzt keinen ausgang


Das Programm läuft, ja die änderungen bezüglich der Mhz unterschiede und des anderen pics habe ich auch berücksichtigt