sätta A0 utan att sätta hela port A

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
ekj
Inlägg: 22
Blev medlem: 26 juli 2007, 19:20:57
Ort: Göteborg

sätta A0 utan att sätta hela port A

Inlägg av ekj »

Hur gör man i C/C++ för att sätta bitarna individuellt på en port på en AVR Mega-uC? Om de olika bitarna används till olika saker vore det ju bättre att styra dom individuellt än att behöva sätta ett värde på hela porten varje gång en av bitarna ska ändras.

Säg att bit 0 styr en LED, Hur ska min kodrad se ut för att sätta på LED:en isf?

Jag hittade ett kodexempel där det såg ut som att man kunde skriva så här:

Kod: Markera allt

PORTA.0=1;
Men då får jag detta felmeddelandet när jag kompilerar:

Kod: Markera allt

test.cpp:12: error: expected `;' before numeric constant
Däremot går det bra att skriva "PORTA=1;", men då måste jag ju hålla koll på de andra 7 bitarna också...

Vad gör jag för fel?


EDIT:
Så här ser hela koden ut:

Kod: Markera allt

#include <avr/io.h>
#include <util/delay.h>

void delay(void);

int main(void){
  DDRA = 255;    // Port A sätts till output
  PORTA = 0;     // Port A sätts till 0
  delay();

  while(1<2){
    PORTA.0 = 1; // sätt på lysdioden
    delay();     // vänta
    PORTA.0 = 0; // stäng av lysdioden
    delay();     // vänta 
  } 
  return 0;
}

void delay(){
    _delay_ms(200.0); // pausar i 200 ms
}
Senast redigerad av ekj 22 januari 2008, 21:31:53, redigerad totalt 1 gång.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Titta några trådar ner eller i databladet.

Kod: Markera allt

#include <avr/io.h>
#include <util/delay.h>

void delay(void);

int main(void){
  DDRA = 255;    // Port A sätts till output
  PORTA = 0;     // Port A sätts till 0
  delay();

  while(1){
    PORTA |= (1<<PA0);  // sätt på lysdioden
    delay();               // vänta
    PORTA &= ~(1<<PA0);  // stäng av lysdioden
    delay();              // vänta 
  } 
  return 0;
}

void delay(){
    _delay_ms(200.0); // pausar i 200 ms
}
zebs
Inlägg: 36
Blev medlem: 5 mars 2008, 22:55:07
Ort: Norrköping

Inlägg av zebs »

Kör du win-avr? Det har inte stöd för det kommandot (tex PORTB.0=1) eftersom det tydligen inte är ett giltigt C-syntax.. men det finns andra kompilatorer som har stöd för kommandot om man hellre vill använda dom....
ekj
Inlägg: 22
Blev medlem: 26 juli 2007, 19:20:57
Ort: Göteborg

Inlägg av ekj »

Nej, jag kör linux, så jag använder avr-gcc

Jag använder tipset som thepirateboy kom med, det fungerar utmärkt. Men det är klart, det hade varit smidigare att kunna skriva PORTA.0.
Användarvisningsbild
Icecap
Inlägg: 26632
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Det kan göras faktisk...

Det kräver att man "fuskar" lite och detta är tagit ur minnet som kan vara lite rostigt:

Kod: Markera allt

#ifndef BYTE
typedef unsigned char BYTE; // Defines BYTE if it's not already done
#endif

struct
  {
  BYTE P0 : 1;
  BYTE P1 : 1;
  BYTE P2 : 1;
  BYTE P3 : 1;
  BYTE P4 : 1;
  BYTE P5 : 1;
  BYTE P6 : 1;
  BYTE P7 : 1;
  } MyPortA = PORTA;
Pp detta vis bör MyPortA sättas till samma adress som PORTA och du kan då adressera med "MyPortA.P0" osv.

Det är inte säkert att du kan tvinga "MyPortA"s adress på detta sätt men du kan ju testa. En sak MÅSTE du ha klart för dig: den "nya" portdefinitionen får INTE heta det samma som originalet, den MÅSTE heta (lite) annorlunda.
PORTAX kan vara ett lämpligt namn, PortA, PortA_Bit eller annat lämpligt.
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Inlägg av Stinrew »

Då kan du t.ex. skriva:

Kod: Markera allt

PORTA |= 0b00000001;
    Vilket är detsamma som:
    PORTA = PORTA | 0b00000001;
    Vill du slippa hålla koll på vilken bit som du sätter in gör du så här:
    PORTA |= (1<<x);     //x bytes ut mot bitposition(0-7)
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Man kan använda struct,
exempel:

Kod: Markera allt

#include <AVR/io.h>
#include <stdint.h>
#include <util/delay.h>

struct bits{
	uint8_t P0 : 1;
	uint8_t P1 : 1;
	uint8_t P2 : 1;
	uint8_t P3 : 1;
	uint8_t P4 : 1;
	uint8_t P5 : 1;
	uint8_t P6 : 1;
	uint8_t P7 : 1;
};

#define port_test (*(volatile struct bits *)  &(PORTB))

#define delay() _delay_ms(200.0)

int main(void){
  DDRB = 255;    // Port A sätts till output
  PORTB = 0;     // Port A sätts till 0

  delay();

  while(1){
    delay();               // vänta
	port_test.P0 = 0;
    delay();              // vänta 
	port_test.P0 = 1;
  } 
}
Men det blir inte riktigt likt som andra "kompilatorer", då port_test inte går att "addressera" direkt ( dvs port_test = ett_värde vilket inte fungerar)

Att lösa det problemet tror jag inte att det går tyvärr...

Annars är |,& och mm att "föredra" då de är lite av standard på AVR. ^^
Användarvisningsbild
MrFreeze
Inlägg: 72
Blev medlem: 23 november 2005, 22:15:02

Inlägg av MrFreeze »

BYTE P0 : 1;
uint8_t P0 : 1;
unsigned int P0:1;

etc är samma sak, en 'int' 1 bit lång så det är ju perfekt när man vill adressera bitwise (detta funkar även för typ 2 ellet 7 bits : int a:2; int b:7; )

Vad man får akta sej för (eller som man kan ha i bakhuvudet i allafall om det blir mystiska fel) är att ibland så vill kompilatorn euh, aligne(sorry
för engelskan) alltså sätta varje nästa ny variabel på en ny Byte/Short/32bitars gräns/...

Man kan tvinga(vilket borde funka för alla kända c/c++ compilatorer)) kompilatorn att inte göra detta genom att använda kommandot "packed" :

Från ett google exempel för gcc :

struct test_t
{
int P0:1;
int P1:1;
int P2:1;
// ...
} __attribute__((__packed__));


/Ludde
SmourF
Inlägg: 268
Blev medlem: 13 april 2004, 15:33:58
Ort: Jönköping
Kontakt:

Inlägg av SmourF »

nu är jag ju inte så insatt i AVR :)

men i C brukar de vara lite knepigt, speciellt om compilatorn inte stödjer RA0 = 1

då får man maska/ora på ngt sätt, beroende på vad man vill åstadkomma

typ, PORTA = PORTA "bitviss or" 0b00000001 (om du vill sätta biten och övriga orörda)

PORTA = PORTA "bitviss and" 0b11111110 (om du vill cleara biten och övriga orörda)

hehe, så brukar vi göra om de inte finns annat sätt, men som sagt, jag kan icke AVR, men i C borde de va samma :)

hade gott

MVH
Skriv svar