PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Funktion wird nicht richtig beendet



kowolfgang
28.09.2007, 16:38
Hallo,

ich soll für einen guten bekannten eine Geschwindigkeitsanzeige entwickeln die ihm die Geschwindigkeit seiner Modelle auf einer 4stelligen Dot-Matrix Anzeige in Wirklichkeit anzeigt. Ich hatte schoneinmal ein Programm dafür in Bascom angefangen, allerdings geht mir Bascom inzwischen ziemlich auf die Nerven weil der Compiler ein paar ziemliche Bugs bei den neueren Tinys hat, die einen immer ewig nach den Ursachen für die Fehler suchen lassen. Dies hier ist also mein erstes wirkliches Projekt in C deswegen bin ich in dieser Sprache noch nicht so bewandert. Als Display hab ich mir das SLR2016 vom Conrad ausgesucht weil es sich mit relativ wenigen Leitungen ansteuern lässt und weil es schön klein ist, zudem leuchten die Zahlen ordentlich hell.

Gesteuert wird das ganze mit einem ATtiny44, die Anzeige hat auch schon funktioniert (allerdings mit einem Programm das ich früher in Bascom geschrieben hab).

Das Problem in meinem Programm ist jetzt aber das das Programm nach beendigung meiner selbstgestrickten Wait Funktion nicht mehr ins Hauptprogramm sondern in die Interrupt Routine vom Timer0 springt (wird für die Waitfunktion verwendet).Hier Poste ich mal den Code damit ihr seht was das Programm die ganze Zeit so treibt




#include <avr/io.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#ifndef F_CPU
#define F_CPU 8000000UL /* Interner Oszillator mit 8Mhz */
#endif

/* Variablen definieren */

uint8_t Statusbyte = 0; /* Statusbyte für verschiedene Operationen */
volatile uint16_t Waittime = 0; /* Countvariable für Waitfunktion */
volatile uint16_t Waitcount = 0; /* Countvariable für Waitfunktion */

/* Variablen für Geschwindigkeitsmessung */

volatile uint8_t overflowcount = 0; /* Zähler für Timer Overflows */
uint16_t timer1counts = 0; /*Zählerstand von Timer1 */
float zeit = 0.0; /* Gemessene Timer1 Zeit */
float ov_summ_zeit = 0.0;
float v_float = 0.0; /* Geschwindigkeit mit Kommastelle*/
uint16_t V = 0; /* Geschwindigkeit ohne Kommastelle */

/* Variablen für Displayanzeige */

char Display[5];

/* Konstanten */

const float H0_10cm = 31.32;
const float N_10cm = 115.2;
const float overflowzeit = 2.097152;
const uint16_t cps = 31250;
const uint8_t disp_char0 = 0x00;
const uint8_t disp_char1 = 0x10;
const uint8_t disp_char2 = 0x20;
const uint8_t disp_char3 = 0x30;

/* Konstanten für Displaychars */
const uint8_t wertetabelle[] PROGMEM = {0x00 , 0x08 , 0x04 , 0x0C , 0x02 , 0x0A , 0x06 , 0x0E , 0x01 , 0x09 , 0x05 , 0x0D , 0x03 , 0x0B , 0x07 , 0x0F };



/* ++++++++++++++++++++++++++++++++++++INTERRUPTS++++ ++++++++++++++++++++++++++*/

ISR(TIM0_OVF_vect)
{ Waitcount ++;
}

ISR(TIM1_OVF_vect)
{ overflowcount ++;
}


/* Prototypen */

void init_io();
void timer_init();
void wait(uint16_t zeit, uint8_t faktor);


/* ++++++++++++++++++++++++++++++++++++FUNKTIONEN++++ ++++++++++++++++++++++++++*/
/* IOs initialisieren */
void init_io()
{
DDRA |= 0xff;
PORTA |= 0xC0;

DDRB |= 0x0C;
PORTB |= 0x07;

#define disp_blank PA7
#define disp_write PA6
#define disp_clear PB2

return;
}

/* Timer initialisieren und Interrupts einrichten*/

void timer_init() /* Timer1 wird initialisiert aber nicht gestartet */
{
/* Timer0 */
TCCR0A = 0;
TCCR0B = 0;
TIMSK0 = (1<<TOIE0);

/* Timer1 */
/*TCNT1L = 0;
TCNT1H = 0;*/
TCNT1 = 0;
TCCR1A = 0;
TCCR1B = 0;
TIMSK1 = (1<<TOIE1);

return;
}

/*+++++++++++++++++++++++++++++++++++++WARTEFUNKTIO N+++++++++++++++++++++++++++*/

void wait(uint16_t zeit, uint8_t faktor)
{
const float CPMS = 31.25; /* Counts pro Milisekunde */
Waitcount = 0;
Waittime = (zeit * faktor)*CPMS;
TCNT0 = 0;
sei();
TCCR0B = (1 <<CS00);
while (Waitcount < Waittime)
{
};


TCCR0B |= (1<< CS00);
cli();
return; /* <<<<<<<Da Hängt er sich auf */
}


/*+++++++++++++++++++++++++++++++++++++HAUPTPROGRAM M+++++++++++++++++++++++++++*/
int main(void)
{
init_io();
timer_init();
wait(1, 1);
V = messung();
Anzeige(15,2);

return 0;
}



ich hoffe ihr könnt mir helfen damit mein erstes C Programm nicht gleich ein Desaster wird


Gruß und Dank im Vorraus


Wolfgang

izaseba
28.09.2007, 17:03
Eine sehr komische "Wartefunktion"
Das hier hat keinen Sinn


TCCR0B |= (1<< CS00);
Wenn Du den Timer stoppen willst muß es so heißen


TCCR0B &= ~(1<< CS00);
und vielleicht noch den Interruptflag in TIFR löschen

Gruß Sebastian

kowolfgang
28.09.2007, 18:52
Hallo izaseba,

danke für deine Korrektur, das mit den Zuweisungen hab ich noch nicht so drauf, scheinbar funktionierts jetzt der Simulator vom AVR Studio springt aus der Funktion wieder einwandfrei raus =P~ .

Die Waitfunktion ist eigentlich reine Timerverschwendung, da er aber (bis jetzt!!) noch nicht gebraucht wird hab ich mir damit eine eigene Wait Funktion gestrickt weil ich bei den Funktionen von der AVR Libc noch nicht so ganz durchsteige und irgendwie noch nicht so ganz kapiert hab wie man andere Libs in AVR Studio einbindet.

P.S.: jetzt hängt der Simulator schon wieder allerdings im Interrupt vom Timer1

izaseba
28.09.2007, 20:03
Hallo Wolfgang,
Es kann ja sein, daß ich mich vergucke, aber was macht das Programm im Interrupt von Timer1, wenn der Timer1 garnicht läuft :-k
Oder hast Du das Programm von oben irgendwie abgeändert ?
Klar ist Deine Wartefunktion Timerverschwendung, sie tut aber Ihren Dienst ;-)
Das ist immernoch besser, als eine delay Funktion, wozu brauchst Du überhaupt diese wait Funktion ?
Vielleicht kann ich Die einen Tip geben, wie das eleganter zu lösen ist...

Gruß Sebastian

kowolfgang
28.09.2007, 22:42
Hallo Sebastian,

die Funktion wird nur gebraucht um die gemessenen Werte dann eine gewisse Zeit lang anzuzeigen und Delay Zeiten bei der Display initialisierung zu realisieren. Warum das Programm dann nach Beendigung der Funktion ausgerechnet in den Timer1 Interrupt springt obwohl sogar davor noch alle Interrupts deaktiviert werden versteh ich auch nicht, das werde ich dann halt irgendwie umschiffen müssen, die Frage ist nur wie? Ein sichern vom SREG hat keine änderung erbracht (warum auch)8-[ .


Gute Nacht


Wolfgang

Hubert.G
29.09.2007, 09:35
Wo springt das return0 am Ende von main hin?

locked
29.09.2007, 10:00
Hallo,

wieso schreibst du bei einem Normalen "void" Unterprogramm, welches überhaupt keinen Rückgabeparameter hat, am Ende "return"?

Mfg

izaseba
29.09.2007, 10:28
Hallo
HubertG hat natürlich recht,
irgendwie fehlt bei Dir die Endlosschleife ( bin ich ein Blindfisch ](*,) )

Gruß Sebastian

kowolfgang
29.09.2007, 13:26
Hallo,

danke für die Tipps gebracht hats bis jetzt leider nichts. Das mit den Return Anweisungen wusste ich nich, das man die bei void funktionen nicht braucht, jetzt weis ichs. Das main keine Endlosschleife ist war auch mein Fehler (liegt warscheinlich an den alten Bascom gewohnheiten) jetzt hab ich mir ne Endlosschleife mit do-while gebastelt, hoffentlich funktioniert das.

Leider springt das Programm immer noch in die Interruptfunktion vom Timer1 trotz eindeutig abgeschalteter Interrupts, hier nochmal der jetzige Code:


#include <avr/io.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#ifndef F_CPU
#define F_CPU 8000000UL /* Interner Oszillator mit 8Mhz */
#endif


/* Variablen definieren */

uint8_t Statusbyte = 0; /* Statusbyte für verschiedene Operationen */
volatile uint16_t Waittime = 0; /* Countvariable für Waitfunktion */
volatile uint16_t Waitcount = 0; /* Countvariable für Waitfunktion */

/* Variablen für Geschwindigkeitsmessung */

volatile uint8_t overflowcount = 0; /* Zähler für Timer Overflows */
uint16_t timer1counts = 0; /*Zählerstand von Timer1 */
float zeit = 0.0; /* Gemessene Timer1 Zeit */
float ov_summ_zeit = 0.0;
float v_float = 0.0; /* Geschwindigkeit mit Kommastelle*/
uint16_t V = 0; /* Geschwindigkeit ohne Kommastelle */

/* Variablen für Displayanzeige */

char Display[5];


/* Konstanten */

const float H0_10cm = 31.32;
const float N_10cm = 115.2;
const float overflowzeit = 2.097152;
const uint16_t cps = 31250;
const uint8_t disp_char0 = 0x00;
const uint8_t disp_char1 = 0x10;
const uint8_t disp_char2 = 0x20;
const uint8_t disp_char3 = 0x30;

/* Konstanten für Displaychars */
const uint8_t wertetabelle[] PROGMEM = {0x00 , 0x08 , 0x04 , 0x0C , 0x02 , 0x0A , 0x06 , 0x0E , 0x01 , 0x09 , 0x05 , 0x0D , 0x03 , 0x0B , 0x07 , 0x0F };



/* ++++++++++++++++++++++++++++++++++++INTERRUPTS++++ ++++++++++++++++++++++++++*/

ISR(TIM0_OVF_vect)
{ Waitcount ++;
}

ISR(TIM1_OVF_vect)
{ overflowcount ++;
}


/* Prototypen */

void init_io();
void timer_init();
void wait(uint16_t zeit, uint8_t faktor);
uint16_t messung();
void Anzeige(uint8_t zeichen, uint8_t place);

/* ++++++++++++++++++++++++++++++++++++FUNKTIONEN++++ ++++++++++++++++++++++++++*/
/* IOs initialisieren */
void init_io()
{
DDRA |= 0xff;
PORTA |= 0xC0;

DDRB |= 0x0C;
PORTB |= 0x07;

#define disp_blank PA7
#define disp_write PA6
#define disp_clear PB2

}

/* Timer initialisieren und Interrupts einrichten*/

void timer_init() /* Timer1 wird initialisiert aber nicht gestartet */
{
/* Timer0 */
TCCR0A = 0;
TCCR0B = 0;
TIMSK0 |= (1<<TOIE0);


TCNT1 = 0;
TCCR1A = 0;
TCCR1B = 0;
TIMSK1 |= (1<<TOIE1);

}

/*+++++++++++++++++++++++++++++++++++++WARTEFUNKTIO N+++++++++++++++++++++++++++*/

void wait(uint16_t zeit, uint8_t faktor)
{
const float CPMS = 5; /*31.25; Counts pro Milisekunde */
uint8_t temp;
temp = SREG;
Waitcount = 0;
Waittime = (zeit * faktor)*CPMS;
TCNT0 = 0;
sei();
TCCR0B |= (1 <<CS00);
while (Waitcount < Waittime)
{
};

TCCR0B &=~ (1<< CS00);
cli();
SREG = temp;

}

/*+++++++++++++++++++++++++++++++++++++Messfunktion ++++++++++++++++++++++++++++*/

uint16_t messung()
{
/* MESSUNG */
while (PINB0 == 1){}
TCNT1 = 0;
TCCR1B |= (1<<CS12);
sei();

while (PINB1 == 1) {}
TCCR1B &=~ (1<<CS12);
cli();

timer1counts = TCNT1;

/*+++++++++++++++++RECHNUNG++++++++++++*/

zeit = timer1counts / cps;
ov_summ_zeit = overflowzeit * overflowcount;
zeit = zeit + ov_summ_zeit;
v_float = H0_10cm/zeit;
V = v_float;

/*itoa(V,Display,10);*/ /* Integer Wert in ASCII String umwandeln */
return(V);
}

/* ANZEIGE */

void Anzeige(uint8_t zeichen, uint8_t place)
{

/* ANZEIGE */
}

/*+++++++++++++++++++++++++++++++++++++HAUPTPROGRAM M+++++++++++++++++++++++++++*/
int main(void)
{
init_io();
timer_init();
wait(1, 1);
do
{
V = messung();
Anzeige(15,2);

}while(1);
}


Hier mal der ganze Code damit ihr seht was bis jetzt so geschrieben steht.


Danke für eure Hilfe und noch einen schönen Bastel-Samstag


Wolfgang

kowolfgang
30.09.2007, 16:18
Hallo ich bins wieder =P~ ,


hab heute nochmal alle möglichkeiten ausprobiert. Der Simulator hängt sich immer wieder an der selben stelle auf, immer wenn ich versuche entweder nur den Timer0 Overflow Interrupt oder alle Interrupts abzuschalten. Jetzt Frage ich mich warum, allerdings kann ich mir diese Frage mit meinen bis jetzt noch sehr bescheidenen C Kenntnissen nicht beantworten, wäre froh wenn ihr mir helfen könntet.


Schönen Sonntag noch

Gruß

Wolfgang

izaseba
30.09.2007, 16:57
Definiere hängt sich auf...
Ich kenne den Simulator nicht, aber wie verhält es sich auf der Hardware ?
und welche Optimierung hast Du gewählt ?

Gruß Sebastian

kowolfgang
30.09.2007, 17:54
Hallo Sebastian,

momentan kann ich die Software nur im Simulator vom AVR Studio testen weil mein ISP Adapter irgendwo nen Wackelkontakt hat.

Zum Thema hängt sich auf: die Funktion wird ordnungsgemäß abgearbeitet bis zu dem Punkt an dem die Interrupts deaktiviert werden, da kommt der PC ins stottern, der CPU Lüfter dreht hoch, es geht nichts mehr (für ca. 30 Sekunden), danach findet sich der Programmcursor in der Interruptroutine vom Timer1 wieder und er springt auch nicht mehr dort heraus.
Als Optimierung hab ich 0s gewählt


Gruß Wolfgang

izaseba
01.10.2007, 20:22
Ich würde mal sagen, AVRStudio spinnt, selbst wenn das Programm weiß was ich wie blöd geschrieben wäre, müßte es irgendwann aus der ISR rausgehen, schau erstmal, was auf der Hardware passiert.
Traue nie deinem Debugger, vor allem, wenn solche blöden Fehler auftreten.
Ich persönlich habe lange ein Bogen um AVRStudio gemacht, erst seitdem ich mir den Dragon geleistet habe, nutze ich es hin und wieder zum debugggen, da läuft es aber auf der realen Hardware ab und AVR Studio zeigt einfach nur an, was im µC abgeht...

Gruß Sebastian

kowolfgang
02.10.2007, 20:48
Hallo Sebastian,

ich werd das dann mal auf der Hardware versuchen, den Wackelkontakt hab ich gefunden, jetzt kanns weiter gehn. Hätte nicht gedacht das sogar ne Atmel Software Fehler hat (obwohl es Fehlerfreie Software nicht gibt), das selbe hab ich auch schon früher mit Bascom erlebt, jetzt hab ich wieder was gelernt O:) .

Ein AVR Dragon ist ja ein richtiges Luxus Debug Tool da kann ich nicht mithalten, auch wenn ich ihn mir schonmal kaufen wollte, er ist einfach noch zu umfangreich für das was ich ihn brauche.


Gute Nacht und schönen Feiertag


Wolfgang

roboterheld
02.10.2007, 21:20
....schönen Feiertag....


was heisst schöner feiertag? die solibelastung soll noch weitergehen für die ossi.

Oppi
31.12.2008, 15:23
Moin moin zusammen,

im Studium wurde ich kürzlichst mit der uC-Programmierung konfrontriert und habe glatt so viel gefallen daran gefunden, dass ich mir einen RP6 zugelegt habe.

In anhlehnung an mein Studium, wo ich den Infineon XC161 kennenlernte, möchte ich den RP6 nun von Grund auf neu programmieren.

Hier kurz die Rahmendaten:
- RP6 mit ATMEGA32L + RP6-Control mit ATMEGA32
- nutze AVR Studio 4
- und mitgelieferte GCC

Die ersten Schritte waren bisher mühsam aber gelangen. Wobei mir noch immer nicht so ganz klar ist, wie ich bei einem neuen Projekt für diese Prozessoren die Speichereinstellungen vornehmen muss?

Im weiteren habe ich bisher ein einfaches Init-Unterprogramm geschrieben, mit dem ich die auf dem RP6 vorhandenen LEDs initialisiere. Aus diesem Unterprogramm kommt der Programmablauf auch korrekt zurück.
Arbeite ich - wofür auch immer / hier z.B. um gezielt einzelne LEDs zu schalten - mit einem weiteren Unterprogramm, bleibt der Programmablauf sowohl in der Simulation, als auch in der Hardware am Ende des Unterprogramms stehen. Steppe ich durch die Simulation, schaltet der Simulator dann an der Stelle wo ich den Rücksprung in die Main erwarte auf Running.


Ein weiteres Problem, was ich gerne ansprechen möchte ist folgendes:
Wieso kann ich ausser in der MAIN keine lokalen Variablen anlegen? Hierbei kommt es dann bereits zu einem Fehler beim Übersetzen. Hängt das mit der womöglich noch nicht korrekt angelegten "Speicherverwaltung" in den Einstellungen des Projektes zusammen?


Schonmal vorab vielen Dank für die Hilfe und zum passenden Zeitpunkt einen guten Rutsch heute abend!

MfG,
Oppi

McJenso
31.12.2008, 16:37
Hallo,

erst einmal willkommen im Forum.

Mach doch bitte einen neuen Thread auf und zeige uns deinen bisherigen Code.
Ich kenne den RP6 nicht, denke aber, dass es C spezifisches Problem ist. Wenn du jedoch mit Funktionen einer mitgelieferten RP6-Bibliothek arbeitest, bist du im RP6 Forum besser aufgehoben.

Gruß

Jens