www.mikrocontroller.net

Forum: Compiler & IDEs Anfängerfrage zu IO´s


Autor: Marc D. (drebin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gemeinde,

ich bin gerade dabei, mir den GCC mit einem Atmega8L anzueignen. Dabei 
benutze ich das AVR Studio 4 sowie WINAVR. Das Brennen funktioniert 
einwandfrei, LED´s
habe ich auf meinem myAVR USB Board auch schon zum Blinken gebracht ;-).
Nun habe ich aber eine Frage zum TuT zum Auswerten der PAx bzw. PINx.
Im TuT steht folgendes Bsp:
while ( !(WARTEPIN & (1 << WARTEBIT)) ) ;

weiter unten:
#include <avr/io.h>
...
/* Fuehre Aktion aus, wenn Bit Nr. 1 (das "zweite" Bit) in PINC gesetzt (1) ist */
if ( PINC & (1<<PINC1) ) {
/* Aktion */
}
/* Fuehre Aktion aus, wenn Bit Nr. 2 (das "dritte" Bit) in PINB geloescht (0) ist */
if ( !(PINB & (1<<PINB2)) ) {
/* Aktion */
}
...

Ich versteh leider den Zusammenhang für die Abfrage des z.B. PINB nicht, 
wenn es expliziet um den PINB2 geht. ->(if (PINB & (1<<PINB2)) ..
Ich mit meinem Anfängerwissen hätte es so geschrieben:
 if (PINB2 == 1) 

.... hoffentlich hab ich mich jetzt nicht zum Affen gemacht :-)

Viele Grüße und Danke schonmal im Voraus..

Gruß, Marc

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PINB2 ist lediglich die Position des Pins im I/O-Register, die in der 
betreffenden Header-Datei definiert ist (Da steht irgendwo "#define 
PINB2 2"). PINB2 ist lediglich eine Zahl (eine 2, um genau zu sein).

ANSI-C-Compiler wie der AVR-GCC können nicht auf einzelne Bits 
zugreifen. Die kleinste verarbeitbare Datenmenge sind auf der 
AVR-Plattform 8 Bit. Um einzelne Bits zu manipulieren, muss man deshalb 
zu "Tricks" greifen. Im Artikel Bitmanipulation ist beschrieben, wie 
und warum es geht.

Kommerzielle Compiler haben i.d.R. µC-spezifische Erweiterungen für 
Bitzugriffe, die aber nicht Standard-konform und demzufolge auch nicht 
portierbar sind. Die "1 << BIT"-Schreibweise hingegen versteht jeder 
C-Compiler.

Autor: Marc D. (drebin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen vielen Dank!
Es hat sprichwörtlich "klick" gemacht.

Gruuß, Marc

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kleine Anmerkung nur:

Johannes M. wrote:

> Kommerzielle Compiler haben i.d.R. µC-spezifische Erweiterungen für
> Bitzugriffe, ...

s/i.d.R./manchmal/

Nicht jeder hat sowas, und bspw. ein IAR lebt auch komplett konform
mit dem Standard -- immerhin eine Art Flaggschiff unter den
kommerziellen Compilern (sowohl von der Codequalität als auch vom
Preis ;-).

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc D. wrote:

> Ich mit meinem Anfängerwissen hätte es so geschrieben:
>
>
 if (PINB2 == 1) 
>
> .... hoffentlich hab ich mich jetzt nicht zum Affen gemacht :-)

Nö, garnicht.

Allerdings ist PINB2 etwas anders definiert, als Du denkst.
Um es so zu schreiben, wie Du es vorhast, muß man es etwas anders 
definieren (daher besser einen anderen Namen wählen).

So definiert und verwendet man Bitvariablen:

#include <io.h>


struct bits {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
} __attribute__((__packed__));


#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)


#define PINB_2  SBIT( PINB, 2 )
#define PORTB_3 SBIT( PORTB, 3 )


void test( void )
{
 if (PINB_2 == 1){
   PORTB_3 = 1;
 }
}



Peter

Autor: Marc D. (drebin)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Besten Dank noch einmal für Eure Unterstützung!

@Peter: nochmehr vielen Dank für die Mühe :-)

Ich werd mich da eher an die Schreibweise wie im GCC-TUT halten :-).

Zu viele versch. Schreibweisen bringen mich im Moment noch ziemlich
durcheinander. Gerade auch bei den "einfachen" Sachen wie setzen von 
Variablen
...die einen schreiben es so wie im TUT mit u_int8  usw.
da hab ich mich noch nicht daran gewöhnt. Bei mir ist´s noch immer das 
unsigned int   usw...  ;-)

Ich denke, ich hab bis jetzt ganz gut Meter gemacht, was das lernen 
betrifft. Mir fehlt jetzt nur noch die Routine.

Im Rahmen meiner Facharbeit für den Techniker will ich ein LCD-Display 
für
mein Motorrad entwerfen..  Drehzal, Geschwindigkeit und eingelegte 
Gangstufe
sollen dabei angezeigt werden. Den AD-Wandler hab ich jetzt soweit 
fertig durchgearbeitet.  Der sowie die ganzen LCD Sachen funktionieren 
auch.
Jetzt fehlt nur noch die Interruptbehandlung mit den Timern und 
Countern.

Könntet "Ihr" Euch aber vllt. mal meinen Code anschauen? Ich denke, der
ist einigermassen lesbar formatiert.
Wie gesagt, bin noch in der Lernphase und beschäftige mich damit seit 
gut 1 Woche.
Danke schonmal für Eure Kritik!

Vielen Dank und Gruß, Marc

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kommentare zum Code:

F_CPU muß vor den #includes, oder besser noch gleich im Makefile 
definiert werden. Wahrscheinlich ist es das auch bei dir, sonst hättest 
du beim #include eine Fehlermeldung bekommen, daß es nicht definiert 
ist.

Dein Einrückungs-Stil ist ziemlich chaotisch.

Verschachtelte Funktionen sind in C eigentlich nicht erlaubt. Es gibt 
auch keinen wirklichen Grund, ReadChannel innerhalb von main zu 
definieren, und es verwirrt auch eher. Stecke die Funktion nach außen.

Ein unsigned long ist für die Mittelwert-Bildung eigentlich nicht nötig, 
(aber auch nicht wirklich schädlich). Der ADC arbeitet mit 10 Bit, daher 
paßt die Summe zweier Wandlungen in 11 Bits, also reicht ein 16-Bit-Wert 
dafür locker aus.

> gangstufe=0x4E;    //wenn ja, ASCII für N wird gezeigt

Wenn du ein N haben willst, schreib das doch einfach hin:
  gangstufe='N';

> else if(adcwert1<=365) //Vergleich mit ADC-Wert für Uadc=1,79V

Hier könnte man sich zur Übersichtlichkeit ein Makro schreiben, das die 
Umrechnung des adc-Werts in Volt macht. Solange man mit 
Compilezeit-Konstanten arbeitet, wird die Berechnung auch im Compiler 
gemacht, es produziert also keinen Overhead.
#define VOLT(wert) ((wert) * 1024.0 / 5.0)
...
 else if (adcwert1 <= VOLT(1.79)))
 

Autor: Marc D. (drebin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rolf,

vielen Dank für Deinen Beitrag!
Solche Kommentare helfen ungemein... weil ich wie gesagt noch
nicht so den Überblick habe, weder mit der Programmiersprache C noch
mit dem Atmel.

Also, ich gelobe Besserung und Deine Info´s werden natürlich in meine 
zukünftige Schreibweise mit einfliessen ;-).

Also, wem noch mehr auffällt, nur zu!!!


Gruß, Marc

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier
     else if(adcwert1>=891)    //Vergleich mit ADC-Wert f�r Uadc=4,69V
          gangstufe=0x36;    //wenn ja, ASCII f�r 6 wird gezeigt

  lcd_gotoxy(0,0);        //Cursor erste Position 
  lcd_puts("km/h:");        //Vorbereitung f�r Geschw.
  
  
  lcd_gotoxy(10,0);        //Cursor so ziemlich letzte Pos Zeile1
  lcd_puts("Gang:");        //dauerhaftes Anzeigen von "Gang:"
  lcd_gotoxy(15,0);        //Cursor hinter ":" setzen
  lcd_putc(gangstufe);      //Anzeigen des ASCII -Zeichens
  
  lcd_gotoxy(0,1);        //Cursor n�chste Zeile
  lcd_puts("U/min:");        //Vorbereitung Drehzahl

  _delay_ms(60);          //n�tig, da Clear-Screen als n�chstes
  lcd_clrscr();          // zuk�nftig noch n�tig f�r korr Drehzahl
  }

Mir gehts um das lcd_clrscr().
Grundsätzlich bin ich kein Freund von ständigem Clear Screen.
Meist tendiert das zu mächtigem Geflacker.
Soviel aber nur als Einschub.

Überleg mal. Nach dem lcd_clrscr(). Was passiert alles bevor
wieder aufs Display geschrieben wird? Oder mit anderen Worten:
Was passiert alles, solange das Display leer ist?
Das ist ne ganze Menge: Da wird der ADC ausgelesen, da werden
auszugebende Buchstaben bestimmt, etc.
In dieser ganzen Zeit ist das Display leer. Gibt es einen Grund
dafür, warum das so sein muss? Nein, nicht wirklich.
Es reicht doch völlig aus, daß das Display gelöscht wird (wenn
es denn unbedingt sein muss, dass es komplett gelöscht wird) kurz
bevor die nächste Ausgabe hingepinselt wird. Auf diese Art ist
jede einzelne Ausgabe maximal lang zu sehen und das Display ist
nur minimal lang leer.
  lcd_clrscr();          // zuk�nftig noch n�tig f�r korr Drehzahl

  lcd_gotoxy(0,0);        //Cursor erste Position 
  lcd_puts("km/h:");        //Vorbereitung f�r Geschw.
  
  
  lcd_gotoxy(10,0);        //Cursor so ziemlich letzte Pos Zeile1
  lcd_puts("Gang:");        //dauerhaftes Anzeigen von "Gang:"
  lcd_gotoxy(15,0);        //Cursor hinter ":" setzen
  lcd_putc(gangstufe);      //Anzeigen des ASCII -Zeichens
  
  lcd_gotoxy(0,1);        //Cursor n�chste Zeile
  lcd_puts("U/min:");        //Vorbereitung Drehzahl

  _delay_ms(60);          //n�tig, da Clear-Screen als n�chstes

Der erste lcd_gotoxy kann dann wahrscheinlich auch entfallen,
da der clrscr() den Cursor normalerweise in die Homeposition
bringt.

Ob der _delay_ms da am Ende noch notwendig ist, musst du ausprobieren.
Auf jeden Fall kann er aber wesentlich kürzer ausgeführt werden.
Kürzere delay -> mehr Rechenzeit für die wirklich wichtigen Dinge
wie zb. Messdaten besorgen und aufbereiten.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.