-         
+ Antworten
Ergebnis 1 bis 8 von 8

Thema: Probleme bei Zeigeroperationen mit PIC16F877

  1. #1
    fritzle123
    Gast

    Probleme bei Zeigeroperationen mit PIC16F877

    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

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    20.08.2004
    Ort
    Unterschleissheim
    Beiträge
    218
    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

  3. #3
    Gast
    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)

    Code:
    *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

  4. #4
    Gast
    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

  5. #5
    Gast
    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:


    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 .

    Bernd

  6. #6
    Gast
    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.
    Code:
    temp = *ptr2;
    *ptr1 = temp;
    Damit müßte auch der CC5X klarkommen.

    Bernd

  7. #7
    Gast
    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

  8. #8
    Gast
    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

+ Antworten

Benutzer, die dieses Thema gelesen haben: 1

Berechtigungen

  • Neue Themen erstellen: Ja
  • Themen beantworten: Ja
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •