Morgen,
hab ein Problem mit dem IPC, funktioniert einfach nicht.
Erst mal eine allgemeine Frage, kann man den IPC pin mit einer zu hohen
frequenz zerstören (~200kHz)? habe im db leider nichts gefunden.
mein erster versuch lief ganz gut, also funktioniert hat es schon mal
(if periode > 20, lass led blinken).
code sieht wie folgt aus:
DDR und Port init:
1
voidinit(void)
2
{
3
4
// 7-bit port D 654.3210
5
DDRD=0x7F;// 111.1111 -> all pins from port D as output.
6
PORTD=0x00;// 000.0000 -> push pull output LOW
7
8
// Config IPC Pin as Input
9
DDRD&=~(1<<PD6);// Input Capture Pin
10
11
// 8-bit port B 7654.3210
12
DDRB=0x80;// 1000.0000 -> all Pins from port B (except 7) as input
13
PORTB=0x60;// 0110.0000 -> Pin 7 push pull out low, pin 5,6 input with pull
14
// up, pin 0,1,2,3,4 input without pull up.
15
}
Init Timer 1 (16bit)
1
// Timer 1, 16bit, prescaler 8, cycle time 65,536ms
2
voidinit_timer1(void)
3
{
4
TCCR1A=0x00;
5
TCCR1B|=(1<<ICNC1)|(1<<ICES1)|(1<<CS11);// IC pos edge, Prescaler 8
Micha S. schrieb:> hab ein Problem mit dem IPC, funktioniert einfach nicht.> Erst mal eine allgemeine Frage, kann man den IPC pin mit einer zu hohen> frequenz zerstören (~200kHz)? habe im db leider nichts gefunden.
Frequenz weiss ich nicht, Zerstörung kommt auf die Schaltung an. Bei dem
folgenden problematischen Code schaltest du PD6 erstmal kurz auf Ausgang
und LOW bevor du PD6 auf Eingang und hochohmig (ohne Pullup) schaltest.
Das kann je nach angeschlossener HW (Versorgung mit niedrigem
Serienwiderstand oder starker Ausgang HIGH > max. Strom eines IO-Ports)
tödlich für den PD6 sein.
// 7-bit port D 654.3210
DDRD = 0x7F; // 111.1111 -> all pins from port D as
output.
PORTD = 0x00; // 000.0000 -> push pull output LOW
// Config IPC Pin as Input
DDRD &= ~(1 << PD6); // Input Capture Pin
Ich würde an PD6 zunächst eine Funktionskontrolle mit Beispielprogrammen
aus der Codekiste machen z.B. mit einem Blinkprogramm für eine LED um
die Funktion Ausgang zu prüfen und mit einem Tasterprogramm um die
Funktion Eingang zu prüfen.
danke erst mal für die schnelle antwort!
Daran denke ich auch gerade, sollte erst einmal den pin testen. hatte
gestern einen interessanten effekt (warum auch immer), der gesamte port
streikte nach einer recht hohen frequenz >200kHz. könnte sein er ist
zerstört.
die signaltreiber schaltung liefert ~0 oder 4,3V (Vcc = 5V), reicht also
für die flanken.
so,schon geändet :)
1
// 7-bit port D 654.3210
2
DDRD=0x3F;// 011.1111 -> all pins from port D as output, pin 6 as input (IPC).
Tu das :-)
Und lass das cli()/sei() und die Zeile "TIFR |= (1 << ICF1);"in der ISR
weg. Die haben dort nichts zu suchen. Die ISR bzw. der
Interruptmechanismus des AVR kümmern sich um diese Punkte. Das Problem
bei hohen Frequenzen hängt IMHO damit zusammen: Der Problemcode erlaubt
zu früh, d.h. vor Verlassen der ISR, einen neuen Aufruf der ISR. Damit
läuft mehr oder minder schnell der Stack über und der AVR in einen
Resetzustand.
Das die ISR beim Ausfhren ihr flag löscht ist klar (fand es optisch
schöner :)) aber die routinen wusste ich nicht das die abgeschaltet
werden. wenn jetzt ein ISR mit höherer prio kommt wird er dann nicht
unterbrochen? ist ne verständnisfrage, im moment ist der capt mein
höchster interner.
oh frage erübrigt sich, höher sind nur die externen und reset (tiny2313)
hoffe es geht so, nächste alternative ist der nächste controller
(gestern hats ja auch funktioniert...:)
Schädlich ist vor allem das sei() vor dem Return der ISR. Zwischen sei()
und Return kann bei gelöschtem Flag der nächste Interrupt zuschlagen und
die geretteten Daten der aktuell laufenden und jetzt unterbrochenen ISR
hängen unaufgeräumt auf dem Stack rum. Das sind jede Menge Register des
Anwendungsprogramms...! Und beim nächsten Interrupt in 5 µs (200 kHz)
werden die nächsten Daten auf dem Stack gepackt und nicht mehr
runtergeladen...
Ok hab ich rausgeschmissen, klar einen stack overflow wäre das letzte wo
ich jetzt brauch!
habe den controller gewechselt aber es geht immer noch nict :(
Micha S. schrieb:> der rest funktioniert einwandfrei, werde es dir per mail schicken.
SChicks nicht per Mail. Da schau ich mir das nicht an.
Poste es hier rein als Attachment.
Der Rest ist auch nicht unbedingt uninteressant. zb Gibst du den
Overflow Interrupt ebenfalls frei. Aber: Hast du einen Handler dafür?
Wie genau sind die Variablen definiert?
All das kann ich im kompletten Porgramm leicht nachsehen. Postest du
aber nur Ausschnitte muss immer lästgi nachgefragt werden. Daher:
Kompletter Code ist meistens die bessere Wahl. Da sehen wir dann was
Sache ist und mussen weder nachfragen noch uns fehlende Details
erfinden.
ja das stimmt. ist eine projektarbeit für die schule, wenn mein prof das
programm online sucht und was findet gibt das einen anschiss oder
schlimmer weil er denkt es sei geklaut, ebensowenig erlaubt er
fremdhilfe.
also vars sind als volatile definiert, ovr isr ja, code hier:
1
// ISR Vars
2
volatileui8t0_counter8=0u;//unsigned char
3
volatileui8t1_counter8=0u;
4
volatileui16t1_ipc_new=0u;// u short
5
volatileui16t1_ipc_old=0u;
6
volatileui8t1_cnt_old=0u;
7
volatileui32period_time=0u;//u.long
8
9
10
ISR(TIMER1_OVF_vect)
11
{
12
// TIFR |= (1 << TOV1); // reset Overflow Flag
13
if(bit_is_set(global_flag,t1_counter8_overflow))
14
{
15
t1_counter8=0u;// set counter to zero
16
clrbit(global_flag,t1_counter8_overflow)// reset overflow flag
Zumindest der alte AVR Simulator ist bei der Reihenfolge in der
Interrupts ausgeführt werden nicht ganz korrekt (Ausführung nach dem
Auftreten des Interrupt signals). Die Hardware kümmert sich aber nicht
darum welches Interruptflag zu erst gesetzt wurde, sondern geht nur
danach welche Bits gesetzt sind.
Daduch kann es passieren das ICP Interrupts schon vor dem Overflow
Interrupt ausgeführt wird, obwohl er eigentlich erst später dran ist.
Die Interrupt Flags werden schon von der Hardware zurückgesetzt.
Sonst gibt halt: Selber denken muss man auch mal üben.
ulrich schrieb:> Sonst gibt halt: Selber denken muss man auch mal üben.
Ja da bin ich grad dran, was mich irritiert ist das der erste versuch
funktioiert hat. egal, habe es jetzt etwas anders gemacht aber vom
prinzip ist es das gleiche. timer 0 läuft als zeitstempel (32,768ms) und
timer 2 als flankenzähler, somit ist grob gesagt:
zeitstempel / anzahl flanken = periodenzeit
trotzdem danke an euch alle ;)