Bit-Typ für die AVR-Mikrocontroller-Programmierung

7

Ich habe einen Code für den 8051-Mikrocontroller geschrieben, in dem ich den Bittyp verwendet habe, ungefähr so:

static bit done_flag = 0;    /* bit variable */

bit testfunc (               /* bit function */
  bit flag1,                 /* bit arguments */
  bit flag2)
{
.
.
.
return (0);                  /* bit return value */
}

Jetzt portiere ich dies auf den ATmega16 AVR-Controller. Ich habe festgestellt, dass der
Bittyp in AVR nicht unterstützt wird .

Das AVR-lib C-Benutzerhandbuch lautet:

Datentypen: char ist 8 Bit, int ist 16 Bit, long ist 32 Bit, long ist 64 Bit, float und double sind 32 Bit (dies ist das einzige unterstützte Gleitkommaformat), Zeiger sind 16 Bit (Funktionszeiger sind Wortadressen, um die Adressierung von bis zu 128 KB Programmspeicherplatz zu ermöglichen). Es gibt eine Option -mint8 (siehe Optionen für den C-Compiler avr-gcc), um int 8 Bit zu erstellen. Diese Option wird jedoch von avr-libc nicht unterstützt und verstößt gegen C-Standards (int muss mindestens 16 Bit betragen). Es kann in einer zukünftigen Version entfernt werden.

Was soll ich jetzt machen?

gpuguy
quelle
Sie können einen boolDatentyp verwenden, aber ich denke, dass dieser immer noch als Byte gespeichert wird, da sind Sie sich nicht 100% sicher.
PeterJ
@PeterJ Ist der boolesche Bitpacking-Compiler nicht abhängig?
Anindo Ghosh
@AnindoGhosh Ja, die Frage ist mit avr-gcc gekennzeichnet und ich glaube nicht, dass sie gepackt werden. Die ältere Version hat dies nicht getan, aber ich bin mir nicht sicher über die neuesten Versionen.
PeterJ
@ PeterJ Es war keine Kritik, nur Neugier :-)
Anindo Ghosh

Antworten:

4

Sie können eine Struktur wie diese verwenden:

typedef struct {
    uint8_t bit0:1;
    uint8_t bit1:1;
    uint8_t bit2:1;
    uint8_t bit3:1;
    uint8_t bit4:1;
    uint8_t bit5:1;
    uint8_t bit6:1;
    uint8_t bit7:1;
} BitField;

typedef union {
    BitField asBits;
    uint8_t asByte;
} BitByte;

BitByte mBitField; 

Und um auf ein Bit auf einmal zuzugreifen, müssen Sie nur

mBitField.asBits.bit3 = 1
Naeriel
quelle
3
Verwenden Sie dies mit Vorsicht. Ein mir bekannter Compiler erzeugt sehr ineffizienten Code für die Bitfeldmanipulation (viele Links- und Rechtsverschiebungen, bei denen eine einfache Maskierung und Prüfung möglich gewesen wäre).
MikeJ-UK
Welcher Compiler? Nur zu wissen.
Naeriel
Der Keil C51-Compiler - obwohl es ohnehin kein Problem ist, wenn zeitkritischer Code in Assembler geschrieben wird.
MikeJ-UK
2
@Naeriel: Compiler haben im Allgemeinen eine schlechte Leistung mit Bitfeldern, außer in Fällen, in denen die Hardware helfen kann und der Compiler davon weiß. Compiler-Anbieter konzentrieren sich im Allgemeinen auf die Optimierung von Mustern, die wahrscheinlich von Programmierern verwendet werden, die eine gute Leistung suchen. Leute, die eine gute Leistung auf dem 8x51 suchen, werden die bitoder bdataLeerzeichen verwenden; Da Bitfelder nicht so gut funktionieren können, haben die Compiler-Autoren möglicherweise nicht gedacht, dass ihre Optimierung Priorität hat.
Supercat
2
Das letzte Mal, als ich avr-gcc überprüft habe, war es auch nicht gut, Bitfelder zu optimieren. Hinweis: Wenn Sie genug RAM für mehrere bools anstelle eines Bitfelds haben, verwenden Sie bools. Wenn Sie diese Bits stattdessen zu „Pack“ wollen und beste Leistung wollen, sollten Sie „handmade“ diejenigen, zB über #defines: #define MY_BIT_VALUE_1 _BV(0) #define MY_OTHER_BIT_VALUE _BV(1) ...innerhalb einer einzigen gespeicherten uint8_tVariablen.
JimmyB
3

Wie PeterJ bereits in seinem Kommentar erwähnt hat, würde ich die Verwendung vorschlagen bool.

Sie müssen die stdbool-Bibliothek einschließen.

#include <stdbool.h>

Wie bereits erwähnt, handelt es sich bei AVRGCC boolum 8-Bit und nur um eine Abstraktion von a uint8_t. Wenn Sie damit nicht leben können und jedes einzelne Bit speichern müssen oder Tonnen von globalen "Ja / Nein" -Flaggen haben (was auf eine schlechte Codierungspraxis hinweisen könnte), können Sie überlegen, was Naeriel in seiner Antwort gepostet hat.

Die Verwendung von bool und der richtigen Benennung von Variablen (unter Verwendung des "is" -Präfix) führt jedoch zu viel saubererem Code. Zum Beispiel verwenden

bool IsOperationCompleted;

anstelle von "done_flag". Dieser Weg ist für jemanden offensichtlicher, der den Code nicht kennt, was genau der Zustand signalisiert.

Rev1.0
quelle
0

Verwenden Sie stattdessen vorzeichenloses Zeichen . Dies verwendet jedoch ein ganzes Byte anstelle eines Bits.

Mäuse
quelle
also anstelle des statischen Bits done_flag = 0;, wenn ich statisches vorzeichenloses Zeichen mache done_flag = 0; sollte es kein problem geben (vorausgesetzt ich habe genügend speicher)?
Gpuguy
Ja. Bitte beachten Sie, dass für den bedingten Vergleich 0 falsch ist und alles, was nicht Null ist, wahr ist. Also, wenn (done_flag) {do_mores_tuff ();} vollständig gültig ist
Mäuse
0

Sie können so etwas verwenden:

#define bit_get(p,m) ((p)&(m)) #define bit_set(p,m) ((p)|=(m)) #define bit_clear(p,m) ((p)&=~(m)) #define BIT(x) (0x01<<(x))

Anwendungsbeispiel:

bit_set(DDRB,BIT(4))

setzt PB4 als Ausgangspin.

Quelle: http://www.avrfreaks.net/

Adithya
quelle