Sida 1 av 2
Dela upp en byte?
Postat: 11 augusti 2006, 15:29:58
av JimmyAndersson
Låt säga att en variabel innehåller talet 66. Binärt 01000010. Talet kan förresten vara allt mellan 0 till 255.
Det vill jag dela upp till två variabler. Så att i detta fallet X = 0100 (dvs 4). Y = 0010 (dvs 2.)
Programmerar som vanligt i MikroBasic, men matte är ju ett universiellt språk.
MikroBasic har kommandon som kan dela upp ett word till två bytes, men jag har inte hittat något som delar upp en byte till två 'grupper' med 4 bytes i varje.
Först trodde jag att jag löst det. Jag gjorde såhär:
(Psuedo-kod, mellanslag i binära tal för att det ska vara lättare att läsa.)
Talet som ska delas upp = 0100 0010 (dvs 66)
x = Talet + 990
x är nu 0100 0010 0000.
oversta = hi(x)
'oversta innehåller nu 0100
under = lo(x)
'under innehåller nu 0010 0000
understa = under - 30
'understa innehåller nu 0010
Men det är ingen bra lösning på andra tal eftersom det är en statisk uträkning. Om Talet som ska delas upp är t.ex 0010 0000 så blir oversta 11 och understa 1110 0000.
Det måste ju finnas bättre sätt att lösa detta. Hur?
AND fungerar ju för att få t.ex 1111 1111 att bli 1111 1111 0000. Men sedan måste jag ju få 1111 0000 till att bli 1111. Om jag löser den biten så behövs visserligen ingen AND. Hmm.. har jag missat någon logik-operator.
Jag ska förresten använda det till en liten rutin för en LCD som ska fungera såhär:
*Lägg in t.ex "Hej" i en sträng.
*Plocka ut bokstav för bokstav och gör om till ascii-kod.
*Dela upp ascii-koden (t.ex 32) till två delar, dvs 0010 och 0000. Skicka först 0010 och sedan 0000 till LCD'ns.
Det är alltså den sista punkten som jag behöver hjälp med.
Om jag förklarat rörigt så är det bara att ropa.

Postat: 11 augusti 2006, 15:55:24
av Greve Hamilton
För att få de "nedre" bitarna kan du ju köra:
Ny_byte = (0x0F & byten);
Och den "övre" delen:
Ny_byte2 = ( (0xF0 & byten) >> 4 );
Kan hända att jag har missuppfattat något. Det händer nämligen allt för ofta.
Bonusfråga; Dessa "halv-bytes" kallas för något, minns inte vad bara. Någon som vet?
Postat: 11 augusti 2006, 15:59:07
av oJsan
Skiftoperatorn!
Jag kan ju inte svära på att den finns i MikroBasic, men den finns definitivt i asm.
c-kod:
tal = 0x43;
tal_h = a>>4; //, skifta åt höger fyra ggr, ersätts med fyra enkelskiftningar i följd i asm
tal_l = a & 0x0F;
tal_h blir då 0x4 och tal_l blir 0x3.
Om du inte hittar någon skiftoperator så funkar nog detta också:
tal = 0x43;
tal_h = a/16;
tal_l = a & 0x0F;
Att skifta ett steg är samma som att dela med två. Att skifta fyra steg är alltså samma som att dela med 2^4=16
Edit: GreveH: Jag tror inte att det är nödvändigt att maska den del som skiftas. "Halvorna" brukar kallas för nibbles.
Postat: 11 augusti 2006, 15:59:33
av AndXy
halv byte = nibble
läs om "SWAP" i manualen till mikrobasic
Postat: 11 augusti 2006, 16:03:13
av oJsan
Om swap finns som assemblerfunktion så den förmodligen effektivast.
Postat: 11 augusti 2006, 16:05:30
av JimmyAndersson
Tackar för svaren!
Hade helt glömt bort skift. Jodå, det finns i MikroBasic. Man använder
<< och
>>
"Hmm.. har jag missat någon logik-operator"
Det hade jag alltså.
edit: Swap verkar också fungera.
Perfekt!

Tack för alla snabba svar.

Postat: 11 augusti 2006, 16:07:35
av Greve Hamilton
Ah, nibble - där satt den!
oJsan: Just fan, tänkte inte så långt.

Men man förstår ju syftet i alla fall.
Postat: 11 augusti 2006, 17:22:26
av JimmyAndersson
Upptäckte just en bugg i MikroBasic.
Med min rutin kan jag skriva t.ex
lcd_skriv("H")
lcd_skriv("e")
lcd_skriv("j")
Det fungerar bra.
(ska ordna så man kan skriva hela meningar i en sträng sedan.)
Men om jag skickar:
lcd_skriv("!")
så blir det helt fel. Plockar jag bort raden så är det ändå fel. Jag måste starta om MikroBasic och ändra massa saker tills den "glömt bort" utropstecknet.
Felmeddelandena blir:
164:1 24 Supplied and formal parameters do not match ('latc.5' to byte) nataggregat1.pbas
164:1 4 Syntax error: Expected ')' but '.' found nataggregat1.pbas
164:1 10 Too many parameters nataggregat1.pbas
164:1 4 Syntax error: Expected 'end' but '' found nataggregat1.pbas
164:1 4 Syntax error: Expected '.' but '' found nataggregat1.pbas
Trots att allt är *exakt* som innan jag lade till utropstecknet.
edit: Tryckte kortkommandot för Build istället för att klicka på 'Skicka' inlägget.

Postat: 11 augusti 2006, 17:35:28
av mullemeck
vad är det lcd_skriv() vill ha in för datatyp?
Är det en sträng eller en byte?
Hur blir det om du skriver lcd_skriv(33) istället?
33 är det decimala talet för "!"
Postat: 11 augusti 2006, 21:38:01
av JimmyAndersson
datatypen är egentligen byte, men i MikroBasic kan man skriva t.ex lcd_skriv("A") som tas emot som 65 (ascii-kod för A.)
Har som sagt rensat bort "!". Faktum är att jag rensat bort allt i hela rutinen och anropen till rutinen, men det blir ändå felmeddelanden. Nu har jag fått bort de gamla, men nu får jag istället detta:
0:0 0 Linker error: Routine not found: lcd_skriv
Förstår inte alls varför den klagar. Koden fungerade innan jag lagt till lcd_skriv("!") och nu har jag alltså tagit bort alla sådana rader.
Kan bjuda på lite kod, trots att den är ok:
Kod: Markera allt
sub procedure lcd_skriv(dim value as byte)
oversta = 0
understa = 0
flytta = 0
oversta = value >> 4 ' Flyttar de översta (4st) fyra steg åt höger.
flytta = value << 4 ' Flyttar fyra steg åt vänster för att de fyra översta ska försvinna.
understa = flytta >> 4 'Flytta tillbaka igen och nu har de tidigare översta försvunnit.
LATC = oversta ' Skicka översta delen
lcd_vanta ' E och vänta
LATC = understa ' Skicka understa delen
lcd_vanta ' E och vänta
end sub
lcd_skriv(65)
Jag får alltså felmeddelandet ovan även om jag plockar bort *allt* i sub-rutinen.
edit: Eh... jahopp, nu fick jag bort felmeddelandet. Plockade som sagt bort allt i sub-rutinen tidigare. Nu skrev jag in:
dim oversta as byte
value = 0
som enda innehåll i rutinen och då försvann felmeddelandet.
Sedan kunde jag stoppa tillbaka rätt innehåll (det som visas i kod-rutan) i rutinen och felmeddelandet är fortfarande borta.
Ibland längtar man faktiskt tillbaka till assembler för DOS 3.1

Postat: 11 augusti 2006, 23:14:12
av sodjan
Jag är helt övertygad om att en TOM sub (utan någon exekverbar kod)
kommer att optimeras bort helt av kompilatorn, d.v.s att en
helt tom "lcd_skriv" kommer att "saknas". Helt logiskt och precis vad man
förväntar sig av varje vettig kompilator. Dock borde det komma en
varning vid kompileringen, så att man inte missar det...
> Sedan kunde jag stoppa tillbaka rätt innehåll...
Även "!" ? Naturligtsvis borde även "!" fungera...
Sen är swap mycket effektivare än att göra 4 st shift (">> 4").
En (maskin-) instruktion istället för 4.
Jag gissar att detta genererar mer kompakt kod :
Kod: Markera allt
sub procedure lcd_skriv(dim value as byte)
tmp = 0
tmp = value
value = swap(value)
value = value and $0F
LATC = value ' Skicka översta delen
lcd_vanta ' E och vänta
value = tmp
value = value and $0F
LATC = value ' Skicka understa delen
lcd_vanta ' E och vänta
end sub
Jag förutsätter att swap() amvänder asm-instruktionen swap !
Det sparar även 2 byte RAM.
Om PORTC.4-7 används till något vettigt, så
fungerar dock varken din eller min kod...
Postat: 11 augusti 2006, 23:31:48
av AndXy
Jimmy, avsluta genast dina "märkliga övningar" med mikrobasic

och börja omgående med assembler till PIC, jamenar Basic é rätt basic, du vet ju inte vad som händer eller

?? Dessutom e PIC:s assembler (instruktionslista) ytterst enkel att lära sig

!!
Postat: 11 augusti 2006, 23:40:21
av lgrfbs
Rapportera in felet till
http://www.mikroe.com/
mikroPascal har kommit ut i en ny version så det bör inte dröja länge tills
mikroBasic också får en uppdaterning.
Postat: 12 augusti 2006, 00:07:45
av sodjan
Jag skulle bara vilja göra en liten kommenter till...
Hela problemet ligger igentligen i denna fras från Jimmy :
>>>> ...men matte är ju ett universiellt språk...
Att dela (eller swap'a) en byte har mycket lite med matematik att göra !
Hela Jimmys problem i första inlägget beror på försöket att *räkna* ut det.
Det är helt vanlig bit-hantering, och alla processorer har bra verktyg (d.v.s
instruktioner typ SWAP och AND) för att lösa denna typ av problem.
Postat: 12 augusti 2006, 15:03:07
av JimmyAndersson
>> Sedan kunde jag stoppa tillbaka rätt innehåll...
> Även "!" ? Naturligtsvis borde även "!" fungera...
sodjan:
Det har blivit fel varje gång jag försökt stoppa in "!". Har inte så mycket lust att testa igen eftersom det tar en stund att ordna upp allt igen.
Tack för koden! Jag hade gjort ett litet fel när jag testade med Swap som gjorde att det inte fungerade. Därför använde jag skift (<< och >>).
> Om PORTC.4-7 används till något vettigt, så fungerar dock varken din eller min kod...
Javisstja, du har ju helt rätt. Jo, PORTC.6 (TX) och PORTC.7 (RX) ska användas till seriekommunikation. Men om jag gör om koden lite så att det bara skickar till PORTC.0-3 så borde det väl fungera?
PORTC.0-3 används för att visa inställda värden på LCD'n. Man ställer in dessa värden med några knappar och encoders. Men man ska även kunna ställa in dessa värden på en dator (via serieporten.) Både knappar/encoders och RX/TX ska använda interrupt.
AndyXy:
lgrfbs: Bra idé. Hm, jag har aldrig hittat var man laddar ner uppdateringarna. ..
sodjan igen:
> Hela Jimmys problem i första inlägget beror på försöket att *räkna* ut det.
Exakt. Lyckligtvis insåg jag det och efterlyste därför ett annat sätt. (Jag hade provat flera bitwise-operatorer.)