Forum: Mikrocontroller und Digitale Elektronik atmega32: Inputverhalten PORTB


von maggie (Gast)


Lesenswert?

Hi,

ich hab folgendes Problem:

Ich habe mir zwei Taster, wie unter 
http://www.mikrocontroller.net/articles/Entprellung beschrieben, mit dem 
74HC14 entprellt. Die Signale gebe ich auf PORTB an die Pins PB0 und 
PB1.

DDRB = 0x00;

Jetzt frage ich alle 100ms die Tasterzustände ab:

if(PINB & PB0) {
...
}

if(PINB & PB1) {
...
}

Wenn ich aber jetzt den Taster an Port PB1 betätige wird auch die obere 
Bedingung wahr.

Ich habe mir das Signal mit dem Oszi angeschaut. Wenn ich den Taster PB1 
drücke, liegt an PB1 HIGH-Pegel an. An PB0 bleibt der Pegel auf LOW. 
Also hab ich schon mal keine ungewollte Verbindung zwischen den beiden 
Pins.

Wenn ich nun die Signale nicht auf PORTB sondern auf PORTA lege, 
funktioniert alles einwandfrei.

Meine Frage: Wer weiß an was es liegen kann?

P.S.: Ich hab die alternativen Funktionen der PINS PB0 und PB1 nicht 
aktiviert ;)

von Justus S. (jussa)


Lesenswert?


von maggie (Gast)


Lesenswert?

Korrektur: ich verwende:

PORTB & (1<<PB0) und PORTB & (1<<PB1)

von maggie (Gast)


Lesenswert?

Sorry,

jetzt richtig:

PINB & (1<<PB0) und PINB & (1<<PB1)

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:
> Korrektur: ich verwende:
>
> PORTB & (1<<PB0) und PORTB & (1<<PB1)

auch das ist falsch.

Hör auf, einfach immer nur Stückwerk zu posten.
Nimm dein *.c File und häng es als Attachment an. Auf die Art kannst du 
keine Fehler beim Tippen machen und wir haben alles was wir brauchen. 
Und zwar so, wie du es tatsächlich programmiert hast und nicht in der 
25ten fehlerbereinigten im Forum getippten Version, die dann immer noch 
nicht dem Programm entspricht, das tatsächlich am µC läuft.

von Huch (Gast)


Lesenswert?

Ach Du weisst doch: Das Problem liegt garantiert nicht in den nicht 
gezeigten Zeilen.
Und evtl. Fehler sind sowieso nur Tippfehler. Im "richtigen" Quelltext 
ist es so wie Du nachher als Korrektur vorschlägst.
Es wird dann eher an der Temperatur oder dem Wochentag gelegen haben.

Aber eine Frage ist da noch: Was ist der Unterschied zwischen PB0 und 1 
<< PB0 ?

Wer hierin Ironie findet, darf sie behalten.

von maggie (Gast)


Lesenswert?

Jo, alles klar:
1
void io_get_inputs(void) {
2
  if(PINB & (1<<PB0)) {
3
    if(!(DISPLAY_OUTPORT & (1<<DISPLAY_GREEN))) { // GREEN BL turned on
4
      display_green_backlight_off;
5
    } else {
6
      display_green_backlight_on;
7
    }
8
  }  
9
}

display_green... sind Makros.

von Huch (Gast)


Lesenswert?

Hab ich's nicht gesagt?

von NurEinGast (Gast)


Lesenswert?

Wieso schaffst Du es nicht einfach das zu zun, was oben vorgeschlagen 
wurde ?

>     Nimm dein *.c File und häng es als Attachment an.

Willst Du Hilfe, oder lieber doch nicht ?

von maggie (Gast)


Lesenswert?

Aber eine Frage ist da noch: Was ist der Unterschied zwischen PB0 und 1
<< PB0 ?

Du hast recht. Hier ist kein Unterschied. Bei PB5 und 1<<PB5 aber sehr 
wohl, da PB5 = 5 und 1 << PB5 = 0x20.

Abgesehen davon, dass ich hier halt zum ersten mal was poste und meine 
Post einbisschen verk*ckt habe, ist das noch lang kein Grund sich hier 
den arroganten Schnösel raushängen zu lassen.

von NurEinGast (Gast)


Lesenswert?

PB0 = 0
1<<BP0 = 1

von maggie (Gast)


Lesenswert?

NurEinGast schrieb:
> Wieso schaffst Du es nicht einfach das zu zun, was oben vorgeschlagen
> wurde ?
>
>>     Nimm dein *.c File und häng es als Attachment an.
>
> Willst Du Hilfe, oder lieber doch nicht ?


Wo ist dein Problem? Ich hab schick dir den Ausschnitt aus meinem 
C-File, um den es geht. Der Rest ist irrelevant.

Wie am Anfang geschrieben, hab ich das DDRB mit 0x00 initialisiert und 
das sollte doch dafür reichen, dass du dir deine Gedanken darüber machen 
kannst.

Das ganze ist Teil eines größeren Projekts und ich sehe keinen Anlass, 
das ganze Projekt hier reinzuposten.

von zaphod (Gast)


Lesenswert?

Was bewirkt ein Lesezugriff auf PINx?
Wo ist die Abfrage des zweiten Tasters?

von Huch (Gast)


Lesenswert?

> ist das noch lang kein Grund sich hier den arroganten Schnösel raushängen > zu 
lassen.

Das war nur Hellseherei. Kein Grund zur Aufregung. Nichts gegen Dich 
persönlich. Reine Statistik. Wenn Drei Milliarden Fische nur im Wasser 
atmen können, vermute ich vom 3.000.000.001ten das selbe.

von maggie (Gast)


Lesenswert?

NurEinGast schrieb:
> PB0 = 0
> 1<<BP0 = 1

Ok, Schach matt ;)

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:
> NurEinGast schrieb:
>> Wieso schaffst Du es nicht einfach das zu zun, was oben vorgeschlagen
>> wurde ?
>>
>>>     Nimm dein *.c File und häng es als Attachment an.
>>
>> Willst Du Hilfe, oder lieber doch nicht ?
>
>
> Wo ist dein Problem? Ich hab schick dir den Ausschnitt aus meinem
> C-File, um den es geht. Der Rest ist irrelevant.

Sagt wer?

Du scheinst nicht gar so unerfahren zu sein.
Wenn der Fehler tatsächlich in dem Code stecken würde, den du gepostet 
hast, hättest du ihn wahrscheinlich selber gesehen.
Da du ihn aber nicht gesehen hast ....  steckt der Fehler ganz woanders.

qed

Poste deinen Code!
Und das mein ich ernst


> Das ganze ist Teil eines größeren Projekts und ich sehe keinen Anlass,
> das ganze Projekt hier reinzuposten.

Du kannst ja auch ein Testprojekt machen, indem du nur den relevanten 
Teil herausziehst, compilierst, auf die Hardware brennst und nachsiehst 
ob der Fehler dort auch noch vorhanden ist. Wenn ja, dann postest du das 
kleinere Testprojekt.

Ansonsten: Such deine Fehler alleine. Irgendwann haben die meisten hier 
keine Lust mehr, dem Fragesteller ständig die Würmer aus der Nase ziehen 
zu müssen.

von maggie (Gast)


Lesenswert?

Ok,

jetzt für alle:
1
#define BIT_IS_SET(var, bit)   ((var) & (1 << (bit)))
2
#define BIT_IS_CLEAR(var, bit)   !BIT_IS_SET(var, bit)
3
4
...
5
6
#define IO_UP       PB0
7
#define IO_ENTER    PB1
8
#define IO_DOWN     PB4
9
10
...
11
12
void io_init(void) {
13
  io_tast_status = 0x00;
14
  io_tast_status_old = 0x00;
15
  io_tast_changed = 0x00;
16
}
17
18
void io_get_inputs(void) {
19
  io_tast_status_old = io_tast_status;
20
  io_tast_status = BIT_IS_SET(PINB, IO_UP) | BIT_IS_SET(PINB, IO_ENTER) | BIT_IS_SET(PINB, IO_DOWN);  
21
  io_tast_changed = io_tast_status_old ^ io_tast_status;  
22
23
  // Ist die Taste gedrückt und hat sich ihr Zustand geändert?
24
25
  if(BIT_IS_SET(io_tast_changed, IO_UP) && BIT_IS_SET(io_tast_status, IO_UP)) {
26
    if(BIT_IS_CLEAR(DISPLAY_OUTPORT, DISPLAY_GREEN)) { // GREEN turned on
27
      display_green_backlight_off;
28
    } else {
29
      display_green_backlight_on;
30
    }
31
  }    
32
33
  // Ist die Taste gedrückt und hat sich ihr Zustand geändert?
34
35
  if(BIT_IS_SET(io_tast_changed, IO_DOWN) && BIT_IS_SET(io_tast_status, IO_DOWN)) {
36
    if(BIT_IS_CLEAR(DISPLAY_OUTPORT, DISPLAY_RED)) { // RED turned on
37
      display_red_backlight_off;
38
    } else {
39
      display_red_backlight_on;
40
    }
41
  }
42
}

von maggie (Gast)


Angehängte Dateien:

Lesenswert?

So, ich habe jetzt ein Testprojekt zusammengestellt.

Somit hoffe ich allen Forderungen der Gemeinschaft nachzukommen und zu 
einer Lösung des Problems meinen Teil in angemessener Weise beizutragen.

Sorry, wenn ich das Ganze etwas umständlich gemacht habe.

von Karl H. (kbuchegg)


Lesenswert?

Ich versteh zwar nicht, wozu in einem Testprogramm dass sich um Taster 
und LED dreht, ein Timer und ein Watchdog enthalten sein muss

aber da dein LED am PC5 hängt und du einen Mega32 verwendest: JTAGEN ist 
abgeschaltet?

von maggie (Gast)


Angehängte Dateien:

Lesenswert?

Karl heinz Buchegger schrieb:
> Ich versteh zwar nicht, wozu in einem Testprogramm dass sich um Taster
> und LED dreht, ein Timer und ein Watchdog enthalten sein muss
>
> aber da dein LED am PC5 hängt und du einen Mega32 verwendest: JTAGEN ist
> abgeschaltet?

JTAGEN ist aus:

Fusebits:  -U lfuse:w:0x2f:m -U hfuse:w:0xc9:

Wie gesagt, das ganze ist Teil eines größeren Projekts und da sind 
getimete Tasks und der Watchdog von Nöten. Hier im Testprojekt 
vielleicht nicht. Da hast du recht. Aber es sollen ja etwa gleiche 
Bedingungen wie bei dem großen Projekt bestehen.

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:

> Wie gesagt, das ganze ist Teil eines größeren Projekts und da sind
> getimete Tasks und der Watchdog von Nöten. Hier im Testprojekt
> vielleicht nicht. Da hast du recht. Aber es sollen ja etwa gleiche
> Bedingungen wie bei dem großen Projekt bestehen.

Ist ok.

Deine Vorstellung wie extern funktioniert ist zwar fehlerhaft. Aber auf 
die Schnelle ist mir da jetzt nichts aufgefallen.

Um festzustellen, ob es ein Hardwareproblem ist, würde ich noch weiter 
abspecken
1
#include <avr/io.h>
2
3
int main()
4
{
5
  DDRB = 0x00;
6
  DDRC = 0xFF;
7
8
  while( 1 ) {
9
    if( PINB & ( 1 << PB0 ) )
10
      PORTC |= ( 1 << PC5 );
11
 
12
    if( PINB & ( 1 << PB1 ) )
13
      PORTC &= ~( 1 << PC5 );
14
  }
15
}

das wär mein Hardware-Testprogramm.
Die LED muss mit PB0 ein und mit PB1 ausschaltbar sein.

Geht das, dann hat es IMHO nichts mit der Hardware zu tun.
(Auch wenn ich mir die Arbeit mit den FF gar nicht gemacht hätte)

von maggie (Gast)


Angehängte Dateien:

Lesenswert?

Vielleicht noch als Ergänzung:

Im Anhang befindet sich das Oszibild, wenn ich auf den Taster auf PB1 
drücke. Man kann sehen, dass keine Rückwirkungen bestehen.

Und auch nochmal: An PORTA funktioniert das Ganze. Deshalb kann es wohl 
auch nicht am PORTC liegen (z.B. JTAG).

von maggie (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
>
> Deine Vorstellung wie extern funktioniert ist zwar fehlerhaft. Aber auf
> die Schnelle ist mir da jetzt nichts aufgefallen.
>

Was ist denn an meiner Vorstellung so falsch?

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:
> Karl heinz Buchegger schrieb:
>>
>> Deine Vorstellung wie extern funktioniert ist zwar fehlerhaft. Aber auf
>> die Schnelle ist mir da jetzt nichts aufgefallen.
>>
>
> Was ist denn an meiner Vorstellung so falsch?


Bei Funktionsprototypen brauchst du kein extern.
Dafür aber bei globalen Variablen, die in einem Header File sind. Sind 
Variablen nicht global, haben sie auch in Header Files nichts verloren.


header_zu_source.h
********
1
#ifndef HEADER_H
2
#define HEADER_H
3
4
5
extern uint8_t  globVar;
6
7
void foo( void );
8
9
#endif

source.c
********
1
// Implementierung für header_zu_source.h
2
#include "header.h"
3
4
uint8_t globVar;
5
6
static uint8_t  meine_Filelokale_Variable;
7
8
void foo()
9
{
10
  globVar = 8;
11
  meine_Filelokale_Variable = 0;
12
}

main.c
******
1
// Verwendet header_zu_source.h
2
#include "header.h"
3
4
int main()
5
{
6
  globVar = 5;
7
}

von maggie (Gast)


Lesenswert?

Das

Karl heinz Buchegger schrieb:
>
> Bei Funktionsprototypen brauchst du kein extern.
> Dafür aber bei globalen Variablen, die in einem Header File sind. Sind
> VAriablen nicht global, haben sie auch in Header Files nichts verloren.
>
>
> header_zu_source.h
> ********
> #ifndef HEADER_H
> #define HEADER_H
>
>
> extern uint8_t  globVar;
>
> #endif
>
> source.c
> ********// Implementierung für header_zu_source.h
> #include "header.h"
>
> uint8_t globVar;
>
> main.c
> ******// Verwendet header_zu_source.h
> #include "header.h"
>
> int main()
> {
>   globVar = 5;
> }

Das mit den Funktionsprototypen gilt aber nur, wenn ich immer jede 
Headerdatei eines Moduls einbinden will.

Und da ich in meinen Moduldateien nur die Header der Module drinhabe, 
referenziere ich Funktionen aus anderen Modulen mit extern.

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:

> Das mit den Funktionsprototypen gilt aber nur, wenn ich immer jede
> Headerdatei eines Moduls einbinden will.

Nein.
Generell.
Ein Funktionsprototyp braucht kein extern. Er schadet allerdings auch 
nicht.

> Und da ich in meinen Moduldateien nur die Header der Module drinhabe,
> referenziere ich Funktionen aus anderen Modulen mit extern.

Du hast aber zb im timer.h deine globalen Varablen nicht mit extern 
markiert. Nochmal: In Header Files haben Variablen ohne extern nichts 
verloren!

Es geht hier um die Unterscheidung zwischen Definition und Deklaration!
http://www.mikrocontroller.net/articles/FAQ#Globale_Variablen_.C3.BCber_mehrere_Dateien

von Karl H. (kbuchegg)


Lesenswert?

Was ist jetzt mit dem Einfachst-Testprogramm?

von maggie (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Was ist jetzt mit dem Einfachst-Testprogramm?

Auch beim Minimalprogramm gibts keinen Unterschied.

An PORTB gehts nicht an PORTA gehts.

von maggie (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
>
> Du hast aber zb im timer.h deine globalen Varablen nicht mit extern
> markiert. Nochmal: In Header Files haben Variablen ohne extern nichts
> verloren!
>
> Es geht hier um die Unterscheidung zwischen Definition und Deklaration!
> http://www.mikrocontroller.net/articles/FAQ#Global...

Ok alles klar. Ist halt einfacher, wenn ich Module aus nem anderen Modul 
einbinden will, weil ich dann nur noch das header-File des Moduls 
einbinden muss und nicht die einzelnen Variablen rauspflücken (und 
pfelgen) muss.

Funktional ist es aber kein Problem.

von maggie (Gast)


Lesenswert?

So ich habe die Ursache des Problems gefunden. PB1 war nicht 100% sauber 
angelötet. Jetzt funktioniert alles so wie es soll.

Viele Dank für eure Geduld.

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:
> Karl heinz Buchegger schrieb:
>>
>> Du hast aber zb im timer.h deine globalen Varablen nicht mit extern
>> markiert. Nochmal: In Header Files haben Variablen ohne extern nichts
>> verloren!
>>
>> Es geht hier um die Unterscheidung zwischen Definition und Deklaration!
>> http://www.mikrocontroller.net/articles/FAQ#Global...
>
> Ok alles klar. Ist halt einfacher, wenn ich Module aus nem anderen Modul
> einbinden will, weil ich dann nur noch das header-File des Moduls
> einbinden muss und nicht die einzelnen Variablen rauspflücken (und
> pfelgen) muss.

Genau darum geht es ja!

Wenn du es richtig machst, ist es nämlich überhaupt kein Problem.
Wenn du deine timer.h in 2 andere *.C Files inkludierst, läufst du 
bereits in Probleme.

von NurEinGast (Gast)


Lesenswert?

Na dann kann ich ja jetzt mein Testboard wieder anders verwenden.
Ich fand Dein Problem interessant und hatte eben Deine Software in mein 
Testboard gebrannt und mit Debugger schauen wollen, was da passiert :-) 
Hatte aber kein Problem gefunden und wollte Dich gerade fragen ob es 
nicht vielleicht doch irgendwie an der HW liegen könnte.

Mir ist zwar nicht wirklich klar, warum dieses Fehlerbild auftritt, wenn 
PB1 nicht sauber verlötet ist - aber egal. Wenn alles läuft - auch gut.

Viel Erfolg weiterhin bei Deinem Projekt

NurEinGast

von maggie (Gast)


Lesenswert?

NurEinGast schrieb:
> Na dann kann ich ja jetzt mein Testboard wieder anders verwenden.
> Ich fand Dein Problem interessant und hatte eben Deine Software in mein
> Testboard gebrannt und mit Debugger schauen wollen, was da passiert :-)
> Hatte aber kein Problem gefunden und wollte Dich gerade fragen ob es
> nicht vielleicht doch irgendwie an der HW liegen könnte.
>
> Mir ist zwar nicht wirklich klar, warum dieses Fehlerbild auftritt, wenn
> PB1 nicht sauber verlötet ist - aber egal. Wenn alles läuft - auch gut.

Mir ist zwar auch nicht klar, was die defekte Lötstelle hier verursacht 
hat. Das Oszibild gibt ja keinerlei Aufschlüsse darüber. Irgendwie schon 
strange.

> Viel Erfolg weiterhin bei Deinem Projekt
>
> NurEinGast

Danke für deine Bemühungen ;)

von maggie (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
>
> Genau darum geht es ja!
>
> Wenn du es richtig machst, ist es nämlich überhaupt kein Problem.
> Wenn du deine timer.h in 2 andere *.C Files inkludierst, läufst du
> bereits in Probleme.

Und noch wegen der Prototypen. Mit extern sage ich dem Compiler ja nur, 
dass sich die Funktion in einem anderen Modul befindet. Sollte ja 
prinzipiell richtig sein. Ist aber nicht mehr nötig wenn ich deine 
Ratschläge befolge ;)

Danke

von Karl H. (kbuchegg)


Lesenswert?

maggie schrieb:
> Karl heinz Buchegger schrieb:
>>
>> Genau darum geht es ja!
>>
>> Wenn du es richtig machst, ist es nämlich überhaupt kein Problem.
>> Wenn du deine timer.h in 2 andere *.C Files inkludierst, läufst du
>> bereits in Probleme.
>
> Und noch wegen der Prototypen. Mit extern sage ich dem Compiler ja nur,
> dass sich die Funktion in einem anderen Modul befindet.


Das weiß er auch so.

void foo( void );

kann nur ein Prototyp und nicht die Implementierung einer Funktion sein. 
Daher ist das extern hier nicht notwendig, wenn es auch nicht schadet.

Mittels "extern" erhebt man etwas zu einer Deklaration um es von einer 
Definition zu unterscheiden. Bei Funktionen ist die Sache auch so klar, 
nur bei Variablen muss man selber Hand anlegen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.