Sida 2 av 3
Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 16:35:02
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.
Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 16:43:24
av ekman
yes! nu får jag utslag!
Ska koppla in LCD'n och testa nu, så har du tid att förklara varför inte det gick med if(g == 1)?

Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 16:51:15
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 :
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]
Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 17:11:55
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().
Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 17:23:09
av ekman
Så där. Nu kan ni pusta ut, nu fungerar LCD'n. Tack alla som har svarat och hjälpt till
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(0b00
111000 & (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
@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
Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 21:12:41
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:
Anta att i är 5 och theByte är 56 (vilket är samma som 0b00111000)
- 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.
- theByte (0b00111000) och 0b00010000 slås ihop med den logiska operatoren "bitvis and" (alltså & -tecknet). Resultatet blir: 0b00010000 eller 16 decimalt.
- funktionen send() anropas med parametern 16.
Nu får vi gå in i funktionen send(), första raden är
i det här fallet
I språket C så är detta exakt samma sak som
Nu körs
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).
Re: Bryta upp ett nummer och ladda in i en array
Postat: 13 december 2011, 21:35:47
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!
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 05:48:57
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"
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:
eller
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 08:12:33
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
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 08:25:20
av pbgp
ekman skrev:Tänkte tackla (128<<i) men blir lite fundersam. Trodde det skulle bli "lätt"
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å:
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
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 09:50:48
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...
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 11:17:44
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
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 12:52:36
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?
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 13:48:56
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!
Re: Bryta upp ett nummer och ladda in i en array
Postat: 14 december 2011, 14:13:22
av pbgp
Ja, i mitt föregående inlägg råkade jag skriva unsigned när jag skulle skrivit signed.