PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Probleme bei Zeigeroperationen mit PIC16F877



fritzle123
14.09.2004, 07:35
Hallo und Grüße an alle PIC Programmierer,

da ich nach langen zögern doch endlich meine Programmiersprache
von Assembler auf C umgestellt habe, stehe ich vor mehreren (vermutlich für euch kleinen) Problemen.

Ich möchte mit meinem PIC16F877 über die serielle Schnittstelle einen
String einlesen, zwischenspeichern und anschließend mit einem 2. String vergleichen.
(Der Wert des 2. String wird im Funktionsaufruf als Konstante
übergeben, dies geschieht jedoch in einer anderen Funktion da ich
diese öfters mit verschiedenen Strings benötige)

Nun habe ich folgende Probleme:

1.)
Ich kann zwar einen String einlesen, bekomme aber das Problem dass
ich für einen späteren Vergleich den Zeiger (globale Variable) wieder
auf das erste Byte richten muss.
Wenn ich beim Aufruf meiner Funktion den String kopiere
(*Start_Byte = *Empfangenes_Byte) bekomme ich aber leider die
Fehlermeldung, dass der Code in C eigentlich richtig ist, aber die Funktion
bei meinem Controller nicht möglich ist, da er nur ein Zeigerregister hat.

Wie kann ich dies in C (ich verwende CC5X) anders programmieren.
Ich habe hierfür auch schon das FSR Register ausgelesen und wollte
den Wert meinem zweiten Zeiger zuweisen, jedoch ist dies in C nicht
möglich da ich einem Zeiger nur eine Zeigervariable und keinen Wert
zuweisen kann.

2.)
Wenn ich meinen String in einer zweiten Funktion vergleichen möchte,
habe ich das Problem dass ich gleichzeitig mit zwei Zeigern arbeiten
muss, um deren Inhalt (ausgelesener Wert) miteinander zu vergleichen.
Gibt es hierfür eine Möglichkeit ohne dass ich ständig mein
FSR – Register neu laden muss?

Ich hoffe ich konnte meine Probleme deutlich erklären und würde
mich über eure Lösungsmöglichkeiten und Vorschläge sehr freuen.

Grüsse von fritzle123

gunzelg
21.09.2004, 18:43
Hallo

ja, das ist ne blöde Sache, PIC16 und C, da sind die PIC18 besser für C geeignet. Aber versuch doch mal Deine Zeiger-Operationen (je eine) in einer Subroutine auszuführem und die entsprechenden Zeiger auch nur lokal und nicht global zu definieren. - Ist so eine Idee, vielleicht nützt gehts.

Gerhard

22.09.2004, 21:42
ja, das ist ne blöde Sache, PIC16 und C, da sind die PIC18 besser für C geeignet
Prinzipiell hast Du recht, d.h. die Architektur der PIC18 kommt C mehr entgegen (in Assembler sind sie aber auch "angenehmer").

Eine Lösung für das Problem von fritzle123 Problem habe ich im Moment auch nicht, da ich den CC5X nicht näher kenne. Es ist aber eigentlich eindeutig ein Problem des verwendeten Compilers, denn PICC von HT-Soft kann dafür Code erzeugen (warum auch nicht, ist ja schließlich in Assembler auch möglich)



*ptr1 = *ptr2
MOVF ptr2, W
MOVWF FSR ; FSR zeigt auf ptr2
MOVF INDF, W ; w enthält Inhalt von ptr2
MOVWF 0x70 ; Inhalt von ptr2 in 0x70 zwischenspeichern
MOVF ptr1, W
MOVWF FSR ; FSR zeigt auf ptr1
MOVF 0x70, W ; W enthält den Inhalt von ptr2
MOVWF INDF ; Inhalt von ptr1 = Inhalt von ptr2

Von diesem Compiler gibt es auch eine freie Version, ist für den 16F877 aber auf 2k Words Code und 2 RAM-Bänke beschränkt.

http://www.htsoft.com/products/PICClite.php

Bernd

27.09.2004, 07:56
Hallo Bern und Gerhard,

eigentlich habt ihr Recht und ich werde bei meiner nächsten Platine
vermutlich auf einen PIC18 umsteigen, da er drei getrennte Zeiger hat.
Leider ist meine Platine schon fertig und ich möchte nicht nochmals von vorne anfangen.
Die Funktion *ptr1 = *ptr2 lässt sich leider bei CC5X nicht anwenden,
da genau dort mein Problem liegt.
Mir ist zudem noch aufgefallen dass mir die Anweisung:

Byte = *String;
einen Zugriff auf meinen Flash Speicher verursacht und
dieser natürlich sehr lange dauert.
Vermutlich werde ich mein Problem doch in Assembler lösen müssen.

Falls du (Bernd) Zeit hättest würde ich mich über den erzeugten Code freuen,
wäre zumindest eine gute Vorlage.

Also, vielen Dank für eure Bemühungen.

Grüße Fritzle123


fritzle123@web.de

27.09.2004, 19:54
Hallo Friztle 123,

der Zugriff auf den Flash-Speicher ist normal, da Konstanten immer im Flash abgelegt werden. Entweder kann man auf die Konstanten über eine Tabelle aus RETLW-Anweisungen oder über TBLRD-Befehle zugreifen. Jeder Zugriff auf den Flash-Speicher ist langsamer als ein RAM-Zugriff.

Hier der vom HT-Compiler erzeugte Code:




1: #include <pic.h>
2:
3: const unsigned char string_rom[5] = "test"; // String im ROM
4: unsigned char byte; // RAM-Adresse ist 0x20
5:
6: void test_fkt (const unsigned char *string)
7: {
8: byte = *string;
0007F1 0183 CLRF 0x3
0007F2 0822 MOVF 0x22, W
0007F3 00A4 MOVWF 0x24
0007F4 0821 MOVF 0x21, W
0007F5 2011 CALL 0x11 // Zugriff auf den String
0007F6 00A0 MOVWF 0x20
9: }
0007F7 0008 RETURN
10:
11: void main(void)
12: {
13: test_fkt (string_rom);
0007F8 3027 MOVLW 0x27 // Parameterübergabe
0007F9 1283 BCF 0x3, 0x5
0007FA 1303 BCF 0x3, 0x6
0007FB 00A1 MOVWF 0x21
0007FC 3000 MOVLW 0
0007FD 00A2 MOVWF 0x22
0007FE 27F1 CALL 0x7f1 // Funktionsaufruf
14: for (;;);
0007FF 2FFF GOTO 0x7ff

// String-Tabelle

Line Address Opcode Label Disassembly
18 0011 1283 string_table BCF STATUS, 0x5 // String-Tabelle, Einsprung erfolgt hier
19 0012 00A3 MOVWF 0x23
20 0013 1BA4 string_indir BTFSC 0x24, 0x7
21 0014 281E GOTO 0x1e
22 0015 1B24 BTFSC 0x24, 0x6
23 0016 2826 GOTO 0x26
24 0017 0824 MOVF 0x24, W
25 0018 008A MOVWF PCLATH
26 0019 0823 MOVF 0x23, W
27 001A 0AA3 INCF 0x23, F
28 001B 1903 BTFSC STATUS, 0x2
29 001C 0AA4 INCF 0x24, F
30 001D 0082 MOVWF PCL
31 001E 1383 BCF STATUS, 0x7
32 001F 1824 BTFSC 0x24, 0
33 0020 1783 BSF STATUS, 0x7
34 0021 0823 ?_test_fkt MOVF 0x23, W
35 0022 0AA3 INCF 0x23, F
36 0023 0084 code_ptr MOVWF FSR
37 0024 0800 MOVF INDF, W
38 0025 0008 RETURN
39 0026 0782 ADDWF PCL, F
40 0027 3474 RETLW 0x74 // Ab hier steht der String
41 0028 3465 RETLW 0x65
42 0029 3473 RETLW 0x73
43 002A 3474 RETLW 0x74
44 002B 3400 RETLW 0

Wenn Du mehr Beispiele für die Codeerzeugung benötigst, solltest Du meinem obigen Link folgen und selbst mit der Lite-Version experimentieren :wink: .

Bernd

27.09.2004, 20:09
Was mir gerade noch eingefallen ist:

Die Zuweisung des Inhalts von Zeiger 2 zu Zeiger 1 kann man natürlich auch über eine temporäre Variable lösen.

temp = *ptr2;
*ptr1 = temp;
Damit müßte auch der CC5X klarkommen.

Bernd

28.09.2004, 15:15
Hallo Bernd,

danke für deine Bemühungen.

die Zuweisung: temp = *ptr2;
gibt mir aber nur den Inhalt der Zelle auf die der Zeiger gerade zeigt.

und
*ptr1 = temp;
funktioniert leider auch nicht da es sich bei *ptr1 um eine Variable
vom Typ Zeiger handelt und ich daher kein Byte zuweisen kann.

Ich versuche es jetzt mal in Assembler, dann wird es schon klappen.

Gruß fritzle123

28.09.2004, 16:19
Hallo Fritzle123,


die Zuweisung: temp = *ptr2;
gibt mir aber nur den Inhalt der Zelle auf die der Zeiger gerade zeigt.

Richtig.


*ptr1 = temp;
funktioniert leider auch nicht da es sich bei *ptr1 um eine Variable
vom Typ Zeiger handelt und ich daher kein Byte zuweisen kann.

Falsch, ptr ist eine Variable vom Typ Zeiger, *ptr ist der Inhalt der Speicherstelle, auf die ptr zeigt. Daher wird der Wert der Variablen temp in die Speicherstelle geschrieben, auf die ptr zeigt.

*ptr1 = *ptr2 bewirkt, daß der Inhalt der Speicherstelle, auf die ptr2 zeigt, in die Speicherstelle geschrieben wird, auf die ptr1 zeigt.

ptr1 = ptr2 bewirkt, daß der Zeiger ptr1 auf die selbe Speicherstelle wie ptr2 zeigt.


Viele Grüße

Bernd