AVR-GCC - C, typer, bit operationer

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
rickeboy
Inlägg: 678
Blev medlem: 13 augusti 2003, 09:12:17
Ort: Göteborg / Karlskrona
Kontakt:

AVR-GCC - C, typer, bit operationer

Inlägg av rickeboy »

Hoj... är vann vid C/C++ men har nu hållt på med avr-gcc etc och jag är lite fundersam över hur man egentligen ska skriva... detta är dock första frågan: det jag undrar är hur det är tänkt att man ska göra variabler t ex char:s etc...

t ex hur många bit:ar får jag när jag skriver detta?

Kod: Markera allt

char hej;
eller detta:

Kod: Markera allt

unsigned char hej;
Jag har kollat i avr-libc manualen och fått fram att man ska använda uint8_t grejorna om man vill ha 8:a bit:ar, uint16_t för 16:on bit:ar etc... hur är det tänkt att man ska använda dem då?
Har sett i andra program och själv gjort så här men förstår inte varför jag ska göra så eller hur det är tänkt att man ska göra, skulle vilja ha klarhet i att.

Kod: Markera allt

typedef unsigned char uint8_t;   

int main(void) {
register unsigned char hej;
}
Blir alla char:s i uint8_t stil nu eller?

Sen angående det här med _BV(); macrot/funktionen som man använder för att ändra bit:ar/register/portar etc med. Det jag funderar över är helt enkelt hur man vet vad man ska ha innan. För nu kollar jag på en förklaring Cykze skrev i tråden "Lite frågor ang. AVR". Där han skrev några förklaringar vad olika tecken gjorde.
t ex

Kod: Markera allt

PORTB ^= _BV(PB3);
Men hur vet man att det ska vara "^= "? Kollade i en bra PDF för att få klarhet i operatorerna men fick inte mkt insikt av det heller. EssentialC slutet av sidan 9 : o / början av sidan 10...

Hur vet man? Eller snarare var har ni hittat hur man gör dessa två viktiga och ganska grundläggande AVR-C saker? I vanliga C/C++ program behöver man ju i stort sett aldrig ge sig in på såna här saker, däför man inte heller har ngn erfarenhet av att heller...

//Rille
Användarvisningsbild
strombom
Inlägg: 3305
Blev medlem: 27 maj 2003, 10:50:20
Ort: Västra Götaland
Kontakt:

Inlägg av strombom »

jag använder bara uint8_t och uint16_t, det kanske går att skriva char men det känns lika bra att använda uint8_t...

de logiska operatorerna ska vara samma i gcc som i andra c-kompilatorer, annars vore det väl konstigt... o_O

det stod ju bra beskrivet i ditt dokument:

! Boolean not (unary)
&& Boolean and
|| Boolean or
~ Bitwise Negation (unary) flip 0 to 1 and 1 to 0 throughout
& Bitwise And
| Bitwise Or
^ Bitwise Exclusive Or
+=, -= Increment or decrement by RHS
*=, /= Multiply or divide by RHS
%= Mod by RHS
>>= Bitwise right shift by RHS (divide by power of 2)
<<= Bitwise left shift RHS (multiply by power of 2)
&=, |=, ^= Bitwise and, or, xor by RHS

/Johan
sprawl
Inlägg: 299
Blev medlem: 9 juni 2004, 13:01:33
Ort: Göteborg

Inlägg av sprawl »

typedef unsigned char uint8_t;

betyder att du skapar en ny typ med namnet uint8_t som är samma som en unsigned char;

en char i c/c++ (om du inte använder unicode?) är 1 byte (8 bitar).

men på olika plattformar så kan tex int bestå av olika antal bitar (16, 32, 64) för att gardera sig så är det lämpligt att använda uint32_t om man vill ha en 32 bitars integer. Sen så får man i en header fil skapa typedefs för dessa nya typer. Dock så brukar det "följa" med ett gäng.

Lite svårt att förklara, jag är en whiteboard människa så jag behöver en sådan för att kunna förklara något :)

/a
Användarvisningsbild
rickeboy
Inlägg: 678
Blev medlem: 13 augusti 2003, 09:12:17
Ort: Göteborg / Karlskrona
Kontakt:

Inlägg av rickeboy »

strombom skrev:jag använder bara uint8_t och uint16_t, det kanske går att skriva char men det känns lika bra att använda uint8_t...
Förstår att nu... dvs man kan lika gärna skriva uint8_t hej; istället för t ex char hej; etc

Jo visst är de logiska operatorerna samma... MEN ( ;) ) grejen är att jag inte lyckas förstå det riktigt... tror det släppte nu dock... hmm...
"Hela PORTD ska vara noll förutom PD5" ==>> PORTD = _BV(PD5);
"Enbart PD5 ska ändra värde" ==>> PORTD |= _BV(PD5);
Dvs PORTD är lika med "Bitwise Or" PD5. dvs den rör bara biten PD5... am I right?

Men vad menar de med "Or":et i Bitwise då? T ex...

sprawl>> Hmm... bra förklaring på "typedef" och det... det blev dock lite själv förklarat när jag kom på det anda... dvs att uint8_t är en TYP... :)

Tack för insikten... om ngn har ytterligare ngt som kan hjälpa till var vänlig att skriv ett svar :)

//Rille
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

char brukar vara "signed 8-bitar" i vanliga fall. Hur det är med AVR-GCC vet jag inte. Men använd som sagt uint8_t, int8_t, uint16_t, int16_t osv istället.

I förklaringen här nedan antar jag att det är PORTB som ska ändras i. Och alla tal är i binär form.

Kod: Markera allt

OR:
1 om minst en bit är 1

  00101000   - PORTB
| 00000010   - _BV(PB1)
----------
  00101010   - Resultatet
Det nya talet blir alltså lika dant som det första (PORTB). Den enda skillnaden är att bit 1 har tillkommit. Det är därför man kan skriva:
PORTB = PORTB | _BV(PB1); //samma som PORTB |= _BV(PB1)
för att sätta en bit utan att påverka de andra bitarna.

Kod: Markera allt

AND:
1 om båda bitarna är 1

  00101000   - PORTB
& 00000010   - _BV(PB1)
----------
  00000000   - Resultatet (falskt)

  00101010   - PORTB
& 00000010   - _BV(PB1)
----------
  00000010   - Resultatet (sant)
AND används främst för att kolla om en bit är satt eller inte.
Ex:
if (PORTB & _BV(PB1))
//PB1 är satt
else
//PB1 är inte satt

Kod: Markera allt

XOR:
1 om och endast om den ena biten är 1 och den andra 0


  00101000   - PORTB
^ 00000010   - _BV(PB1)
----------
  00101010   - Resultatet

  00101010   - PORTB
^ 00000010   - _BV(PB1)
----------
  00101000   - Resultatet
Som synes kommer PB1 växla mellan 1 och 0 varje gång man kör den genom XOR.

Kod: Markera allt

Komplentet(?):
0:or blir 1:or och 1:or blir nollor

~ 00000010   - _BV(PB1)
----------
  11111101   - Resultatet

Kör vi AND på resultatet blir det så här:

  00101010   - PORTB
& 11111101   - _BV(PB1)
----------
  00101000   - Resultatet
Bit PB1 försvinner alltså. Jämför med PORTB = PORTB & (~_BV(PB1))
frejo
Inlägg: 496
Blev medlem: 21 april 2004, 21:43:01
Ort: Linköping

Inlägg av frejo »

Sidan 101 i avr-libc-user-manual-1.0.3.pdf

Data types:
char is 8 bits, int is 16 bits, long is 32 bits, long long is 64 bits, float
double are 32 bits (this is the only supported floating point format), pointers
are 16 bits (function pointers are word addresses, to allow addressing the whole
128K program memory space on the ATmega devices with > 64 KB of flash
ROM). There is a -mint8 option (see Options for the C compiler avr-gcc)
make int 8 bits, but that is not supported by avr-libc and violates C standards
(int must be at least 16 bits). It may be removed in a future release.

Sidan 34

Use intN t if you need exactly N bits.
Since these typedefs are mandated by the C99 standard, they are preferred over
your own typedefs.
Note:
If avr-gccs -mint8 option is used, no 32-bit types will be available.


Hoppas det hjälpte.
Skriv svar