Hallo,
nachdem mir die Suchfunktion nicht mehr weiterhelfen kann und auch meine
Bekannten mir nicht mehr helfen konnten wende ich mich mit meinem
Problem ans Forum.
Ich habe die Aufgabe 2 4-schrittige Quadraturencoder auszulesen und
diese Daten an den Rechner zu schicken, damit eine Weiterverarbeitung in
Labview folgen kann. Das Programm zum Auslesen basiert auf dem
Beispielcode von Peter Dannegger. Zur Kommunikation mittels Uart
verwende ich fertige Dateien und Initialisierungsbefehle von Peter
Fleury.
Ich verwende einen ATMega 168 Crumb Modul. Dieses Modul trägt den
ATMega168 einen UART zu USB Wandler und ein Quarz das, auf 20 MHz
taktet.
Die Versuche Strings per UART in der Mainmethode zu senden waren
erfolgreich und konnten mit Putty angezeigt werden.
Es sollte ein Programm folgen, dass über Interrupts die Encoder
ausliest, und die Werte sendet.
Ich möchte Timer 0 verwenden um die Encoder auszulesen und Timer 2 um
die akkumulierten Werte auszugeben.
Um eine Beschädigung der Encoder vollständig auszuschließen. Wird das
Programm getestet, ohne dass sie angeschlossen sind. Es müsste die
durchgehende Ausgabe des Wertes 0 für jeden Encoder folgen.
Leider funktioniert nichts. Putty detektiert keine Datenausgabe des
Mikrocontrollers. Die Kompilierung des C-Programms erzeugt 0 Warnungen.
Wo liegt der logische Fehler in diesem Programm?
gruß Christoph
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<stdlib.h>
4
#include"uart.h"
5
6
7
#ifndef F_CPU
8
9
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 20000000"
10
#define F_CPU 20000000UL // Systemtakt in Hz - Definition als unsigned long beachten
11
// Ohne ergeben sich unten Fehler in der Berechnung
12
#endif
13
14
#define UART_BAUD_RATE 9600
15
//Target Atmega 168
16
17
18
19
#define PHASE_A1 (PINC & 1<<PINC0)
20
#define PHASE_B1 (PINC & 1<<PINC1)
21
#define PHASE_A2 (PINC & 1<<PINC2)
22
#define PHASE_B2 (PINC & 1<<PINC3)
23
24
25
26
int8_tenc_delta1;//-128 ... 127
27
int8_tenc_delta2;
28
int8_tWert1=0;
29
int8_tWert2=0;
30
charout1[4];
31
charout2[4];
32
33
voidencode_init(void)
34
{
35
TCCR2B=(1<<WGM22)|(1<<CS22)|(1<<CS21)|(1<<CS20);
36
OCR2B=10;
37
TCCR0B=(1<<WGM01)|(1<<CS02)|(1<<CS00);
38
OCR0B=1;
39
TIMSK2=1<<OCIE2B;
40
TIMSK0=1<<OCIE0B;
41
//beide Zähler initialisieren
42
}
43
44
45
ISR(TIMER2_COMPB_vect)//Abtastzeit
46
{
47
staticint8_tlast1;
48
staticint8_tlast2;
49
int8_tnew1,diff1;
50
int8_tnew2,diff2;
51
new1=0;
52
if(PHASE_A1)
53
new1=3;
54
if(PHASE_B1)
55
new1^=1;//convert grey to binary
56
diff1=last1-new1;//difference last - new
57
if(diff1&1){//bit 0 = value (1)
58
last1=new1;//store new as next last
59
enc_delta1+=(diff1&2)-1;//bit 1 = direction(+/-)
60
}
61
62
new2=0;
63
if(PHASE_A2)
64
new2=3;
65
if(PHASE_B2)
66
new2^=1;//convert grey to binary
67
diff2=last2-new2;//difference last - new
68
if(diff2&1){//bit 0 = value (1)
69
last2=new2;//store new as next last
70
enc_delta2+=(diff2&2)-1;//bit 1 = direction(+/-)
71
}
72
73
}
74
75
ISR(TIMER0_COMPB_vect){//Interrupt, der per UART daten an den PC sendet
ISR(TIMER0_COMPB_vect){//Interrupt, der per UART daten an den PC sendet
2
cli();
3
itoa(Wert1,out1,10);
4
itoa(Wert2,out2,10);
5
uart_puts(out1);
6
uart_puts("\r\n");
7
uart_puts(out2);
8
uart_puts("\r\n");
9
Wert1=0;
10
Wert2=0;
11
sei();
12
}
Grusel.
Raus mit dem ganzen Zeug aus dem Interrupts. Dann klappts auch mit dem
Encoder. Merke: In Interrupts kommt nur das allernotwendigste.
Verarbeitung in main.
>Interrupt, der per UART daten an den PC sendet
Spätestens, wenn ich das 'U' in dem Kommentar tippen würde, würde ich
wahrscheinlich so ein unkontrollierbares Zittern kriegen.
Schliesse mich meinem Vorredner an bezüglich UART...
Lass die sei() cli() Orgie in den ISR weg. cli macht ohnehin keinen Sinn
in der ISR, da beim IRQ das I-Flag ohnehin gelöscht ist (keine "nested
interrupts" per Default).
Bist sicher, dass uart_* bei gesperrten Interrupts funktioniert?
Hi
Wenn ich mich nicht verrechnet habe, schlägt dein Timerinterrupt
(TIMER0_COMPB_vect) alle 102,4 µs zu. Die Übertragung eines Zeichens bei
9600 Baud dauert 1,04mS. Das sollte dir zu denken geben. Ansonsten
schließe ich mich Grrrr an.
MfG Spess
spess53 schrieb:
> schlägt dein Timerinterrupt> (TIMER0_COMPB_vect) alle 102,4 µs
Na dann sollte Christoph mal seine Strategie neu überdenken. Alle 102,4
µs was tun, was mindestens 1,04ms dauert? Da hilft auch auslagern in
main nichts. Ist aber auf jeden Fall der bessere Weg.
Eine eigene Frage?
Dieser Thread ist über 16 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.