Forum: Mikrocontroller und Digitale Elektronik rlf Befehl bei PIC16F887 klappt nicht!


von DasSauerkraut (Gast)


Lesenswert?

Hallo Leute,

habe hier folgenden Quellcode:
1
    list        p=16f887            ; list definiert den Controller 
2
    #include    <p16f887.inc>      ; Headerdatei mit Registernamen 
3
    __CONFIG      _CONFIG1, _LVP_OFF&_FCMEN_OFF&_IESO_OFF&_BOR_OFF&_CPD_OFF&_CP_OFF&_MCLRE_ON&_PWRTE_ON&_WDT_OFF&_INTRC_OSC_NOCLKOUT 
4
    __CONFIG    _CONFIG2, _WRT_OFF&_BOR21V 
5
;---------------------------------------------------------------------- 
6
; Configuration Word Register1:          
7
;         Low Voltage Programming -> LVP_OFF(disabled)                 
8
;         Monitor Clock Fail-safe -> FCMEN_OFF(disabled)                      
9
;         Internal External Switch Over Mode -> IESO_OFF(disabled)         
10
;         Brown Out Detect -> BOR_OFF(disabled)     
11
;         Data EE Read Protect -> CPD_OFF (disabled) 
12
;         Code Protect -> CP_OFF 
13
;         Master Clear Enable -> MCLRE_ON (enabled) 
14
;         Power Up Timer -> PWRTE_ON (enabled) 
15
;         Watchdog Timer -> WDT_OFF (disabled) 
16
;         Oscillator -> INTRC_OSC_NOCLKOUT (Internal RC No Clock)             
17
; Configuration Word Register2:  
18
;         Flash Memory Write Protection off -> WRT_OFF (disabled) 
19
;         Brown-out Reset Voltage -> BORV21 (2,1 V) 
20
 
21
          ORG         0x000    ; Anfangsadresse 0x000 
22
ResetVector    movlw     high(main) 
23
            movwf     PCLATH 
24
            goto      main
25
;----------------------------------------------------------------------
26
; Variablen Definition
27
;----------------------------------------------------------------------
28
ms1   equ 0x22
29
ms100   equ 0x23
30
31
;---------------------------------------------------------------------- 
32
; Hauptprogramm: main 
33
;---------------------------------------------------------------------- 
34
main         
35
        bsf     STATUS, RP0     ; auf Bank 1 umschalten 
36
    movlw  0x00       ; PORTA ist Ausgang
37
    movwf  TRISA  
38
        clrf   STATUS       ; auf Bank 0 umschalten
39
    movlw  b'00000001'
40
    movwf  PORTA
41
    bcf     STATUS, C
42
43
44
;---------------------------------------------------------------------- 
45
; Lauflicht
46
;----------------------------------------------------------------------  
47
mainloop      
48
    call   delay_100ms
49
    rlf    PORTA,f
50
    goto   mainloop
51
52
;----------------------------------------------------------------------
53
; delay Funktion 100ms
54
;----------------------------------------------------------------------
55
delay_100ms
56
    movlw  d'100'      ;Zeitkonstante 100ms
57
    movwf  ms100
58
wait2  movlw  d'100'            ;Zeitkonstante 1ms
59
    movwf  ms1        
60
wait1  nop            ;1µS
61
    nop            ;1µS
62
    nop            ;1µS
63
    nop            ;1µS
64
    nop            ;1µS
65
    nop            ;1µS
66
    nop            ;1µS
67
    decfsz  ms1        ;1µS
68
    goto   wait1      ;2µs
69
    decfsz  ms100
70
    goto  wait2      
71
    return 
72
73
;---------------------------------------------------------------------- 
74
        END                    ; Programmende 
75
;----------------------------------------------------------------------
Das Problem hierbei ist das der rlf PORTA, f Befehl nicht funktioniert.

Der Ausgang sieht wie Folgt aus:

1. Durchlauf: 00000001
2. Durchlauf: 00000000

wenn ich das bitmuster Manuell durchlaufenlasse also jedes mal den Wert 
manuell ins Register schreibe für den nächsten Schritt klappt es. Also 
Zeitschleife und alles geht. nur diese blöden rotationsbefehle klappen 
nicht. Kann mir jemand sagen woran das liegt?

von Chris B. (dekatz)


Lesenswert?

Wie in 99% solcher Fälle:
Ich würde mal den PortA von ANALOG (das ist die Defaulteinstellung nach 
einem Reset) auf DIGITAL umschalten --> Datenblatt 3.0

von Teo D. (teoderix)


Lesenswert?


von DasSauerkraut (Gast)


Lesenswert?

BANKSEL ANSEL   ;
clrf  ANSEL   ;PORTA to digital I/O
clrf   STATUS

Hat in der Tat Funktioniert.

Bist du so nett mir zusagen wo der genau Unterschied besteht? Habe die 
Ports ja vorher schon als Ausgang festgelegt. Warum muss ich dann 
nochmal die Analogeingänge ausschalten? geschieht das nicht automatisch?

von Chris B. (dekatz)


Lesenswert?

DasSauerkraut schrieb:
> BANKSEL ANSEL   ;
> clrf  ANSEL   ;PORTA to digital I/O
> clrf   STATUS
>
> Hat in der Tat Funktioniert.
>
> Bist du so nett mir zusagen wo der genau Unterschied besteht? Habe die
> Ports ja vorher schon als Ausgang festgelegt. Warum muss ich dann
> nochmal die Analogeingänge ausschalten? geschieht das nicht automatisch?

Als reiner Ausgang würde der Port auch in der Analogkonfiguration 
funkteonieren.

<rlf PORTA, f> ist aber ein "read-modify-write" Vorgang: PortA wird 
Gelesen, nach Links verschoben und wieder Geschrieben. Und der 
Lesevorgang läuft ohne Umschaltung über den Analogpfad und dessen 
Verhalten ist nicht vorhersehbar (in Bezug auf definiertes 0 oder 1´).

Im DB findet man unter 3.2.3. die Blockdiagramme der einzelnen Portpins 
und kann den Signalweg dort nachvollziehen.

von DasSauerkraut (Gast)


Lesenswert?

So ein kleines Problem gibt es aber noch:

Ich habe folgenden Init code:
1
        BANKSEL  TRISA
2
  clrf  TRISA  
3
        clrf   STATUS       ; auf Bank 0 umschalten
4
  BANKSEL ANSEL       ;
5
        clrf  ANSEL       ;PORTA to digital I/O
6
  clrf   STATUS
7
  bcf  STATUS, C
8
  clrf   PORTA
9
  bsf  PORTA, 0
das Problem ist jetzt das ich den PIC ein paar mal neu sarten muss bis 
das lauflicht mit nur einer LED durchläuft. Es scheint als würde der 
PORTA nicht richtig gelöscht werden, bevor der Wert B'00000001' 
geschrieben wird. Bzw. es wird ein falscher Wert reingeschrieben keine 
Ahnung. xD Kann mir jemand erklären wieso? Der Port wird doch mit clrf 
PORTA gelöscht?

von Chris B. (dekatz)


Lesenswert?

???? nur ein Schuß ins Blaue, aber initialisiere mal die Register in der 
Reihenfolge wie im DB
1
BANKSEL PORTA ;
2
CLRF    PORTA ;Init PORTA
3
BANKSEL ANSEL ;
4
CLRF    ANSEL ;digital I/O
5
BANKSEL TRISA ;
6
CLRF    TRISA ;

von W.S. (Gast)


Lesenswert?

Warum zum Kuckuck gönnst du deinem kleinen Programm nicht eine 
RAM-Zelle, wo du dein ominöses Lauflicht zelebrierst und anschließend 
nur noch auf den Port kopierst?

W.S.

von DasSauerkraut (Gast)


Lesenswert?

Bin erst seit ein paar Tagen dabei mich mit den PICs und Assembler 
auseinander zu setzen. =) Learning by doing =)

von Ottmar K. (wil1)


Lesenswert?

Hallo
Dein Programm hat in "Main" einen grundsätzlichen Fehler. Ein neuer 
Durchlauf kann nur erfolgen wenn Bit 0 wieder gesetzt wird (vgl. meinen 
Code wieter unten)

Beim Erlernen des Programmierens, sollte das Datenblatt des verwendeten 
Prozessors stets Schritt für Schritt zu Rate gezogen werden, das hilft 
viel gegen "Verirrungen" und Fehlschlüsse!

Dazu gibt es in MPLAB den Simulator "MPLAB-SIM" mit welchem man (fast) 
alle Möglichkeiten der PICs durchspielen kann.

-Datenblatt-

4.1 PORTA and the TRISA Register
PORTA is a 6-bit wide, bidirectional port. The corresponding data 
direction register is TRISA.
...Other PORTA pins are multiplexed with analog inputs and the analog 
VREF input for both the A/D converters and the comparators.

-Datenblatt Ausszug Ende-

Kurzum: Am PORTA stehen nicht 8, sondern nur 6 Bits zur Verfügung. Daher 
kann  "RLF" - ein 8bit-Schiebefehl an PORTA nicht ohne weiteres zum 
Durchschieben eines einzelnen Bits verwendet werden! Zudem werden einige 
Pins nach Reset/Neustart nicht als digitale I/O sonder als analoge 
Eingänge konfiguriert.

Besser ist es da schon PORTB oder PORTC zu verwenden. Dann klappt auch 
der Übertrag des letzten Bits "RB7" ins Carrybit als Indikator, dass 
jetzt alle Bits durchgeschoben sind. So kann RB0 erneut gesetzt werden.

-Alternativer Code-

Nachstehend habe ich Deinen Code mal entsprechend korrigiert (Die 
Initialisierung von PORTB habe ich mir geschenkt:

Main
    movlw  b'00000001' ;erstmal RB0=1 setzen
    movwf  PORTB
Main_Loop
    call    Delay100ms ;LED kurz zeigen, dann weiterschalten
    bcf     STATUS,C  ;Carry=0 (wird automatisch nach PORTB,RB0 kopiert)
    rlf      PORTB,f  ;LED um 1 bit weiter nach links schieben
    btfss   STATUS,C  ;Carry=1? letztes Bit von RB7 nach Carry
                      ;geschoben? Dann sind jetzt alle LEDs aus!
    GOTO   Main_Loop  ;NEIN, weiter mit bitshift left
    GOTO   Main       ;JA, wieder von vorn, dazu RB0=1 setzen

mfG Ottmar

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
Noch kein Account? Hier anmelden.