Hallo an alle Mitdenker!

Zitat Zitat von Andre_S Beitrag anzeigen
Grundvoraussetzung um wirklich „effektiv“ helfen zu können, wäre sicherlich die Offenlegung der Quellcodes ...
Hier kommt er - bewährt dysfunktional: (hoffentlich nicht sinnentstellend gekürzt)
Code:
;         list            p=16f876a          ; list directive to define processor
         #include        P16F876A.INC       ; processor specific variable definitions


    __CONFIG  _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC

; STATUS bit definitions

     #define    _C        STATUS,0          ; fuer die Kurzschreibung
     #define    _Z        STATUS,2          ; von Bitpruefungen "BTFSS _Z"




; Hardware-Signale
     ; PORT A
        ; Pins RA0/1/3 analog beschaltet
        ; Pin RA2 Ausgang ENL fuer LCD
        ; Pin RA4 Eingang
        ; Pin RA5 Ausgang ENR fuer Register

     ; PORT B
        ; LCD-Modul Und Latch: nur Ausgaenge
        ; Datenpuffer:  cio_lcd, dat_reg

; Flag-Bits
     #define    LCD_TXF   flaxa,0           ; =1: Sendeauftrag fuer ISR ans LCD
     #define    LCD_RS    flaxa,1           ; =1: Datenregister, =0: Befehlsregister
     #define    LZBLANK   flaxa,2           ; =1: unterdruecke fuehrende Nullen
     #define    REG_TXF   flaxa,3           ; =1: Sendeauftrag fuer Registerwerte
     #define    SCRFLAG   flaxa,6           ; =1: temporaeres Flag
;     #define    NEWDATA   flaxa,7           ; =1:



; gültig für f_OSZ = 12MHz (HS_OSC)
T1PREH             EQU    0xF4        ; preload = 2^16 - d'3000' = 0xF448 für 1000,0 Hz @ 12MHz /4, 1:1
T1PREL             EQU    0x48        ; d.h. 3000x 1µs bis zum Overflow



;***** KONSTANTEN *****
ADR_BMA020         EQU    0x70        ; I2C-Basisadresse des g-Sensors


; Pin-Nummern fuer LCD und Out-Register
BIT_ENL            EQU    d'2'        ; Port A: LCD-Enable-Signal
BIT_ENR            EQU    d'5'        ; Port A: Out-Register-EN an
BIT_RW             EQU    d'2'        ; Port B: Read- /Write-Signal LCD
BIT_RS             EQU    d'1'        ; Port B: RegisterSelect-Signal,   Funktion: Data bzw. /Instruction


;***** BANK(0)-EXKLUSIVE REGISTER  0x20..0x6F
    CBLOCK   0x20
      cio_lcd       ; Datenpuffer LCD
      dat_reg       ; Datenpuffer OpenColl, Register
      cio_dac       ; Datenpuffer Digital-Analog-Wandler (D7..D0 --> D0..7, seitenverkehrt)
      mscr          ; Scratch Byte fuer das Hauptprogramm (alles ausser ISR)
      iscr          ; Scratch Byte fuer die Interrruptausfuehrung (ISR)
      buf_ra        ; EN-Ausgaenge LCD und Register
      sta_ra        ; dig. Eingang
      buf_rc        ; falls mal Ausgaenge sein werden
      sta_rc        ; Tasteneingaenge
      flaxa         ; div. Flags
      dat_lcd       ; Netto-/Nutz-Daten zum LCD; NICHT die Bitleiste inkl. Steuersignale am Bus: das ist cio_lcd
      cur_zsp       ; Text-Position Zeile,Spalte
      cur_cmd       ; DisplayDataRAM-Adresse fuer LCD-Modul
      txt_fst       ; "first char"-Index des gewaehlten Fixtexts
      txt_idx       ; Laufvariable
      i2c_adr       ; Device-Adresse
      i2c_reg       ; Registeradresse im Device
      i2c_dat       ; Dateninhalt des Registers
      loopcount     ; frei verfuegbarer Durchlaufzaehler
      gxraw         ; Rohwert-MSB g-Sensor x-Achse
      gyraw         ; Rohwert-MSB g-Sensor y-Achse
      gzraw         ; Rohwert-MSB g-Sensor z-Achse
    ENDC ;


;***** GLOBALE VARIABLEN  0x70..0x7F
dlycnt             EQU        0x7A          ; allg. Delay-Restzyklen zu je 1ms
ticker             EQU        0x7B          ; allg. Laufvariable u.a. fuer das Lebenszeichen
tickerh            EQU        0x7C          ; Folgestufe zur Zaehlung der ticker-Ueberlaeufe
temp_w             EQU        0x7D          ; variable used for context saving
temp_status        EQU        0x7E          ; variable used for context saving
temp_pclath        EQU        0x7F          ; variable used for context saving






;**********************************************************************
;                                 ; Begin of 2k-Code Page #0  (1/4)
         ORG     0x0000           ; processor reset vector
;**********************************************************************

         nop                      ; nop required for icd
         goto    MAIN             ; go to beginning of program
         nop
         nop



;**********************************************************************
         ORG     0x004            ; interrupt vector location
;**********************************************************************


;**********   Kontext sichern   **********
         movwf   temp_w           ; save off current W register contents
         movf    STATUS,w         ; move status register into W register
         movwf   temp_status      ; save off contents of STATUS register
         movf    PCLATH,w         ; move pclath register into w register
         movwf   temp_pclath      ; save off contents of PCLATH register

         ; Lead-In
         bcf     STATUS,RP0       ;
         bcf     STATUS,RP1       ; Bank 0 als default
         bcf     PCLATH,4         ;
         bcf     PCLATH,3         ; Code Page #0




;;************** ANFANG DER TMR1-ISR *******************
ISR_TMR1
         bcf     PIR1,TMR1IF      ; auslösendes Flag löschen
         movlw   T1PREH           ; Preload-Werte laden
         movwf   TMR1H            ;
         movlw   T1PREL           ;
         movwf   TMR1L            ;


ISR_DIGIN
         ; Momentaufnahmen der dig. Eingaenge
         movf    PORTA,w          ;
         movwf   sta_ra           ;
         movf    PORTC,w          ;
         movwf   sta_rc           ;
ISR_DIGIN_E


ISR_LCD
         ; LCD bedienen
         btfss    LCD_TXF         ; ToDo-Flag da? Sendeauftrag?
         goto     ISR_LCD_E       ; =0: nix zu tun
         bcf      LCD_TXF         ; Arbeit da; Flag loeschen
         movf     cio_lcd,w       ;
         movwf    PORTB           ;
         bsf      buf_ra,BIT_ENL  ; das Bit fuer EN am LCD
         movf     buf_ra,w        ;
         movwf    PORTA           ; LCD enable aktiv
         nop                      ; Wartezeit, ...
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ; 6*  0,33us = 2us
         bcf      buf_ra,BIT_ENL  ;
         movf     buf_ra,w        ;
         movwf    PORTA           ; LCD enable wieder passiv
         nop                      ; Wartezeit, ...
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ; 6*  0,33us = 2us
ISR_LCD_E


ISR_REG
         ; Register bedienen
         btfss    REG_TXF         ; neue Daten ?
         goto     ISR_REG_E       ; DAC ohne Auftrag nicht stoeren (DAC haengt DIREKT am PORTB)
         bcf      REG_TXF         ; Arbeit da; Flag loeschen
         movf     dat_reg,w       ;
         movwf    PORTB           ;
         bsf      buf_ra,BIT_ENR  ; das Bit fuer EN am Register
         movf     buf_ra,w        ;
         movwf    PORTA           ; Register-enable aktiv
         nop                      ; Wartezeit, ...
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ; 6*  0,33us = 2us
         bcf      buf_ra,BIT_ENR  ;
         movf     buf_ra,w        ;
         movwf    PORTA           ; Register-enable wieder passiv
         nop                      ; Wartezeit, ...
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ;
         nop                      ; 6*  0,33us = 2us
ISR_REG_E



         ; Millisekunden-Eieruhr
         movf    dlycnt,f         ; Z-Flag generieren
         btfss   STATUS,Z         ;
         decf    dlycnt,f         ; dekr., wenn nicht null (Z=0)


         ; Hier laeuft die 'Unruh' des Controllers bzw. seiner Firmware
         incf    ticker,f         ; universell und immer in Bewegung
         movf    ticker,w         ;
         btfsc   _Z               ;
         incf    tickerh,f        ;


  

         ; abschliessende Arbeiten vor Ende der ISR:
ISR_TAIL
            ; ... derzeit nichts



;************** ENDE DER TMR1-ISR *******************

ISR_RESTORE
         ; Kontext wiederherstellen
         movf    temp_pclath,w    ; retrieve copy of PCLATH register
         movwf   PCLATH           ; restore pre-isr PCLATH register contents
         movf    temp_status,w    ; retrieve copy of STATUS register
         movwf   STATUS           ; restore pre-isr STATUS register contents
         swapf   temp_w,f         ; Kniff: W laden, ohne den Status zu veraendern !
         swapf   temp_w,w         ; restore pre-isr W register contents

         retfie                   ; return from interrupt (bewirkt auch ein "bsf INTCON,GIE")


;***
MAIN                    ;  Das Hauptprogramm



         ; RAM (partiell) initialisieren
         movlw   0x20             ; erste Speicherzelle
         movwf   FSR              ; Zeiger setzen
RAMCLR
         clrf    INDF             ; Zugriff !
         incf    FSR,f            ; naechste Zelle
         btfss   FSR,7            ; fertig ?  Zeiger >= 0x80 ?
         goto    RAMCLR           ; NEIN
RAMCLR_E


         ; Portregister fuer digitale Ausgaenge initialisieren

         movlw   b'00010000'      ; 5: EN des Registers, 4: OC, 2: EN des LCD
         movwf   buf_ra           ;
         movwf   PORTA            ; (Umbau-bedingte Abweichung von meinem Anschlussprinzip)
         movlw   b'00000000'      ;
         movwf   cio_lcd          ;
         movwf   PORTB            ;
         movlw   b'00000000'      ; PORTC[4;3] unbedingt auf "L" setzen,
         movwf   buf_rc           ;
         movwf   PORTC            ; damit der I2C-Bus-Reset durchfuehrbar ist


         ; I/O-Leitungen konfigurieren
         banksel TRISA

         movlw   b'11001011'      ; 5: EN Register, 4: OC, 3, 1, 0: ANx, 2: EN LCD
         movwf   TRISA            ;
         movlw   b'00000000'      ; alles Ausgaenge fuer LCD-Modul, Register, DAC
         movwf   TRISB            ;
         movlw   b'11111000'      ; 7..5: Tasten; 4,3: I2C; 2,1: PWM, 0: I/O
         movwf   TRISC            ;

         banksel PORTA            ; Bank 0



         ; ADC konfigurieren
         bsf     STATUS,RP0       ; Bank 1
         movlw   b'01000100'      ; Fosc/64 left just.
         movwf   ADCON1           ;
         bcf     STATUS,RP0       ; Bank 0

         movlw   b'10011000'      ; Start mit Poti-Kanal
         movwf   ADCON0           ;


 

         ; Timer1 Prescaler  konfig. & Preload
         ; gültig für f_OSZ = 4MHz (HFINTOSC-default prescaler 2:1)
         movlw   b'00000000'      ;
         movwf   T1CON            ;
         movlw   T1PREH           ; preload = 2^16 - d'3000' für 1000,0 Hz @ 12MHz /4, 1:1
         movwf   TMR1H            ; d.h. 3000x 0,333µs bis zum Overflow
         movlw   T1PREL           ;
         movwf   TMR1L            ;


         ; Interrupts enablen, Timer in Gang setzen
         bsf     INTCON,PEIE      ; Gruppe der Peripherals
         bsf     INTCON,GIE       ; globales Enable
         bsf     STATUS,RP0       ; Bank 1
         bsf     PIE1,TMR1IE      ; Timer 1: 1= IRQ enable
         bcf     STATUS,RP0       ; Bank 0
         bsf     T1CON,TMR1ON     ; Timer 1: 1= starten


         ; I2C Bus Recovery, falls erforderlich
I2CCLR_A
         btfss   PORTC,3          ; SCL-Signal
         goto    I2CCLR           ;
         btfss   PORTC,4          ; SDA-Signal
         goto    I2CCLR           ;
         goto    I2CCLR_E         ; keines von beiden ist low, Bus ist frei
I2CCLR
         bsf     STATUS,RP0       ; Bank 1
;         bcf     TRISC,3          ; SCL aktiv = low, fallende Taktflanke
  movf TRISC,w
  andlw  b'11110111'
  movwf TRISC
         bcf     STATUS,RP0       ; Bank 0
         movlw   d'5'             ;
         call    P0_IDLE          ; ... und warten
         ;
         bsf     STATUS,RP0       ; Bank 1
;         bsf     TRISC,3          ; SCL passiv = high, steigende Taktflanke
  movf TRISC,w
  iorlw  b'00001000'
  movwf TRISC
         bcf     STATUS,RP0       ; Bank 0
         movlw   d'5'             ;
         call    P0_IDLE          ; ... und warten

         goto    I2CCLR_A         ; Bus frei? Testen!

I2CCLR_E
         bsf    buf_rc,3          ;
         bsf    buf_rc,4          ; eventuell loest dies hier das Nichtfunktionieren der I2C-Verbindung
         movf   buf_rc,w          ;
         movwf  PORTC             ;




         ; LCD-Modul initialisieren
         pagesel LCD_INIT         ;
         call    LCD_INIT         ; Basisinitialisierung
;         pagesel LCD_CGRAM        ;
;         call    LCD_CGRAM        ; laden der frei definierbaren Zeichen
         pagesel MAIN             ;


         ; I2C initialisieren
         pagesel I2C_INIT100      ;
         call    I2C_INIT100      ; I2C mit 100kHz starten
         pagesel MAIN             ;


   movlw  d'5'
  call P0_IDLE



;**********************************************************************
;                    Anfang der Hauptschleife
;**********************************************************************


SCHLEIFE

;  incf loopcount,f

         pagesel ACC_GETGXYZ
         call    ACC_GETGXYZ
         pagesel SCHLEIFE

; Unterfunktion zum Test des g-Sensormoduls BMA020

      ; X-Komponente anzeigen
         movlw   0x11             ; Cursor positionieren
         movwf   cur_zsp          ;
         pagesel LCD_SETCURSOR    ;
         call    LCD_SETCURSOR    ;

  ; gekürzt

      ; Y-Komponente anzeigen
         movlw   0x21             ; Cursor positionieren
         movwf   cur_zsp          ;
         pagesel LCD_SETCURSOR    ;
         call    LCD_SETCURSOR    ;

  ; gekürzt


      ; Z-Komponente anzeigen
         movlw   0x28             ; Cursor positionieren
         movwf   cur_zsp          ;
         pagesel LCD_SETCURSOR    ;
         call    LCD_SETCURSOR    ;

  ; gekürzt

         ;  Kontrolle fuer zyklischen Schleifendurchlauf
         movlw   0x18             ; Cursor positionieren
         movwf   cur_zsp          ;
         pagesel LCD_SETCURSOR    ;
         call    LCD_SETCURSOR    ;

  ; gekürzt



         pagesel SCHLEIFE
         goto    SCHLEIFE
;**********************************************************************
;                    Ende der Hauptschleife
;**********************************************************************




P0_IDLE
         ; Prinzip: "Jeder Code Page ihre eigene Bummelfunktion"
         ; wartet stur, bis die ISR den Zaehler dlycnt bis Null heruntergezaehlt hat
         ; benutzt dabei den selben Zaehler wie LCD_IDLE
         movwf   dlycnt           ; Delayzeit wird im W-Register geliefert
P0_IDLE_1
         movf    dlycnt,f         ; zero flag generieren
         btfss   STATUS,Z         ; bei Z=1 ausbrechen
         goto    P0_IDLE_1        ;

         return                   ;






;**********************************************************************
;**********************************************************************
         ORG     0x0800   ; Begin of 2k-Code Page #1  (2/4)
;**********************************************************************
;**********************************************************************





;;**********************************************************************
;; Initialisierung des I2C-Moduls
;I2C_INIT100
;         movlw   b'00001000'      ; I2C Master Mode mit SSPADD
;         movwf   SSPCON           ;
;         bsf     SSPCON,SSPEN     ; und aktivieren
;         ;
;         bsf     STATUS, RP0      ; Bank 1
;         movlw   0x27             ; Achtung: Tabelle im Datenblatt des PIC16F87xA ist falsch; siehe MSSP-Errata
;;         movlw   0xFF             ; Test, minimale Frequenz
;         movwf   SSPADD           ; Reload-Wert fuer Clock-Takt
;         bcf     STATUS, RP0      ; Bank 0
;
;         banksel SSPSTAT
;         bsf     SSPSTAT,SMP      ; =1: _disable_ slew rate control
;         bcf     SSPSTAT,CKE      ;  disable  SMP-specific inputs
;         banksel PORTA
;         ;
;         return                   ;

;**********************************************************************
; Initialisierung des I2C-Moduls
I2C_INIT100
         bsf     STATUS, RP0      ; Bank 1
         movlw   0x27             ; etwa 100kHz bei 12MHz-Oszillator
         movwf   SSPADD           ; Reload-Wert für Clock-Takt
         bcf     STATUS, RP0      ; Bank 0
         ;
         movlw   b'00001000'      ; I2C Master Mode mit SSPADD
         movwf   SSPCON           ;
         bsf     SSPCON,SSPEN     ; und aktivieren
         ;
         return                   ;






;**********************************************************************
; Beschleunigungsmesswerte aus dem BMA020 abholen: b.a.w. nur 3 MSBytes;
; Die hier implementierte I2C-Protokoll-Makrostruktur ist Chip-spezifisch.

ACC_GETGXYZ
         ; *********************** Ordnung und Ruhe am I2C-Bus ***************
;         call    I2C_SETTLE       ; MSSP-Modul neu starten
         ; ******
;         call    I2C_W_STOP       ; weitere Bus-Aktivitaeten unterbinden


         ; *************************************************************
         ; *** Protokollzyklus: Accelerometer auslesen               ***
         ; *************************************************************

         ; *********************** Kommunikation starten ***************

        call    I2C_W_START      ; (erstmalig) Start-Bedingung senden



         ; *********************** Adresspointer setzen ***************
         movlw   ADR_BMA020       ; Device schreibend (R/W = 0) adressieren
         movwf   SSPBUF           ; ... und senden
         call    I2C_R_ACK        ; /ACK vom Slave abwarten
         ; ******
         movlw   0x02             ; Adresspointer
         movwf   SSPBUF           ; ... senden
         call    I2C_R_ACK        ; /ACK vom Slave abwarten


         ; *********************** Device auslesen ***************
         call    I2C_W_START      ; (erneut) Start-Bedingung senden
         ; ******
         movlw   ADR_BMA020       ; Device lesend (R/W = 1) adressieren
         iorlw   0x01             ; R/W = 1
         movwf   SSPBUF           ; senden
         call    I2C_R_ACK        ; /ACK vom Slave abwarten
         ; ******
         call    I2C_R_BYTE       ; Byte anfordern (02h) und verwerfen
         movf    SSPBUF,w         ; dummy read
         call    I2C_W_ACK        ; /ACK senden
         ; ******
         call    I2C_R_BYTE       ; Byte anfordern (03h)
         movf    SSPBUF,w         ; Datum
         movwf   gxraw            ; ... uebernehmen
         call    I2C_W_ACK        ; /ACK senden
         ; ******
         call    I2C_R_BYTE       ; Byte anfordern (04h) und verwerfen
         movf    SSPBUF,w         ; dummy read
         call    I2C_W_ACK        ; /ACK senden
         ; ******
         call    I2C_R_BYTE       ; Byte anfordern (05h)
         movf    SSPBUF,w         ; Datum
         movwf   gyraw            ; ... uebernehmen
         call    I2C_W_ACK        ; /ACK senden
         ; ******
         call    I2C_R_BYTE       ; Byte anfordern (06h) und verwerfen
         movf    SSPBUF,w         ; dummy read
         call    I2C_W_ACK        ; /ACK senden
         ; ******
         call    I2C_R_BYTE       ; LETZTES Byte (07h) anfordern
         movf    SSPBUF,w         ; Datum
         movwf   gzraw            ; ... uebernehmen
         call    I2C_W_NACK       ; NACK senden

  incf loopcount,f  ; zu Testzwecken

         ; *********************** Kommunikation beenden ***************
         call    I2C_W_STOP       ; Stop-Bedingung senden

         ; *************************************************************
         ; *** Ende Protokollzyklus                                  ***
         ; *************************************************************

         return                   ;






;**********************************************************************
; nachfolgend die granularen I2C-Protokollelemente
;**********************************************************************


;**********************************************************************
; universeller Pseudo-Befehl "I2C-Bus zur Ruhe bringen" (Master)
I2C_SETTLE
;         bcf     I2C_TO           ; Stoermeldung optimistisch loeschen
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bcf     SSPCON,SSPEN     ; MSSP deaktivieren
         nop                      ;
         nop                      ;
         nop                      ;
         bsf     SSPCON,SSPEN     ; und neu starten
         nop                      ;
         nop                      ;
         nop                      ;

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Start senden" (Master)
; Blockierungspotential: Fehldiagnose "Bus-Kollision" durch EMI oder Kupferwurm
I2C_W_START
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bsf     STATUS, RP0      ; Bank 1
         bsf     SSPCON2,SEN      ; Start-Kondition einleiten
         bcf     STATUS, RP0      ; Bank 0
  btfsc  SSPCON,WCOL
  goto I2C_W_START
I2CWSTART
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

         btfss   PIR1,SSPIF       ; /ACK schon empfangen ?
         goto    I2CWSTART        ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Repeated Start senden" (Master)
; Blockierungspotential: Fehldiagnose "Bus-Kollision" durch EMI oder Kupferwurm
I2C_W_RSTART
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bsf     STATUS, RP0      ; Bank 1
         bsf     SSPCON2,RSEN     ; Repeated-Start-Kondition einleiten
         bcf     STATUS, RP0      ; Bank 0
;  btfsc  SSPCON,WCOL
;  goto I2C_W_RSTART
I2CWRSTART
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

         btfss   PIR1,SSPIF       ; /ACK schon empfangen ?
         goto    I2CWRSTART       ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Acknowledge /ACK vom Slave abwarten" (Master)
; Blockierungspotential: /ACK nicht detektiert
I2C_R_ACK
I2CRACK
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

         btfss   PIR1,SSPIF       ; /ACK schon empfangen ?
         goto    I2CRACK          ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Byte vom Slave holen" (Master)
; Blockierungspotential:
I2C_R_BYTE
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bsf     STATUS, RP0      ; Bank 1
         bsf     SSPCON2,RCEN     ; Empfangsbereitschaft herstellen
         bcf     STATUS, RP0      ; Bank 0
I2CRBYTE
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

           ; Dateneingang abwarten
         btfss   PIR1,SSPIF       ; Empfangsdaten im Buffer ?
         goto    I2CRBYTE         ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Acknowledge /ACK senden" (Master)
; (das ist ein Acknowledge mit aufforderndem Beigeschmack)
I2C_W_ACK
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bsf     STATUS, RP0      ; Bank 1
         bcf     SSPCON2,ACKDT    ; Ackn.-Pegel =0 setzen: --> /ACK (=0)
         bsf     SSPCON2,ACKEN    ; /ACK-Sequenz starten
         bcf     STATUS, RP0      ; Bank 0
I2CWACK
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

           ; warten auf Ende der Acknowledge-Sequenz
         btfss   PIR1,SSPIF       ; Sequenz schon beendet ?
         goto    I2CWACK          ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Not-Acknowledge NACK senden" (Master)
; (das ist ein Acknowledge mit abweisendem Beigeschmack)
I2C_W_NACK
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bsf     STATUS, RP0      ; Bank 1
         bsf     SSPCON2,ACKDT    ; Ackn.-Pegel =1 setzen --> NACK : "OK, aber keine weiteren Daten erwuenscht"
         bsf     SSPCON2,ACKEN    ; NACK-Sequenz starten
         bcf     STATUS, RP0      ; Bank 0
I2CWNACK
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

         btfss   PIR1,SSPIF       ; Sequenz schon beendet ?
         goto    I2CWNACK         ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;
;**********************************************************************
; universeller I2C-Befehl "Stop senden" (Master)
I2C_W_STOP
         bcf     PIR1,SSPIF       ; I2C-Int.Request
         bsf     STATUS, RP0      ; Bank 1
         bsf     SSPCON2,PEN      ; Stop-Sequenz starten
         bcf     STATUS, RP0      ; Bank 0
I2CWSTOP
;         btfsc   I2C_TO           ; wenn I2C-Stoerung,
;         return                   ; dann nicht warten !

         btfss   PIR1,SSPIF       ; Sequenz schon beendet ?
         goto    I2CWSTOP         ;
         bcf     PIR1,SSPIF       ; JA, fertig !

         return                   ;

;**********************************************************************
;**********************************************************************
         ORG     0x1000   ; Begin of 2k-Code Page #2  (3/4)
;**********************************************************************
;**********************************************************************








;**********************************************************************
;**********************************************************************
         ORG     0x1800   ; Begin of 2k-Code Page #3  (4/4)
;**********************************************************************
;**********************************************************************







;**********************************************************************
LCD_IDLE
         ; wartet stur, bis die ISR den Zaehler dlycnt bis Null heruntergezaehlt hat
         movwf   dlycnt           ; Delayzeit wird im W-Register geliefert
LCD_IDLE_1
         movf    dlycnt,f         ; zero flag generieren
         btfss   STATUS,Z         ; bei Z=1 ausbrechen
         goto    LCD_IDLE_1       ;

         return                   ;
;**********************************************************************
LCD_PUSH         ; nur jeweils EIN 4-bit-Uebertragungsvorgang, weil in der fruehen Initialisierungsphase
                 ; variable Wartezeiten, daher kein delay eingebaut
         movf    dat_lcd,w        ; Nettodaten holen
         andlw   0xF0             ; D7..D4 isolieren; RS (D/I) und RW sind damit passend "L" eingestellt
         movwf   cio_lcd          ; Uebergabewert speichern
         bsf     LCD_TXF          ; Uebergabe-Flag fuer ISR setzen
LCD_PUSH_1
         btfsc   LCD_TXF          ; Flag=0  --> ISR hat uebernommen!  ?
         goto    LCD_PUSH_1       ;

         return                   ;

;**********************************************************************
LCD_INIT
         pagesel LCD_IDLE

         movlw   d'30'            ;
         call    LCD_IDLE         ; >= 15ms nach PowerOn warten

         movlw   0x30             ; 0x30: Reset
         movwf   dat_lcd          ;
         call    LCD_PUSH         ;
         movlw   d'10'            ;
         call    LCD_IDLE         ; >= 4.1ms warten

         movlw   0x30             ; 0x30: Reset
         movwf   dat_lcd          ;
         call    LCD_PUSH         ;
         movlw   d'3'             ;
         call    LCD_IDLE         ; >= 100us warten; 1ms kann auch 0us sein!

         movlw   0x30             ; 0x30: Reset
         movwf   dat_lcd          ;
         call    LCD_PUSH         ;
         movlw   d'3'             ;
         call    LCD_IDLE         ; Verarbeitungszeit weiterhin jeweils 1ms + X  ?????

         movlw   0x20             ; 0x20: 4-bit-Datenbus
         movwf   dat_lcd          ;
         call    LCD_PUSH         ;
         movlw   d'3'             ;
         call    LCD_IDLE         ; >= 1ms interne Verarbeitungszeit ?????

         ; ab hier wird explizit 4-bit-weise auf D[7:4] kommuniziert,
         ; zuerst oberes Nibble, dann unteres Nibble

         movlw   0x28             ; 0x28: System Set: 4-Bit / 2-zeilig
         movwf   dat_lcd          ;
         call    LCD_CMD          ;
         movlw   d'3'             ;
         call    LCD_IDLE         ;

         movlw   0x06             ; 0x06: Entry Mode: v.l.n.r. ohne shift
         movwf   dat_lcd          ;
         call    LCD_CMD          ;
         movlw   d'3'             ;
         call    LCD_IDLE         ;

         movlw   0x01             ; 0x01: Clear Display
         movwf   dat_lcd          ;
         call    LCD_CMD          ;
         movlw   d'10'            ;
         call    LCD_IDLE         ;

         movlw   0x0C             ; 0x0C: Display On, kein Cursor
         movwf   dat_lcd          ;
         call    LCD_CMD          ;
         movlw   d'10'            ;
         call    LCD_IDLE         ;

         return                   ;

         END                      ; directive 'end of program'
Zitat Zitat von Siro Beitrag anzeigen
Ich hab jetzt nicht ganz verstanden warum Du das RC3 Bit einmal auf Input und dann wieder auf Output setzt, das ist doch die Clockleitung
Zitat Zitat von witkatz Beitrag anzeigen
das Gleiche passiert hoffentlich auch mit TRISC,4 (s. MSSP Erratum)
Nein, warum auch?? Wir sprechen hier über einen I2C-Master. Dieses Vorgehen emuliert den OpenDrain der SCL-Leitung des Masters. Das funktioniert bei einem anderen Projekt makellos und ich habe dieses Vorgehen auch bei meiner Recherche bestätigt gefunden. Es werden so lange SCL-Takte erzeugt, bis die SDA-Leitung frei (=1) ist und der Master den I2C-Startbefehl auf dem Bus durchsetzen kann.

Zitat Zitat von witkatz Beitrag anzeigen
Mit TRISC passiert nach der Aktivierung des MSSP-Moduls nichts mehr? V.a. kein bcf/bsf
Definitiv nein, soweit es um explizite Zugriffe auf TRISC geht. Zwischenzeitlich habe ich die bcf/bsf-Befehle für den Busreset auch noch durch lesen, AND/OR und schreiben ersetzt, alles ohne Erfolg.

Zitat Zitat von witkatz Beitrag anzeigen
Falls du LCD auch mit PORTC ansteuerst, ...
Ist nicht der Fall.


Liebe Grüße
RoboHolIC