Forum: Mikrocontroller und Digitale Elektronik AVR Arduino Timerproblem


von Shaggie S. (shaggie)


Angehängte Dateien:

Lesenswert?

Hallo,

mein Projekt ist ein K-line OBD Sniffer. Ich möchte die Bytes lesen die 
Übertragen werden, dafür nehme ich einen Arduino Nano Clone.
Es handelt sich also um einen ATMega328p. Zur Programmierung nutze ich 
das Ardunio Studio.

Die Baudrate des K-Line-Bus liegt bei 10400 Baud, ich habe nun zu 
Testzwecken eine TTL UART USB Stick mit CP2101 auf 9600 Baud eingestellt 
und sende ein Signal mit Druck der a-Taste und versuche dieses nun mit 
dem Arduino zu messen. Jedoch kommt dabei nicht immer das richtige 
Ergebnis raus.
Um nun zu überprüfen woran es liegt, habe ich einen Logicanalyzer eines 
Bekannten geliehen, um zu schauen was der Timer so macht.

Dabei kommt raus, dass der Timer schon bei Aktivierung einen Interrupt 
wirft. Was mir nicht einleuchtet, da er erstmal loszählen soll. Das er 
28µs benötigt um loszulegen stört mich nicht. aber dass der erste 
Timerlauf nur 54µs dauert, an Stelle von 104µs, verwundert mich sehr.

Woran kann das liegen?

Ergebnis siehe Anhang.
Erklärung zum Bild:
Kanal 0 ist das Signal vom UART Stick
Kanal 1 das alternierende Debugsignal des Arduino
1
// digital pin 2 has a K-LineWire attached to it. Give it a name:
2
int kLinePin = 2;
3
// globaler Counter
4
int counter = 0;
5
// zustandsvariable für die Messung
6
byte messung = 0x00;
7
// ergebnisbyte
8
byte kLineByte = 0x00;
9
10
// the setup routine runs once when you press reset:
11
void setup() {
12
  // initialize serial communication at 115200 bits per second:
13
  Serial.begin(9600);
14
  
15
  pinMode(kLinePin, INPUT);   // Pin D2 als input setzen
16
  pinMode(3, OUTPUT);         // Pin D3 für debug als output setzen
17
  
18
  digitalWrite(3,1);          // setze Pin D3 internen pullup
19
  digitalWrite(kLinePin,1);   // setze Pin D2 internen pullup
20
  
21
  noInterrupts();             // Alle Interrupts temporär abschalten
22
  
23
  // Timer 1 setzen
24
  TCCR1A = 0x00;                 // Timer Control Register mit 0 initialisieren
25
  TCCR1B = 0x00;                 // Timer Control Register mit 0 initialisieren
26
  TCCR1B |= (0x01 << WGM12);     // Timer Modus CTC
27
  TCCR1B |= (0x01 << CS10);      // ohne prescaler
28
  TCNT1 = 0;                     // Timer Counter mit 0 initialisieren
29
  OCR1A = 1666;                  // Output Compare Register vorbelegen
30
      
31
  //Pinchange interrupt auf Pin D2 scharf schalten
32
  PCMSK2 |= (0x01<<PCINT18);
33
  PCICR |= (0x01<<PCIE2);
34
   
35
  interrupts();               // alle Interrupts scharf schalten
36
  
37
}
38
39
//Interrupthandler für Pinchange an D2
40
//wenn eine Pegeländerung an Pin D2 passiert, werfe interrupt
41
ISR (PCINT2_vect){
42
  // wenn Messungszustand 0 und signal an D2 0 Messung starten
43
  if(messung == 0x00 && digitalRead(kLinePin)==0 ){
44
    messung = 0x01;
45
    TIMSK1 |= (1 << OCIE1A);    // starte den timer, alle ~104µs (1667 takte) pin d2 zu messen
46
  }
47
}
48
49
//Interrupthandler für Abtastraster
50
ISR(TIMER1_COMPA_vect) {
51
  byte val = digitalRead(kLinePin)==0 ? 0x00 : 0x01; // miss signal an D2, wandel in byte um
52
    
53
  //debug
54
  digitalRead(3)==1 ? digitalWrite(3,0) : digitalWrite(3,1); // gebe an D3 alternierend 1 oder 0 aus 
55
    
56
  erzeugeByte(val); // sende den gemessenen wert an die funktion
57
}
58
59
60
// befüllt das byte und gibt es an die console weiter
61
void erzeugeByte(byte _kLinePinState){
62
  if (counter<8){    
63
    kLineByte = kLineByte << 1 | _kLinePinState;    
64
    counter++;
65
    return;
66
  }
67
  
68
  Serial.print("Byte: ");
69
  Serial.println(kLineByte, BIN);
70
  digitalWrite(3,1);
71
  messung = 0x00;
72
  TIMSK1 &= ~(1 << OCIE1A);    // stoppe den timer
73
  kLineByte = 0x00;
74
  counter = 0;
75
}
76
77
// the loop routine runs over and over again forever:
78
void loop() {        // delay in between reads for stability
79
  }

von Peter D. (peda)


Lesenswert?

ShAG G. schrieb:
> TIMSK1 |= (1 << OCIE1A);    // starte den timer

Nö, damit wird der Interrupthandler erlaubt.
Start/stop erfolgt mit den CS1x-Bits im TCCR1B;

Beitrag #5147242 wurde vom Autor gelöscht.
von Shaggie S. (shaggie)


Lesenswert?

Peter D. schrieb:
> ShAG G. schrieb:
>> TIMSK1 |= (1 << OCIE1A);    // starte den timer
>
> Nö, damit wird der Interrupthandler erlaubt.
> Start/stop erfolgt mit den CS1x-Bits im TCCR1B;

DANKE!!!!!

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.