Skriva till portregistret på en PIC

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Skriva till portregistret på en PIC

Inlägg av lillahuset »

Grubbla inte för mycket. Alla pinnar som är definierade (via TRIS) som utgångar påverkas av skrivning. Pinnar som är definierade (via TRIS) som ingångar påverkas inte av skrivning.

Sätt dig ner och studera schemat så kommer du att komma till klarhet.
Mr Andersson
Inlägg: 1409
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Skriva till portregistret på en PIC

Inlägg av Mr Andersson »

> PORTC &= ~(0b01110111);, är inte det här exakt samma sak som att direkt skriva PORTC &= 0b10001000);, dvs man inverterar samtliga bitar?
> Sen tycker jag det här var klurigt: PORTC &= !(0b01110111);. Hur blir det egentligen? Blir det inte logiskt samma som ovan? Dvs man inverterar alla bitar? Väldigt intressant det här!

~ är bitvis NOT, dvs invertering. Helt rätt där.
! är logisk NOT. 0 blir 1, allt annat blir 0. Notera att vi pratar heltal här och inte individuella bitar. PORTC &= !(0b01110111); är samma sak som PORTC &= 0;
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva till portregistret på en PIC

Inlägg av Magnus_K »

Ahaaa, då hänger jag med. Tack för det Mr Andersson :tumupp:
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46963
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Skriva till portregistret på en PIC

Inlägg av TomasL »

När det gäller IO-portar och att hantera individuella bitar, så skall man vara medveten om RMW problemet.

Man kan väldigt lätt få konstigheter annars.
Bästa sättet att hantera det är att använda ett "skuggregister", manipulera det och sedan kopiera hela "skuggregistret" till porten.

Dock om man använder de avsedda makrona för att skriva till portarna, så skapas "skuggregistren" per automatik.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46963
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Skriva till portregistret på en PIC

Inlägg av TomasL »

Och nu kommer lite förklaringar.
Man skall aldrig manipulera en IO-port direkt.
Generellt gäller:
Man skall bara läsa en PORT, skrivning och manipulation skall alltid gå via LAT om det finns eller via skuggregister.

Orsaken är, om man skall sätta enskilda bitar på en port, så kommer det att utföras en RMW instruktion, det är inte absolut säkert att man läser tillbaka det man tror att man skall läsa. Detta eftersom man läser av spänningsnivåerna på portpinnarna och under vissa förutsättningar så kan spänningen på portpinnarna vara för låga för att registrera en etta.
Ponera följande:
Vid en tidigare skrivning så har man satt pinnarna enligt följande 10101010.
Dock så är det av någon anledning så att exvis utgången för bit3 belastas hårt, vilket gör att spänningen på portpinnen faller under gränsen för att tolkas som en etta.
Nu vill man sätta bit 6 till en etta, vad som händer då är att porten läses tillbaka biten manipuleras och det hela skrivs tillbaka till porten.
Men, eftersom bit 3 är hårt belastad så kommer man att läsa tillbaka 10100010 i stället för det avsedda 10101010, och när då slutresultatet blir skrivet till porten blir det 11100010 i stället för det man trodde sig ha 11101010.

Detta fenomen kan också uppstå om man har en kapacitiv last på portpinnen

För att råda bot på detta skriver man till LAT-registren i stället, och om de inte finns till ett skuggregister vilket sedan i sin helhet skrivs till porten.


Så för att skriva till en port använder man:

LATA &= ~BITFIELD;
LATA |= BITFIELD;
eller
portAShadow&= ~BITFIELD;
portAShadow|= BITFIELD;

PORTA = portAShadow;
Användarvisningsbild
ecenier
Inlägg: 1150
Blev medlem: 13 december 2007, 17:51:42
Ort: Älvsjö
Kontakt:

Re: Skriva till portregistret på en PIC

Inlägg av ecenier »

Tack TomasL. Mycket bra beskrivet!



Sent using Tapatalk
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva till portregistret på en PIC

Inlägg av Magnus_K »

Ja, bra beskrivning och tror faktiskt det har varit på tal tidigare :humm:
TomasL skrev:Dock om man använder de avsedda makrona för att skriva till portarna, så skapas "skuggregistren" per automatik.
Vilka är dom avsedda makrona?
Sen hittar jag varken något om LAT eller shadow i databladet för 16F690 så där kanske man inte kan göra så mycket mer än att skriva direkt till PORT-registren?
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Skriva till portregistret på en PIC

Inlägg av lillahuset »

Skapa bara en variabel för porten, typ mk_porta och gör operationen på den och kopiera sedan till porten.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva till portregistret på en PIC

Inlägg av Magnus_K »

Ah, då förstår jag, tack! :tumupp:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Skriva till portregistret på en PIC

Inlägg av sodjan »

> Sen hittar jag varken något om LAT eller shadow i databladet för 16F690...

LAT är internt i F690 (inte synligt från programkoden).
"Shadow" är bara ett begrepp för ett temporärt register som man
gör bitoperationer till och sen skriver hela till PORT registret...

Hur som helst, inget av detta har egentligen något direkt med din
ursprungliga fråga att göra. Svaret på det har du fått, det är inget
problem att skriva till hela PORT registret även om några pinnar
är satta som ingångar.
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Skriva till portregistret på en PIC

Inlägg av lillahuset »

Just det.
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1353
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: Skriva till portregistret på en PIC

Inlägg av baron3d »

En bra regel är att bara läsa och skriva till IO endast en gång.
T.ex.

Kod: Markera allt

int main(void) {
	unsigned char in_uc;
	unsigned char ut_uc;
	
	while(1) {
		in_uc = PortB; // läs ingångar
	
		// diverse kod


		PortC = ut_uc; // skriv till utgångar		
	}
}
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva till portregistret på en PIC

Inlägg av Magnus_K »

Är inte det så en PLC jobbar? Läs alla ingångar, modifiera, skriv alla utgångar?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Skriva till portregistret på en PIC

Inlägg av sodjan »

Så kan det nog vara, det ger en bättre "sync" mellan olika
utgångar, och alla ingångar läses av vid samma tidpunkt.
Kan minska risken för olika "race conditions".
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46963
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Skriva till portregistret på en PIC

Inlägg av TomasL »

Magnus_K skrev:Vilka är dom avsedda makrona?
Sen hittar jag varken något om LAT eller shadow i databladet för 16F690 så där kanske man inte kan göra så mycket mer än att skriva direkt till PORT-registren?
Makrona är de som är beskrivna i ditt IDE, för PIC32 är det till exempel:
PORTSetBits(IOPORT_A, BIT_2 | BIT_4);
Du hittar dessa i hjälpen under PLIB troligen.

EN del processorer saknar LAT-registren, uppenbarligen är din processor en av dem. och då får du använda shadow-register i stället, dvs en variabel som du skapar.

En fördel med att bara skriva/läsa portarna på specifika platser är för att det är lättare att ha kontroll på det också.

Så, för att sammanfatta;

Skapa x antal variabler för de portar som fungerar som ingångar.
Om bara delar av en port används som ingång, skapa en mask för dessa, till exempel :
#define PORTA_INPUTMASK 0x1111000 // bit 4 till 7 används som ingångar.
När du läst av porten kan du maska bort de pinnar om är utgångar genom att "OCHa" det inlästa värdet med masken, blir lite tydligare då.
Skapa en funktion som läser ingångarna, denna funktion skall bara läsa och eventuellt hantera avstudsning.

Skapa x antal variabler för dina utgångar, samma här skapa en mask för de pinnar som används, i masken skall utgångarna vara ettor.
skapa en funktion som skriver till dina portar efter avmaskning..


Dessa två funktioner anropar du nu från ditt programs huvudloop, till exempel:
ReadPorts(); i början av loopen,
och
WritePorts(); i slutet av loopen.


Ett annat tips, vilket inte har ett dugg att göra med ämnet.
Om du använder PIC32, så deklarera lokala räknarvariabler som "register uint32", då läggs de i ett av CPUns register i stället för i RAM, går mycket fortare och du sparar lite RAM.
Skriv svar