Hey leute.
Ich habe folgendes Problem.
Ich will ein Signal auswerten, das wie folgt aufgebaut ist.
Ein Bit ist jeweils 4ms lang.
Die Information ist 12 Bits lang.
Zwischen den Bits ist immer eine Pause von mehr als 14*4ms.
Ich lese das Signal mit einem Optokoppler später ein, von daher sind die
Signale in meinem Code verdreht. Das heißt, ein High Pegel kommt als Low
Pegel am µC an.
Ich bin so vorgegangen:
Verwendet habe ich einen Atmega8535
Ich habe den Timer 1 in den CTC Modus versetzt (ich denke mal nicht
richtig, ich komm mit dem Datenblatt nicht zurecht...)
Prescaler auf 8 und er soll bei 124 einen Interupt machen.
Dort sehe ich dann nach, wenn 14 bits nacheinenader auf High sind (am µC
also Low), dann wurde die Pause erkannt. Fällt nun der Wert auf Low,
dann kanns losgehen mim einscannen.
So schreibt er mir alle 4ms einen bit.
Das Problem ist, das der Timer sich wohl nur ein einziges mal aufruft.
Wo könnte das Problem liegen?
Hier ist mal der Code
1
#include<stdlib.h>
2
#include<avr/pgmspace.h>
3
#include<lcd.h>
4
#include<avr/io.h>
5
#include<util/delay.h>
6
#include<stdint.h>
7
#include<avr/interrupt.h>
8
9
//Wählt wie oft auf high ohne unterbrechung
10
uint8_tcount=0;
11
//Steht auf 1, wenn mehr als 14 mal auf high (also 14*4ms vergangen sind, also eine Pause)
12
uint8_twatch=0;
13
//das ist mein wert der verändert wird und ausgelesen werden soll, 12bit lang
14
uint16_twert=0b000000000000;
15
//bit muss ich rückwärts reinschreiben, das ist die position
16
uint8_tbit=12;
17
uint8_tlcd=0;
18
uint16_twertbuffer;
19
20
///ACHTUNG ACHTUNG ACHTUNG ACHTUNG ACHTUNG
21
///Pin auf Low heißt 1 und Pin auf High heißt 0 !!!!
22
///ACHTUNG ACHTUNG ACHTUNG ACHTUNG ACHTUNG
23
24
ISR(TIMER1_COMPA_vect)
25
{
26
//Wenn der counter unter 8 sein sollte, und ein low signal auftritt
27
//Wird der counter auf 0 zurück gesetzt, weil da noch irgendwo ein
28
//Signal ist, also keine pause
29
if((count<15)&&(PIND&(1<<PIND0))){count=0;}
30
31
//Wenn ein high signal da ist dann zählt der count eins hoch
32
if(!(PIND&(1<<PIND0))){count++;}
33
34
//Wenn der counter jetz größer ist als 7, war wohl ne pause.
35
//Wenn zusätzlich noch ne flanke kommt, dann fängt das signal an
36
//Das heißt watch ist auf 1, damit er unten bit schreibt
37
if((count>14)&&(PIND&(1<<PIND0))){watch=1;}
38
39
//Wenn watch auf high, ließt er den wert ein
40
if(watch==1){
41
lcd=0;
42
43
//Wenn ein High kommt, dann soll er ne 1 schreiben an der stelle des Bits
44
if(!(PIND&(1<<PIND0))){
45
wert|=(1<<bit);
46
}
47
}
48
//Springt jedesmal eine Bitposition zurück
49
bit--;
50
51
//Wenn das 0te Bit geschrieben ist, wird bit auf 12 zurückkgesetzt
52
//watch auf 0, damit keine werte geschrieben werden
53
//Wertbuffer übernimmt den wert, damit er immer aktuell abrufbar ist
54
//wert wird auf 0 zurückgesetzt damit man ihn neu mit bits befüllen kann
Mike schrieb:
> TCCR1B = (1<<CS11) | (1<<WGM13) | (1<<WGM12) ;
du initialisiert als Vergleichsregistert ICR1, demnach vermute ich, dass
bei dir im moment kein Compare Match auftritt
versuche es mal so
1
TCCR1B=(1<<CS11)|(1<<WGM12);
so wird OCR1A initialisiert
Prescaler 8 ist so korrekt
Mir fällt grad auf dass das vieleicht nicht das einzige Problem ist.
Ich hab vergessen dass es einen Overflow geben wird, wenn das Signal zu
lange auf high ist. Das muss ich vorher zurücksetzen.
Und zweitens muss ich nachdem watch auf 1 steht, den Timer
zurücksetzten, so das er von neuem anfängt zu zählen. Wie mache ich das?
Mit OCR1A = 124; setze ich ja fest wann der Overflow passiert, aber
womit setze ich den Zähler auf 0 zurück?
Mit der genannten Einstellung läuft der Timer im CTC Modus (Clear on
Compare Match).
Tritt ein Compare Match auf, wird der Timer zurücksetzet auf 0 (das
Timer Zählregister TCNT1). Er zählt wieder von 0 bis eben zum Compare
Match (OCR1A). Und das solange du ihm einen Takt vorgibst (Prescaler
!=0).
Einen TimerOverflow gibt es nicht, da du kein Overflow Interrupt hast
(der Timer OVF wurde nicht initialisiert und es gibt in deinem Programm
auch keine ISR).
Wie meinst du es gibt keinen ISR??
Kann es vllt sein das meine Lösung (wenn sie mal funktionieren sollte)
zu kompliziert ist?
Ich will dass er eine Pause von mehr als 14*4ms erkennt. Und dann wenn
ne Flanke kommt, soll er alle 4ms dann immer ein bit einlesen, und das
12 mal.
Gruß
Ich hab mal eben nur mal im Timer zählen lassen, aber der zählt ein
einziges mal und danach nicht mehr.
Hab ne andere Einstellung versucht, geht aber nicht.
....
TCCR0 geht bei mir, hat aber kein CTC :/
Jetz hab ichs mal so probiert, der Timer läuft.
Hab mal größere Werte genommen damit der Timmer ned so schnell läuft.
Das Problem ist, er schreibt mir keine Bits rein...
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<avr/signal.h>
4
#include<stdint.h>
5
#include<lcd.h>
6
#include<stdlib.h>
7
8
9
//Count zählt wie oft ein High wert ohne unterbrechung da war
10
//Watch auf 1 bedeutet, er kann bits schreiben
11
//i ist meine Bitposition (muss rückwärts schreiben)
12
uint8_tcount=0,watch=0,i=12;
13
//Wert wird beschrieben, und wertb speichert das am ende zwischen
14
uint16_twert=0x00,wertb=0x00;
15
//Hat nur belang für die LCD ausgabe
16
uint8_tdisplay=0;
17
//Setzt in der main nach ner Pause, wenn eine flanke auftaucht den Timer zurück um
18
//sich mit dem signal zu syncronisieren
19
uint8_treset=1;
20
21
22
23
SIGNAL(SIG_OVERFLOW0)
24
{
25
display++;
26
if(display==11){display=0;}
27
28
//Verhindert overflow
29
if(count>15){count=15;}
30
//Wenn eine flanke auftritt, wird count auf 0 zurückgesetzt
31
if((PIND&(1<<PIND0))&&(watch==0)){count=0;}
32
//Solang auf low, wird count hochgezählt
33
if((!(PIND&(1<<PIND0)))&&(watch==0)){count++;}
34
//Ist der wert 14 erreicht, wird watch auf 1 gestellt.
35
if(count>14){watch=1;}
36
//Kommt jetz ne flanke mit watch auf 1, geht das zählen los
37
if((watch==1)&&(PIND&(1<<PIND0))){
38
//Wenn auf low, soll er mir ne 1 reinschreiben
39
if(!(PIND&(1<<PIND0))){
40
wert|=(1<<i);}
41
//geht immer eine bitposition zurück
42
i--;
43
//Soll alle werte zurücksetzten, und den wert zwischenspeichern
Aktuell fehlen da ein paar "volatile". Das Ganze kann aber auch ganz
grundsätzlich so nicht funktionieren. Wenn du mit einem festen Raster
abtastest, und dieses Raster nicht irgendwo auf das Eingangssignal
synchronisiert wird, dann werden die Abtastpunkte auch mal im Bereich
der Flanken liegen. Du musst bei jedem Datum das Raster neu auf die
erste Flanke ausrichten, damit die Abtastpunkte ungefähr in der Mitte
des Bits liegt.
Stefan Ernst schrieb:
> Aktuell fehlen da ein paar "volatile". Das Ganze kann aber auch ganz> grundsätzlich so nicht funktionieren. Wenn du mit einem festen Raster> abtastest, und dieses Raster nicht irgendwo auf das Eingangssignal> synchronisiert wird, dann werden die Abtastpunkte auch mal im Bereich> der Flanken liegen. Du musst bei jedem Datum das Raster neu auf die> erste Flanke ausrichten, damit die Abtastpunkte ungefähr in der Mitte> des Bits liegt.
Ich hab einen kleinen Fehler im Code schon gefunden.
Aber wie richte ich das Signal den aus?
Ich muss ne Flanke erkennen, klar, aber das muss ja in der Main
passieren, sonst kann ich das nicht anpassen.
Mir rauch langsam der Kopf, gibt es da nicht ne feste Vorgehensweiße um
solche Signale einzulesen??
Danke
Ok ich habs hinbekommen mit dem Timer 2
Das Problem ist nur, ich weiß nicht wie ich den Timer dazubringe, das er
bei einer Flanke sich selbst zurücksetzt.
Ziemlich am Ende vom Code, da wo die vielen Fragezeichen sind:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<avr/signal.h>
4
#include<stdint.h>
5
#include<lcd.h>
6
#include<stdlib.h>
7
8
uint8_tflanke;
9
//Count zählt wie oft ein High wert ohne unterbrechung da war
10
//Watch auf 1 bedeutet, er kann bits schreiben
11
//i ist meine Bitposition (muss rückwärts schreiben)
12
uint8_tcount=0,watch=0,i=12;
13
//Wert wird beschrieben, und wertb speichert das am ende zwischen
14
uint16_twert=0x00,wertb=0x00;
15
//Hat nur belang für die LCD ausgabe
16
uint8_tdisplay=0;
17
18
19
20
21
SIGNAL(SIG_OUTPUT_COMPARE2)
22
{
23
flanke=PIND;
24
display++;
25
if(display==50){display=0;}
26
27
//Verhindert overflow
28
if(count>15){count=15;}
29
//Wenn eine flanke auftritt, wird count auf 0 zurückgesetzt
30
if((PIND&(1<<PIND0))&&(count<15)){count=0;}
31
//Solang auf low, wird count hochgezählt
32
if((!(PIND&(1<<PIND0)))&&(watch==0)){count++;}
33
//Ist der wert 14 erreicht, wird watch auf 1 gestellt.
34
35
36
if((count>14)&&(PIND&(1<<PIND0))){watch=1;}
37
38
39
if(watch==1){
40
41
42
//Wenn auf low, soll er mir ne 1 reinschreiben
43
if(!(PIND&(1<<PIND0))){
44
wert|=(1<<i);
45
}
46
//geht immer eine bitposition zurück
47
i--;
48
//Soll alle werte zurücksetzten, und den wert zwischenspeichern
49
if(i==0){
50
i=12;
51
watch=0;
52
if(wert!=0){
53
wertb=wert;}
54
wert=0x00;
55
count=0;
56
}
57
58
59
}
60
61
62
}
63
64
65
66
67
intmain(void)
68
{
69
DDRD=0x00;
70
PIND=0xff;
71
TCCR2=(1<<CS20)|(1<<CS22)|(1<<WGM21);
72
OCR2=250;
73
TIMSK|=(1<<OCIE2);
74
75
76
charbuffer[7];
77
78
79
lcd_init(LCD_DISP_ON);
80
lcd_clrscr();
81
while(1){
82
83
// HIER Soll der Timer2 bei 0 wieder anfangen zu Zählen