Sida 1 av 1
[PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 20:23:46
av Klas-Kenny
Hej!
Jag är ny med att programmera PIC, och skulle i det jag kodar behöva invertera bitar för att få koden mindre, enklare och snyggare, finns detta?
Just nu har jag
Kod: Markera allt
movlw b'00001001'
movwf PORTC
;Lite annan kod
movlw b'11110110'
movwf PORTC
;mera kod
Vilket jag tycker är fult, så om jag enkelt kunde ha en variabel med det som ska till PORTC och kunde invertera den skulle allt bli mycket enklare.
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 20:25:25
av victor_passe
Xor med 255 inverterar.
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 20:43:21
av Icecap
Kod: Markera allt
.define VALUE_1 b'00001001'
.define VALUE_1_INV (255-VALUE_1 )
movlw VALUE_1
movwf PORTC
;Lite annan kod
movlw VALUE_1_INV
movwf PORTC
kanske?
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 21:20:15
av bos
Varför krångla med xor och manuell uträkning när det finns en mnemonic för att invertera?
Kod: Markera allt
foo res 1
...
movlw b'00001001'
movwf foo ; spara talet '00001001' i variabeln "foo"
comf foo, f ; invertera "foo"
movfw foo ; w innehåller nu '11110110'
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 21:27:04
av Klas-Kenny
bos: Tack! där kom exakt vad jag ville ha!

Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 21:28:27
av Icecap
bos: dels för att det inte klart framgick att sekvensen skulle vara utan undantag och även ur R-M-W-synpunkt, det kan ju ibland bli ...intressant... om en portpinne är belastat så att den läsas som motsatsen av vad den egentligen är, då blir resultatet fel helt enkelt.
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 21:30:50
av bos
Det framgick rätt klart tycker jag: "...om jag enkelt kunde ha en variabel med det som ska till PORTC och kunde invertera den skulle allt bli mycket enklare". Inga RMW-problem där.
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 22:06:54
av jesse
Jag skulle nog ändå valt icecaps version.
Med en invertering av det tillfälliga tillståndet på porten riskerar man att man t.ex. råkar invertera två gånger och därmed få fel. Att mata ut en konstant som är fördefinierad känns tryggare - även med tanke på belastning på pinnen, och gör dessutom programmet mer lättläst.
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 22:17:41
av bos
Konstigt resonemang.
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 22:28:41
av Icecap
Jag förstår att du aldrig har suttit och svurit över att det inte fungerar och man sedan efter MÅNGA svordomar hittar den konstant som skulle ha varit ändrat men inte blev det då den blev översett när man ändrade de andra.
Jag har konsekvent ingen konstant i programmet, de definieras alltid på lämpligt sätt och sedan används namnet hela vägen, detta ger i övrigt också ett enklare program att läsa!
Så du kanske tycker att det är ett konstigt resonemang men du har då nog inte suttit i klistret ordentligt heller...
Om man sedan enbart behöver invertera data kan man fint göra det med ett kommando men "originalvärdet" definierar jag alltid!
Re: [PIC]Assembly - Invertera data?
Postat: 27 juni 2010, 23:32:38
av sodjan
Alltså...
Grundproblemet här är att det inte tydligt framgår av förstainlägget om det är en
fast konstant som ska inverteras eller om det är ett godtyckligt värde. Metoden
blir ju helt annorlunda beroende på vilket det är.
Om vi antar att det är ett visst fast värde så är ju bos kodexempel lite galet
eftersom det helt i onödan använder ett GPR i processorn ("foo") för att hålla en konstant.
Så gör man inte (utan att ha en väldigt bra anledning till det). Icecaps version är
mycket bättre och använder assembly-time variabler för att hålla de två olika
värderna. Inga bortkastade register i onödan, så att säga.
Om det däremot inte är klart redan vid assembly-time vilket värde det handlar om
så blir det en helt annan fråga, och där fungerar (t.ex) COMF. Sen så måste man ju
inte göra det mot ett PORTx register så R-M-W är en helt annan diskussion och har
igentligen inte med grundfrågan att göra.
Så kärnfrågan är, handlar det om en fast "konstant" som aldrig kommer att ändras
under run-time eller är det faktiskt en "variabel" ?? Utan ett tydligt svar på det så
går det inte att svara entydigt på frågan.
Re: [PIC]Assembly - Invertera data?
Postat: 28 juni 2010, 00:57:57
av Klas-Kenny
Sodjan:
Egentligen skulle man nog kunna säga att det är en konstant, som bara ska vara "original" eller inverterad.
För att förklara mig lite kan jag säga att det inte är något vettigt egentligen, utan det är bara lite lek för att lära, att tända fyra LED i ett visst mönster:
1001
0110
1001
osv.
Så för att lösa detta snyggt ville jag bara toggla mellan de två olika lägena, istället för att först köra det ena, sen en delay, sen den andra, sen en delay igen, och sedan börja om från början.
Smidigare att bara toggla, delay, börja om.
Icecaps version körde jag först (Fast skrev in värdena direkt i koden istället för konstanter) , men ville som sagt lösa det snyggare. (Kodmässigt i alla fall, prestanda vet jag inte

)
Re: [PIC]Assembly - Invertera data?
Postat: 28 juni 2010, 08:26:58
av sodjan
> (Fast skrev in värdena direkt i koden istället för konstanter)
Och det har du fått svar på att det (helt rätt) är en dålig metod.
Sätt upp dina konstanter på ett ställe som är lätt att hitta tillbaka till
och använd symbolerna i koden.
> Smidigare att bara toggla, delay, börja om.
Visst, det bör gå lika bra att bara sätta upp ett värde som en symbol
och sedan invertera det vid behov senare i koden. Om du läser direkt
från PORTx och inverterar värdet så bör du vara medveten om R-M-W
problematiken, även om det sannolikt inte är något problem i fallet
med 8 st LEDs på alla pinnar.
Re: [PIC]Assembly - Invertera data?
Postat: 28 juni 2010, 09:27:48
av Icecap
För att anknyta till detta att definiera ett värde med namn och sedan konsekvent använda detta.
Ett projekt styr bland en del annat ett 7-segment LED-display med 3 siffror. Såklart ska det kunde visas " 0"-"999" men även lite annat (t.ex. "Err", "FAb" osv). De 3 siffror är scannade men jag definierade först (programmerar i C):
// A '0' turns on the segment
#define SEG_A 0xDF // 11011111
#define SEG_B 0xEF // 11101111
#define SEG_C 0x7F // 01111111
#define SEG_D 0xFD // 11111101
#define SEG_E 0xFB // 11111011
#define SEG_F 0xF7 // 11110111
#define SEG_G 0xBF // 10111111
#define SEG_DP 0xFE // 11111110
#define SEG_OFF 0xFF // 11111111
Sedan kom definitionerna på varje tecken:
#define DSP_DEF_0 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) // '0'
#define DSP_DEF_1 ( SEG_B & SEG_C) // '1'
#define DSP_DEF_2 (SEG_A & SEG_B & SEG_D & SEG_E & SEG_G) // '2'
#define DSP_DEF_3 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_G) // '3'
#define DSP_DEF_4 ( SEG_B & SEG_C & SEG_F & SEG_G) // '4'
#define DSP_DEF_5 (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) // '5'
#define DSP_DEF_6 (SEG_A & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) // '6'
#define DSP_DEF_7 (SEG_A & SEG_B & SEG_C) // '7'
#define DSP_DEF_8 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) // '8'
#define DSP_DEF_9 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_F & SEG_G) // '9'
#define DSP_DEF_A (SEG_A & SEG_B & SEG_C & SEG_E & SEG_F & SEG_G) // 'A'
#define DSP_DEF_B ( SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) // 'b'
#define DSP_DEF_C (SEG_A & SEG_D & SEG_E & SEG_F) // 'C'
#define DSP_DEF_d ( SEG_B & SEG_C & SEG_D & SEG_E & SEG_G) // 'd'
#define DSP_DEF_E (SEG_A & SEG_D & SEG_E & SEG_F & SEG_G) // 'E'
#define DSP_DEF_F (SEG_A & SEG_E & SEG_F & SEG_G) // 'F'
#define DSP_DEF_H (SEG_B & SEG_C & SEG_E & SEG_F & SEG_G) // 'H'
#define DSP_DEF_I ( SEG_B & SEG_C) // 'I'
#define DSP_DEF_J ( SEG_B & SEG_C & SEG_D & SEG_E) // 'J'
#define DSP_DEF_L ( SEG_D & SEG_E & SEG_F) // 'L'
#define DSP_DEF_n ( SEG_C & SEG_E & SEG_G) // 'n'
#define DSP_DEF_O (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) // 'O'
#define DSP_DEF_o ( SEG_C & SEG_D & SEG_E & SEG_G) // 'o'
#define DSP_DEF_P (SEG_A & SEG_B & SEG_E & SEG_F & SEG_G) // 'P'
#define DSP_DEF_R ( SEG_E & SEG_G) // 'r'
#define DSP_DEF_S (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) // 'S'
#define DSP_DEF_U ( SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) // 'U'
#define DSP_DEF_u ( SEG_C & SEG_D & SEG_E) // 'u'
#define DSP_DEF_Y ( SEG_B & SEG_C & SEG_D & SEG_F & SEG_G) // 'y'
#define DSP_DEF_QM (SEG_A & SEG_B & SEG_E & SEG_G & SEG_DP) // '?'
#define DSP_DEF_DS ( SEG_G) // '-'
#define DSP_DEF_SP (SEG_OFF) // ' '
Alla dessa definitioner tar inte minnesplats! De finns enbart i kompilern än så länge men nu kan jag använda dessa värden som värden i hela programmet och skulle jag ha klantat mig och kastat om på ett par segment räcker det med att jag definierar rätt i de första definitioner, alla andra värden blir då korrekta vid den efterföljande kompilering.
Och vilken är enklast att förstå när man läser det?
MOVLW 0b01101111 (eller 0x6F)
kontra
MOVLW DSP_DEF_1
Jag vill påstå att den senare är mer tydlig, man kan även välja namn som är mer tydliga om man vill.
Som regel anser jag att ett värde ska vara beskrivit EN gång och alla delar som använder detta värde ska referera till denna definition, efter att ha suttit med laptopen vid ett skylt vid E4'an i Bureå till 04:37 och haft chefen att sova i bilen under tiden jag programmerade som en blådåre har jag gjort detta konsekvent och det har räddad mig från många besvär efter detta.
Re: [PIC]Assembly - Invertera data?
Postat: 28 juni 2010, 10:30:20
av Nerre
Och om man sen upptäcker att kortlayouten skulle bli enklare om man byter plats på några av segmenten så är det bara de första defintionerna som behöver ändras.
Och behöver man ett till tecken eller behöver modifiera ett tecken är det också enkelt att peta in.
Fast jag hade nog valt att sätta kortare namn på de definitioner som motsvarar tecknen.