Bryta upp ett nummer och ladda in i en array

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av pbgp »

aha!

Återgå till den här loopen:

Kod: Markera allt

for(uint8_t i=0; i < 8; i++)
{
  send( theByte & ( 1 << i ) );
}
Sedan ändrar du send till:

Kod: Markera allt

void Send(int g)
{
   if (g)
   {
      PORTB=0x40; // Set Serial Pin to 1
   }
   else
   {
      PORTB=0x00; // Set Serial Pin to 1
   }
      //Send pulse to SERCLK
      PORTD |= (1<<4); // HIGH
      PORTD &= ~(1<<4); // LOW
}
Prova det. Om det funkar ska jag förklara varför.
ekman
Inlägg: 280
Blev medlem: 13 januari 2009, 14:04:35

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av ekman »

yes! nu får jag utslag! :D
Ska koppla in LCD'n och testa nu, så har du tid att förklara varför inte det gick med if(g == 1)? :humm:
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av jesse »

Orsaken att (G == 1) inte fungerar:

Antag att data = 0b11111111 = bara ettor.

data & (1 << 0 ) = 1
data & (1 << 1 ) = 2
data & (1 << 2 ) = 4
data & (1 << 3 ) = 8
data & (1 << 4 ) = 16
data & (1 << 5 ) = 32
data & (1 << 6 ) = 64
data & (1 << 7 ) = 128

Som du ser blir det bara "ett" för bit "noll". Alla andra bitar ger andra värden.

------------------------------------------------------
Skrev nedanstående innan jag såg att det fungerar :

Kod: Markera allt

	if (g == 1)
Som sagt, du måste kolla om g är skild från noll. "1" är den bara om bit0 är etta.
if (g != 0)är detsamma som att skriva if (g) .

Kod: Markera allt

		PORTD |= (1<<4); // HIGH
		PORTD &= ~(1<<4); // LOW
Här går det bara en klockcykel... Om du kör 1 MHz blir det 1 µS. Det borde räcka för ett shiftregister, men beror på omständigheter som längd på kabel med mera. Det går bara en eller ett par klockcykler från det att PORTB sätts tills klockan går hög. Även här lite kort marginal.

Ändra först så att logiken stämmer. Om det fortfarande inte händer något, eller om bitmönstret blir fel, så testa att ha in fördröjningar här:

Kod: Markera allt

		_delay_us(10);
		PORTD |= (1<<4); // HIGH
		_delay_us(10);
		PORTD &= ~(1<<4); // LOW
Och glöm inte att shifta ut högsta biten först.[/color]
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av pbgp »

Jesse förklarade bra, han belyser också en sak som du missade. Du skrev:

Kod: Markera allt

      ShiftArray[0] = theByte & 1;
      ShiftArray[1] = (theByte & 2) >> 1;
      ShiftArray[2] = (theByte & 3) >> 2;
      ShiftArray[3] = (theByte & 4) >> 3;
      ShiftArray[4] = (theByte & 5) >> 4;
      ShiftArray[5] = (theByte & 6) >> 5;
      ShiftArray[6] = (theByte & 7) >> 6;
      ShiftArray[7] = (theByte & 8) >> 7;
Hade du följt LHelges kod:

Kod: Markera allt

ShiftArray[0] = theByte & 1;
ShiftArray[1] = (theByte & (1 << 1)) >> 1;
ShiftArray[2] = (theByte & (1 << 2)) >> 2;
ShiftArray[3] = (theByte & (1 << 3)) >> 3;
ShiftArray[4] = (theByte & (1 << 4)) >> 4;
ShiftArray[5] = (theByte & (1 << 5)) >> 5;
ShiftArray[6] = (theByte & (1 << 6)) >> 6;
ShiftArray[7] = (theByte & (1 << 7)) >> 7;
Så hade det funkat på en gång utan ändringen i send().
ekman
Inlägg: 280
Blev medlem: 13 januari 2009, 14:04:35

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av ekman »

Så där. Nu kan ni pusta ut, nu fungerar LCD'n. Tack alla som har svarat och hjälpt till :D

Men i ärlighetens namn så är jag fortfarande osäker på vad som händer.
Det är just send( theByte & ( 1 << i ) ); jag inte förstår.

Men om det är som du säger Jesse, så skickas det binära talet?

så send(0b00111000 & (1<<5)); skickar talet 16?
Den skiftar 5 steg till vänster, och om en 1 finns där. Så skickar den det talets binära värde? I så fall har jag helt missat att "den gör så".

Sen så tror jag löste det där med att skicka störst tal först till shiftregistern genom att koppla bit0 till bit14 på lcd'n :roll:

@pbgp
aa inte helt otippat att jag skulle missa det. blir inte klok på alla shiftningar. Det ger väl med sig så småningom kanske
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av pbgp »

Det är precis som du själv förklarat med ditt exempel där i är 5. låt oss bryta ner följande rad i beståndsdelar:

Kod: Markera allt

send( theByte & ( 1 << i ) );
Anta att i är 5 och theByte är 56 (vilket är samma som 0b00111000)
  1. talet 1 skiftas 5 steg till vänster. Man skickar, så att säga, in nollor från sidan. Resultatet blir 0b00010000 vilket är 16 decimalt.
  2. theByte (0b00111000) och 0b00010000 slås ihop med den logiska operatoren "bitvis and" (alltså & -tecknet). Resultatet blir: 0b00010000 eller 16 decimalt.
  3. funktionen send() anropas med parametern 16.
Nu får vi gå in i funktionen send(), första raden är

Kod: Markera allt

if (g)
i det här fallet

Kod: Markera allt

if(16)
I språket C så är detta exakt samma sak som

Kod: Markera allt

if(16 != 0)
Nu körs

Kod: Markera allt

PORTB=0x40
Resten tror jag du förstår.

Jag tror du behöver fundera lite på vad som menas med "talets binära värde". Datorn skiljer inte på binärt, decimal eller annat. Din kompilator kommer att generera exakt samma kod för send(16), send(0xA), send(56 & 0b00010000) som den gör för send(56 & 16).
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av jesse »

Variabeln theByte är ju åttabitars. Det består ju av åtta bitar. Inget annat.

Det kan innehålla t.ex. 11110000 eller 00000111, men för bekvämlighets skull kan vi skriva decimalt eller hexadecimalt i programkoden och det översätts då till ettor och nollor i maskinkoden.

00000111 binärt = 4+2+1 = 7 decimalt
11110000 binärt = 128+64+32+16 = 240 decimalt

När du ser en formel t.ex. i denna if-sats: if (apa & (bongo >> 3)) { ... } så måste du veta vad varje operation gör ochi vilken ordning de utförs för att förstå vad som händer. (Som tur är kan man använda parenteser - då löser sig det med ordningen. Den innersta parentesen löses alltid först.)

Om apa = 00000111 och bongo = 11110000 så händer följande:

1) bongo shiftas tre steg åt höger: 11110000 blir 00011110.
2) logiska operationen OCH utförs på 00000111 och 00011110. Bara när båda bitarna på samma position är en etta så blir resultatet en etta:

Kod: Markera allt

    00000111          (7)     (det decimala talet står inom parentes)
&   00011110         (30)
    ---------
    00000110          (6)
När det står (1 << i) så är det talet "ett" decimalt dvs. 00000001 binärt, som skiftas i antal gånger:
om i = 2 blir det 00000100, om i = 6 blir det 01000000.

Jämför med hur det skulle bli om du hade skrivit t.ex. ( 128 >> i ) istället?

Om du kan det här bra så kan du gå tillbaks i koden och se vad som sker och varför de tidigare försöken blev fel.
Lär du dig det binära logik-tänket så vinner du extremt mycket när du ska programmera controllers!
ekman
Inlägg: 280
Blev medlem: 13 januari 2009, 14:04:35

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av ekman »

Jag har tänkt fel förut vilket gör att det känns lite svårare att lära om sig, men trägeln vinner :)

Tänkte tackla (128<<i) men blir lite fundersam. Trodde det skulle bli "lätt" :roll:
Jag kan inte trycka in 128 decimalt i kalkylatorn (med byte i tryckt). Och när jag skriver binärt 1000 0000 så står det -128?

Vad beror dettta på? blev sjukt osäker på vilka värden bitarna representerar nu (1111 1111)

är det:

Kod: Markera allt

64+32+16+8   +   4+2+1+0
eller

Kod: Markera allt

128+64+32+16   +   8+4+2+1
Nerre
Inlägg: 27235
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av Nerre »

En signed byte kan bara anta värden från -128 till 127.

I princip så är biten längst till vänster "teckenbiten". Är den noll är det ett positivt tal, är den 1 är det ett negativt tal.

Det enklaste sättet att förstå negativa binära tal är nog att helt enkelt subtrahera från noll.

-1 är samma sak som 0-1
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av pbgp »

ekman skrev:Tänkte tackla (128<<i) men blir lite fundersam. Trodde det skulle bli "lätt" :roll:
Jag kan inte trycka in 128 decimalt i kalkylatorn (med byte i tryckt). Och när jag skriver binärt 1000 0000 så står det -128?

Vad beror dettta på? blev sjukt osäker på vilka värden bitarna representerar nu (1111 1111)
Det andra alternativet är rätt, alltså:

Kod: Markera allt

128+64+32+16   +   8+4+2+1
Att 1000 0000 ger -128 innebär att din kalkylator använder "tvåkomplementsform" för binära tal. Tvåans komplement är inte så intuitiv då 1000 0000 är -128 och 1111 1111 är -1. Man kan ju tycka att fler 1:or skulle ge det större negativa talet men så är det alltså inte. Det finns fördelar i hårdvaruimplementationen av addition och subtraktion som gör att man väljer tvåkomplementsform. Jag ger mig inte in på att förklara närmare utan rekommenderar istället Wikipedias artikel:

http://en.wikipedia.org/wiki/Twos_complement
Användarvisningsbild
Icecap
Inlägg: 26652
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av Icecap »

Att den visar -128 beror på att den använder signed char som bas. Kan du välja unsigned ska du göra det - eller helt enkelt lära dig hur det fungerar...
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av pbgp »

Icecap: hela den här tråden har ju gått ut att han vill lära sig hur det fungerar. Hitintills har det gått ganska bra. Föresten så har du fel, en unsigned char behöver inte representeras i tvåkomplementsform. Hade kalkylatorn använt ettkomplement så hade den visat -0
Nerre
Inlägg: 27235
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av Nerre »

Fast ettkomplement är väl betydligt svårare att räkna med?

Anledningen till att man använder tvåkomplement är ju att om man tar -2 +2 och kör in det i en vanlig adderare så får man 0.

Med ettkomplement så blir väl ALU krångligare?

Öht måste det ju vara väldigt mycket krångligare att jobba med ett system där det finns både +0 och -0...? Blir t.ex. -2 + 2 till -0 då, medans 2 - 2 blir +0?
Användarvisningsbild
Icecap
Inlägg: 26652
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av Icecap »

pbgp: fel? Det är väl du som har lite problem. En unsigned skrivs aldrig med förtecken och är alltid positivt. En unsigned byte kan ha alla heltalsvärden mellan 0 och 255, jag ser inte var 1- eller 2-komplement kommer in där!
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Bryta upp ett nummer och ladda in i en array

Inlägg av pbgp »

Ja, i mitt föregående inlägg råkade jag skriva unsigned när jag skulle skrivit signed.
Skriv svar