Forum: Mikrocontroller und Digitale Elektronik einzelnen PIN eines ATTiny 2313 abfragen-SRF04 US Devantech


von Tilman (Gast)


Lesenswert?

Hallo Leute,
vielleicht kann mir einer von Euch weiterhelfen, ich beisse im Moment
auf Granit:

Ich möchte an einem AT Tiny 2313 den PIN 3 von PortD auf High oder Low
abfragen. Wenn er High ist, soll über UART eine 1 an mein
Terminalprogramm geschickt werden (das Ganze läuft auf einem STK500).
Wenn der Pin Low ist, soll eine Null gesendet werden. Soweit, so gut.
Gedacht ist das, um das Echosignal eines SRF04 Ultraschallmoduls
abzufragen.

Um ein Signal erstmal zu simulieren lasse ich PINB0 meines Tiny2313 0,2
Sekunden ein High-Signal schicken, dann 0,2 Sekunden Low. Verbunden habe
ich den PINB0 des Tiny mit PIND3. Das Ganze funktionert auch mit einer
LED, die ich mit PINB0 verbunden habe. Sie blinkt brav mit 2,5Hz vor
sich hin. Aber wenn ich jetzt statt diese LED blinken zu lassen, eine
0, bzw. 1 über UART rausschicke, dann bekomme ich entweder nur Nullen,
oder nur Einsen am Hyperterminal. Ich raffs nicht. Benutzt habe ich
einen Teil des Programms "extinttest.asm" hier aus dem Tutorial.
Dabei ist INT0=0 und INT1=1, d.h., es sollte bei jeder Änderung am PIN
der entsprechende Zustand auch rausgeschickt werden (Hoffe, ich stelle
das hier verständlich dar). Aber ich bekomme nur Nullen. Wenn ich
INT0=1 und INT1=1 mache, dann bekomme ich nur Einsen (und das auch noch
viel langsamer als die Nullen im vorherigen Fall...) Kann mir jemand
weiterhelfen ?
Hier ist mein Code:

.include "tn2313def.inc"

.def temp = r16
.equ CLOCK = 4000000
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1

.org 0x000
         rjmp main            ; Reset Handler
.org INT1addr
         rjmp int1_handler    ; IRQ1 Handler

main:
        ; Stackpointer initialisieren
        ldi temp, LOW(RAMEND)
        out SPL, temp

        ; Baudrate einstellen
        ldi temp, LOW(UBRRVAL)
        out UBRRL, temp
        ldi temp, HIGH(UBRRVAL)
        out UBRRH, temp

        ; Frame-Format: 8 Bit
        ldi temp, (1<<UCSRC)|(3<<UCSZ0)
        out UCSRC, temp

        sbi UCSRB,TXEN                    ; TX aktivieren

       ldi temp, 0b00001000  ;00:Low Level , 01: jede Änderung, 10:
fallende Flanke, 11: steigende Flanke
         out MCUCR, temp

         ldi temp, 0b11000000  ;INT1 (PD 3) aktivieren
         out GIMSK, temp

  ldi temp, 0x00             ; Port D = Eingang
        out DDRD, temp

  ldi temp, 0xFF             ; Port B = Ausgang
        out DDRB, temp

        sei                  ;Interrupts allgemein aktivieren


;***Send 200ms pulse to PB0:
fire:
    ldi temp, 0xff
          out DDRB,temp
    ;out PORTB,temp
         rcall pause        ;wait 200 ms

    ldi temp, 0x00
    out DDRB,temp
    ;out PORTB,temp
         rcall pause
    rjmp fire
;***200 ms pulse has been sent

int1_handler:
    sbic PIND,3
    ldi r24,'1'
    sbis PIND,3
    ldi r24,'0'

    ldi temp, 0xff
    out DDRB, temp
    rcall pause
    ldi temp, 0x00
    out DDRB, temp
    rcall pause

int0_:  sbis UCSRA,UDRE      ; Warten bis UDR bereit ist
  rjmp int0_
        out UDR, r24
       reti

pause:
; =============================
;   Warteschleifen-Generator
;     800000 Zyklen: (200 ms)
; -----------------------------
; warte 799995 Zyklen:
          ldi  , $5F
WGLOOP0:  ldi  , $17
WGLOOP1:  ldi  , $79
WGLOOP2:  dec
          brne WGLOOP2
          dec
          brne WGLOOP1
          dec
          brne WGLOOP0
; -----------------------------
; warte 3 Zyklen:
          ldi  , $01
WGLOOP3:  dec
          brne WGLOOP3
; -----------------------------
; warte 2 Zyklen:
          nop
          nop
; =============================
ret

von remo (Gast)


Lesenswert?

Gib doch einfach mal an einem freien Pin den Wert des Registers R24 aus
und hänge über einen Vorwiderstand eine LED an den Port.
So kannst du zumindest eingrenzen, ob dein Problem am Einlesen von D3
oder am Ausgeben des Seriellen Wertes liegt.

Viel Glück beim Suchen
Remo

von Rolf Magnus (Gast)


Lesenswert?

Deine Interrupt-Routine sichert keinerlei Register, und auch die Flags
werden nicht gesichert. Außerdem solltest du in deiner
Interrupt-Routine eher nicht in einer Warteschleife auf die
Schnittstelle warten, denn während dieser Zeit bleibt auch deine
Pin-toggle-Schleife stehen. Und warum hast du innerhalb der
Interrupt-Routine noch mal eine zweite toggle-Schleife?
Und warum nimmst du zum Toggeln DDRB? Damit schaltest du den Port nur
zwischen Eingang und Ausgang um.

von Tilman (Gast)


Lesenswert?

Danke Remo.
Danke Rolf, ja ja, Du hast Recht, viele Fragen, auf die ich selbst
nicht genau die Antwort kenne, was ein sicherer Hinweis darauf ist,
dass es mir im mOment noch stark am nötigen Know How fehlt. Ich muss
das alles noch mal neu machen.
Die Warteschleife ist dazu da, um eine Zustandsänderung am PIND3
sichtbar zu machen, d.h. also mal kurz warten und währenddessen die
LEDs an PORT B anmachen, damit ich halt sehe, dass sich da was tut.
Ich beutze DDRB, weil wenn ich "out PORTB" schreibe, dann gehen die
LEDs nicht an, das klappt irgendwie nur mit "out DDRB", ist schon
klar, dass das eigentlich das Richtungsregister ist.
Na ja, danke für die Hilfe.

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.