PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Peinliches if else Problem bei Portabfrage



Kaiser-F
12.04.2008, 16:07
Hallo Leute,

ich schäme mich, dieses Problem zu schildern... aber es geht nicht anders.
Ich programmiere schon seit längerem mit AVRGCC (WINAVR),
habe auch schon mehrere Projekte gemacht mit CAN, GrafikDisplays usw...

Ich kann von mir sagen, dass ich es einigermaßen drauf hab.


Nun wollte ich heute mal meinen Bruder ein bisschen anlernen.
Angebangen haben wir mit Ausgänge setzen.
Haben ne simple funktion geschrieben, die ne LED setzt oder löscht.
Dann wollten wir als nächsten schritt nen Schalter anschließen.

Wir benutzen einen ATMega32, DIL40 am Steckbrett. Wir benutzen nur
Drahtbrücken, da die kabel ja nicht 100Pro leiten...

An PB0 schließen wir also unseren Schalter gegen Masse.
Wir initialisieren:


DDRB &= ~(1<<PB0); // PB0 als Eingang
PORTB |= (1<<PB0); // Pullup an PB0 aktivieren


Dann zum Problem:
Ich schreibe folgendes in die Hauptschleife:




if( PINB & (1<<PB0) ){
LED1(1);
}else{
LED1(0);
}



Ist die Bedingung erfüllt, ist alles OK.
Wird die Bedingung nicht erfüllt, also Schalter gedrückt,
dann hängt sich der Controller auf. Bleibt einfach stehen!

Wenn ich es aber so schreibe, funktioniert es:


if( PINB & (1<<PB0) ){
LED1(1);
}
if( !(PINB & (1<<PB0)) ){
LED1(0);
}



Ich verstehe es nicht. Das ist ein typischer Vorführeffekt...
Ich steig einfach nicht dahinter, warum er das else nicht mag.

Ich habe schon bei vielen programmen die obige Schreibweise benutzt...
Es gab nie ein Problem...

Und jetzt das... ich verstehe es einfach nicht....

Ich hoffe jemand von euch kann mir bei diesem lachhaften Problem helfen.

Besten Dank!

PicNick
12.04.2008, 18:38
Very strange.
Da ein Controller aber in diesem Sinne nicht "stehenbleiben" kann, treibt er sich offenbar woanders herum.
kannst du nicht den kompletten Code reinstellen (möglichst uneditiert)
so lange wird er ja wohl nicht sein.

Wenn wir es dann wissen, ist es sicher ein Schwachsinn zum aufs-hirn-klatschen. Da freu ich mich schon drauf.

Kaiser-F
12.04.2008, 19:06
Hallo PicNick,

ich bin gespannt...

Es sind drei Dateien... Ein Winziges Programm:

die main.c:


/************************************************** **********************************/
/* Projektname -=> ATMega32 Versuche */
/* Programmversion -=> V0.1 */
/* Mikrocontroller -=> ATMega32 */
/* Letzte Änderung -=> 12.04.2008 */
/************************************************** **********************************/



// -=> Defines & Includes <=-

// -=> Defines <=-
#define F_CPU 1000000


// -=> AVR Includes <=-
#include <avr/io.h>
#include <util/delay.h>

// -=> Programmheaders <=-


// -=> Programmfiles <=-
#include <led.c>
#include <dip.c>


// -=> Intrrupts <=-


// -=> Hauptfunktion <=-

int main (void){

// -=> Initialisieren <=-
LED_INIT();
DIP_INIT();

// -=> Hauptschleife <=-
while(1){

if( DIP1() ){
//Erster Wartezyklus
LED1(1);
LED2(0);
_delay_ms(500);

//Zweiter Wartezyklus
LED1(0);
LED2(1);
_delay_ms(500);

}else{
//Erster Wartezyklus
LED1(1);
LED2(0);
_delay_ms(50);

//Zweiter Wartezyklus
LED1(0);
LED2(1);
_delay_ms(50);
}

}
return 0;
}


/************************************************** **********************************/


Die led.c:


//LED-TREIBER


//LED INIT
void LED_INIT(void) {
DDRA = (1<<PA5) | (1<<PA0);
}

//LED1 - ON/OFF
void LED1( unsigned int set ) {

if(set) {
PORTA |= (1<<PA0);
}else{
PORTA &= ~ (1<<PA0);
}
}

//LED2 - ON/OFF
void LED2( unsigned int set ) {

if(set) {
PORTA |= (1<<PA5);
}else{
PORTA &= ~ (1<<PA5);
}
}


Die dip.c:


//DIP

//INIT
void DIP_INIT(void) {
DDRB &= ~(1<<PB0); //PINB0 als Eingang
PORTB |= (1<<PB0); //PINB0 10K PullUp aktivieren
}

uint8_t DIP1( void ) {
if( PINB & (1<<PB0) ){ //Wenn PINB0 = 1 (5V)
return 0; //Verlasse Funktion mit 0 (AUS)
}else{ //Ansonsten
return 1; //Verlasse Funktion mit 1 (EIN)
}

}

geronet
12.04.2008, 19:30
Eins hab ich schonmal:

_delay_ms(500) wird nicht funktionieren:

"The maximal possible delay is 262.14 ms / F_CPU in MHz"

Grüsse, Stefan

Kaiser-F
12.04.2008, 19:35
Hallo Stefan,

also bei mir hat das immer funktioniert...
Das kann aber nicht der Grund sein, warum das Spinnt...
Denn egal was ich in die if/else schleife schreibe, hängt er scheinbar.

Ich versteh es einfach nicht... Ich habe in vielen Projekten diegleiche
schreibweise... und da funktioniert es...

Hab es auch schon auf anderen Pins und Ports probiert... auch schon nen frischen controller genommen... Hilft alles nix..

UND DAS BEI SO EINEM WINDIGEN PROGRAMM...

Ich hoffe bloß ich hab meinen Bruder durch diesen Vorführeffekt keine Angst eingejagt ^^

pctoaster
12.04.2008, 20:09
Hi,
der delay funktioniert schon (auch wenn es hier im Board immer anders behauptet wird), weil:
Function Documentation

void _delay_ms ( double __ms )
Perform a delay of __ms milliseconds, using _delay_loop_2().
The macro F_CPU is supposed to be defined to a constant defining the CPU clock frequency (in Hertz).
The maximal possible delay is 262.14 ms / F_CPU in MHz.
When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.

Aber warum das Programm nicht geht, kann ich add hoc auch nicht erklären. Es könnte sein, da dies mit den Prellen des Schalters zu tun hat. Es wäre vielleicht mal interessant zu sehen, wie die main.lst dazu aussieht.

robocat
12.04.2008, 20:33
neulich hatte ich etwas ähnliches, da hatte ich mit avr-gcc und einem standard-makefile kompiliert, und irgendetwas haarsträubend einfaches ging nicht. bzw mit folgendem makefile dann doch.. kA wieso:

## General Flags
PROJECT = main
MCU = atmega8
TARGET = main
CC = avr-gcc

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -O0
CFLAGS += -Wp,-M,-MP,-MT,$(*F).o,-MF,dep/$(@F).d

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0


## Objects that must be built in order to link
OBJECTS = $(TARGET).o

## Build
all: $(TARGET) $(TARGET).hex $(TARGET).eep

## Compile
$(TARGET).o: $(TARGET).c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

##Link
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@

%.eep: $(TARGET)
avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@

%.lss: $(TARGET)
avr-objdump -h -S $< > $@

## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) $(TARGET).elf $(TARGET).hex $(TARGET).eep

## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)

vielleicht mal testen wenn sonst niemand rat weiss.

gruesse

EDIT: lag also an irgendwelchen compiler-flags, nur welche habe ich auf die schnelle nicht rausgefunden.

Kaiser-F
13.04.2008, 15:22
Der frisst das else{} nicht..
sobald ein Befehl zwischen den klammern bei else steht,
hängt er sich auf... (bzw. macht was anderes...

Egal ob ich jetzt die dely mit dabei hab, oder im ganzen programm kein delay verwende...

Ich verstehe es nicht!

Michael-Hage
13.04.2008, 16:09
Ich habe dein Programm mal mit dem AVRStudio kompiliert und auf dem Atmega8 ausgeführt. Die Lampe blinkt schnell und wenn der Taster gedrückt wird langsam. Also ist dein Code definitiv nicht falsch.

Ich habe die Lampe an PC0 und den Taster auf PD4 geändert. Vielleicht ist bei deinem Atmega32 der Port irgendwie anders gefused? Vielleicht mal andere Ports probieren?

PicNick
13.04.2008, 18:21
Is ja wirklich verzwickt. @Michael-Hage hat ja schon gesagt, dass es bei ihm funzt. Ist ja wirklich so nix zu sehen
Also,
Mach bitte eine Version die HÄNGENBLEIBT, lass dir aber auch die .LSS files machen und stell die hier rein rein. (wäre ultimativ)

Zwischenversuch, um einzukreisen, WO die Schweinebacke herumkurvt:
dip.c



uint8_t DIP1( void )
{
if( PINB & (1<<PB0) )
return 0;
return 1; // also KEIN else
}


Alternative, aber sicherheitshalber getrennt probieren

main.c


while (1)
{
if( DIP1() )
{
LED1(1);
LED2(0);
_delay_ms(500);
LED1(0);
LED2(1);
_delay_ms(500);
continue; // auch kein else
}
LED1(1);
LED2(0);
_delay_ms(50);
LED1(0);
LED2(1);
_delay_ms(50);
}



Spekulation: Einer der wenigen Möglichkeiten, im Nirwana zu verschwinden, ist die Dauerschleife am Ende des Programmes (vom C eingefügt).

ex535
13.04.2008, 18:36
Hi Franz,
dein Programm funktioniert bei mir.
Pollin Atmel Evaluations-Board mit Addon Board
Port's geändert!
Pullup abgeschaltet, da sonst Taste nicht erkannt wird.
avr-gcc Compiler 4.2.2 vom 21.12.2007
Gruß
Kurt

Kaiser-F
13.04.2008, 23:12
Hallo zusammen,

ich Danke euch vielmals für Euren tollen Einsatz!
Sehr nett von Euch, dass ihr es sogar getestet habt!!!

Leider ist mein Bruder heute nicht da und kommt erst
morgen mit seinemNotebook zurück...
Also hab ich die Tests an meinem PC fortgesetzt.
Erst mal das Programm neu Compiliert und geflasht...
Und siehe da... ES GEHT!

Morgen stelle ich dann den Ordnerinhalt nach dem Compilieren online.

Er hat jedenfalls die gleiche WINAVR-Version installiert wie ich sie habe:
WinAVR-20071221rc1

Es ist genau der gleiche Code... Gleicher Programmer ( USB-Programmer von chip45.com )

Bei mir gehts, bei ihm nicht.

Er hat ein Lenovo Thinkpad X60...

Ich verstehe es einfach nicht.

Hier mal der code des funktionierenden Programms:
http://www.sir-kaiser.de/upload/Grundprogramm.zip

Morgen bekommt ihr dann das nichtfunktionierende Programm
mit gleichen C-Files und Makefile!


Nochmals besten Dank Leute!!!

Gute Nacht!

pctoaster
17.04.2008, 23:32
machst Du das flashen mit anschließenden Lesetest ?
Gleicher Programmer, gleiches Kabel, aber eben nicht selbes Programmer, selbes Kabel ;-) Fehler beim flashen ?
Und wie schon erwähnt: die *.lss vergleichen.