Forum: Mikrocontroller und Digitale Elektronik PCINT0 wird immer getriggert


von Franz (Gast)


Lesenswert?

Hallo, ich habe folgendes Problem...ich habe einen PCINT - Interrupt in 
meinem Programm, der andauernd triggert (anscheinend auch ohne 
Flankenwechsel) dieses Codebeispiel ist nur ein teil meines Programmes 
und soll dazu dienen, software-uart zu implementieren.

Ich verwende einen ATTINY85, AtmelStudio 7, AVR Dragon, AVR/GNU C 
Compiler...
Für den Software-Uart verwende ich eine Baudrate von 2400 baud/s
Also braucht ein bit bei mir zur übertragung 416 µs, ein halbes also 208 
µs

Weiß jemand, warum ich ständig in die ISR springe ??? Ich habe sonst nur 
diesen Pin (PINB0) einen PCINT zugewiesen und sonst keinen... mein 
empfangener Wert ist immer 1023 = 0b 0000 0011 1111 1111.......

Danke vielmals schon für die Hilfe im Voraus
1
#define F_CPU 8000000UL
2
#include <util/delay.h>
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <stdint.h>
6
7
static volatile uint16_t received_char = 0;
8
static volatile uint8_t bit_cnt_receiver = 0;
9
10
int main(void)
11
{
12
13
  DDRB &= ~(1<<PB0); //Input, der den Interrupt auslöst
14
15
  //PCINT
16
  GIMSK |= (1<<PCIE); //PinChangeInterrupt für PIN_UART_RX ist aktiv
17
  PCMSK |= (1<<PIN_UART_RX); //Pin Change enabled
18
19
  //TIMER 1
20
  TCCR1 |= (1<<CTC1); //Clear Timer on Compare Match
21
  TCCR1 |= (1<<CS12) | (1<<CS11); //Prescaller von 32 = 0,25 MHz Taktgeschwindigkeit
22
  OCR1A = 104; //Alle ~104 µs ein Tick
23
  TIMSK |= (1<<OCIE1A); //Interrupt bei OutputCompare enabled
24
  
25
  sei();        //Global Interrupts enabled
26
27
  while (1);
28
29
  return 0;
30
}
31
32
33
//--------------------------------------------------------------
34
/// Interrupt routine for PIN-Change for receiving 11 bits (Software-Uart-Receiving) (-> Command + Adress)
35
///
36
///
37
ISR(PCINT0_vect)
38
{
39
  if(PINB &= ~(1<<PB0)) //Bei fallender Flanke....startbit wird möglicherweise empfangen
40
  {
41
    _delay_us(208); //in der mitte des startbits
42
    
43
    if(PINB &= ~(1<<PB0)) //Bei low PEGEL....startbit wird empfangen
44
    {
45
      TIMSK |= (1<<OCIE1A); //Timer wird eingeschalten
46
      GIMSK &= ~(1<<PCIE); //PCINT wird ausgeschalten
47
      received_char = 0;
48
    }
49
  }
50
}
51
52
53
54
//--------------------------------------------------------------
55
/// Interrupt timing routine for counting bit for bit
56
///
57
///
58
ISR(TIMER1_COMPA_vect)
59
{
60
  
61
  if (PINB |= (1<<PB0))
62
  {
63
    received_char |= (1<<bit_cnt_receiver);
64
  }
65
66
  else
67
  {
68
    received_char &= ~(1<<bit_cnt_receiver);
69
  }
70
71
  bit_cnt_receiver++;
72
73
74
  if(bit_cnt_receiver>9)
75
  {
76
    bit_cnt_receiver = 0;
77
    TIMSK &= ~(1<<OCIE1A); //Timer wird ausgeschalten
78
    TCNT1 = 0; //Timer wird auf 0 gesetzt
79
    GIMSK |= (1<<PCIE);    //PCINT wird eingeschalten
80
  }
81
82
}

von Michael K. (Gast)


Lesenswert?

Franz schrieb:
> Weiß jemand, warum ich ständig in die ISR springe

Ohne weiter zu lesen:
Weil das IRQ Flag noch ansteht.
Irgendwas musst Du selber rücksetzen, ein Register lesen damit das Flag 
rückgesetzt wird, oder ähnliches.
Ist eigentlich immer so wenn man einen IRQ nicht mehr verlassen kann.

von Stefan F. (Gast)


Lesenswert?

Michael K. schrieb:
> Ohne weiter zu lesen:
> Weil das IRQ Flag noch ansteht.

Bei AVR werden die IRQ Flags automatisch zurück gesetzt, wenn man eine 
ISR hat.

von Felix U. (ubfx)


Lesenswert?

Franz schrieb:
> if (PINB |= (1<<PB0))

Damit togglest du deinen PB0 Pin. Das ergibt keinen Sinn.

> if (PINB &= ~(1<<PB0))

Und du solltest aufhören, beim Abfragen von Pins auch wieder in die 
entsprechenden Register zu schreiben. Außerdem solltest du aufhören, 
delays in ISRs zu verwenden.

von Hannes J. (hannes_j)


Lesenswert?

Der löst immer wieder aus weil du den Pin toggelst würde ich sagen. 
Glaube die = in deinen ifs sind zu viel.

Edit: Ah Felix hatte es über mir schon geschrieben

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Stefanus F. schrieb:

> Bei AVR werden die IRQ Flags automatisch zurück gesetzt, wenn man eine
> ISR hat.

Das ist längst nicht alle AVR8-Interrupts wahr, für die meisten 
allerdings schon. Für die hier verwendeten PCINT- und Timer-Interrupts 
auf jeden Fall.

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.