PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit while(1)



NewBot
16.03.2014, 13:01
Hi Leute,

endlich habe ich mal Zeit an meinem Robot zu bauen und zu programmieren.
Leider habe ich beim Programmieren das Problem, dass immer wieder aus der eigentlich unendlichen while(1)-Schleife rausgesprungen wird. Und ich finde keine Erkärung warum. Dadurch wird die controll_LED_green immer wieder abgeschaltet, was ja eigentlich theoretisch nicht passieren sollte.

Der Zweite Fehler ist, dass er immer wieder in die if (FWD_OnOff == false)-Abfrage reinspringt, obwohl der Wert auf true gesetzt werden müsste.
Hier erst mal der bisherige komplette Code:


#define F_CPU 16000000UL // ohne CKDIV8_Fuse = 16 MHz --> auf 16MHz eingestellt
#include <avr/io.h> // Standard Portfunktionen einbinden
#include <util/delay.h> //verzögerungs_lib einbinden
#include <avr/interrupt.h> // sei() setzt I-Bit, cli() löscht I-Bit, ISR()
#include "own_Port_define.h" //eigene Portdefinierung

bool FWD_OnOff;

void init_all (void)
{
//################ Ports #########
// Output Port B: Motor Enable, Left_Direction, Right_Direction,
DDRB |= (1<<motor_enable_DDR) | (1<<left_direction_DDR) | (1<<right_direction_DDR);
motor_Off; // High = Motor off ==> PORTB |= (1<<motor_enable_PORT);
//Output Port D: Left_PWM, Right_PWM
DDRD |= (1<<left_PWM_DDR) | (1<<right_PWM_DDR);

//############### Controll ############
DDRB |= (1<controll_LED_Yellow_DDR) | (1<<controll_LED_Green_DDR) | (1<<start_Taster_DDR); //Ausgang
//DDRB &= ~(1<<start_Taster_DDR); //Eingang
PORTB &= ~(1<<controll_LED_Green_PORT); //Interner Pull Up disable
PORTB &= ~(1<<controll_LED_Yellow_PORT); //Interner Pull Up disable
PORTB |= (1<<start_Taster_PORT); //Interner Pull Up enable

//################ Timer #########
//Data sheet age 98 "Normal Mode"
TCCR0A &= ~(1<<COM0A1) & ~(1<<COM0A0) & ~(1<<WGM01) & ~(1<<WGM00); // OCR0A disconnect, normal Port Function
TCCR0B &= ~(1<<WGM02); // WGM0:2 = 0 --> Normal Mode
TCCR0B |= (1<<CS01) | (1<<CS00); // prescaler 64 --> (16MHz / 64) / 256 = 976,5625 --> ~977 IRQ pro Sekunde
TIMSK0 |= (1<<TOIE0); // Overflow IRQ Enable
sei();

//################ PWM #########
//COM2x1 = HIGH ==> non-inverting-mode, set OC2x at bottom and clear on compare match;
//WGM01 = HIGH und WGM00 = HIGH ==> Fast PWM, TOP = 0xFF, Update of OCRn at bottom, TOV-Flag set on MAX;
TCCR2A |= (1<<COM2A1) | (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);
//CS22 = HIGH ==> clk/64 (from prescaler)
TCCR2B |= (1<<CS22); // hier => 976,6Hz
}

void adjust_all (void)
{
FWD_OnOff = false;
}

bool Abfrage_PB7 (void)
{
if ( (PINB & (1<<start_Taster_PIN) ) == 0 ) //Prüft, ob auf PD5 ein LOW anliegt. Wenn ja, dann...
{
//_delay_ms(50); //...warte kurz (enprellung) und...
if ( (PINB & (1<<start_Taster_PIN) ) == 0) //...prüfe noch einmal. Wenn immer noch,dann...
{
PORTB |=(1<<controll_LED_Green_PIN); //...setze PB6 auf HIGH.
return false;
}
}
return true; //Sonst gib ein True zurück.
}

void Start_Impulse (void)
{
while(Abfrage_PB7()); //Solange kein False zurückgegeben wird, bleibe in der Schleife
//_delay_ms(1000); //Warte, bis mit der weiteren Ausführung gestartet wird
}

void Engine_off (void)
{
motor_Off;
pwm_Value_left = 0;
pwm_Value_right = 0;
}

void FWD_direction (void)
{

left_FWD_direction;
right_FWD_direction;
pwm_Value_left = 190;
pwm_Value_right = 80;
FWD_OnOff = true;

}
void BWD_direction (void)
{
left_BWD_direction;
right_BWD_direction;
}

void easy_drive (void)
{
if (FWD_OnOff == false)
{
FWD_direction();
}
motor_On;

}

int main(void)
{
init_all();
adjust_all();

Start_Impulse();

while(1)
{
easy_drive();
}
}

Eventuell sieht ja jemand den Fehler und könnte diesen mir mitteilen. Danke!

derNeue
16.03.2014, 20:32
Hallo!


Du gibst einen Überlauf Interrupt vom Timer0 frei. Aber nirgends sehe ich den Code für die ISR. Sowas kann ganz lustige Folgen haben.

Auch ist deine scheinbare Tastenentprellung irgendwie seltsam.


Dennis

NewBot
17.03.2014, 08:39
Danke, jetzt geht alles wie es soll.

Mir hat die Zeile: TIFR0 &= ~(1<<TOV0) in der ISR(TIMER0_OVF_vect) gefehlt.

Das mit der entprellung (Abfrage, Warten und nochmalige Abfrage) habe ich so irgendwo mal im Netz gefunden.
Der Zusatz ist nur dazu da um in der endlosschleife drinnen zu bleiben, bis halt die Start-Taste gedrückt ist.

derNeue
17.03.2014, 13:52
Mir hat die Zeile: TIFR0 &= ~(1<<TOV0) in der ISR(TIMER0_OVF_vect) gefehlt.

Das glaube ich nicht. Mit diesem Befehl löscht du das Interrupt Flag. Das wird aber automatisch gelöscht, sobald du in die ISR reinspringst. Nach wie vor fehlt in deinem "kompletten" Code die ISR ganz.


Das mit der entprellung (Abfrage, Warten und nochmalige Abfrage) habe ich so irgendwo mal im Netz gefunden.
Der Zusatz ist nur dazu da um in der endlosschleife drinnen zu bleiben, bis halt die Start-Taste gedrückt ist.

Das ist aber eine schlechte Art einer Entprellung. Für dein jetziges Vorhaben vielleicht ausreichend, aber trotzdem ein ganz schlechter Stil. Für gewöhnlich macht man sowas mit einem Timer-Interrupt.
http://www.mikrocontroller.net/articles/Entprellung#Softwareentprellung


Dennis

NewBot
17.03.2014, 15:58
Stange, dass es trotzdem funktioniert. Heißt also noch mal das Datenblatt und das Web wälzen.
Na gut.

Mit dem Entprellen hast du recht. per Timer ist besser. Wird beim nächsten Projekt beachtet.
Hier brauche ich nur einen Taster und einmal drücken zum start (damit mir der Robot nicht ungewolt vom Tisch springt).