Bryta upp ett nummer och ladda in i en array
Bryta upp ett nummer och ladda in i en array
Hej
Jag använder AVR studio 5 och försöker programmera i C.
Jag får numret 00111000 som är deklarerat med uint8_t.
Hur kan jag göra för att ladda det numret in i en array så att det ser ut så här om vi säger att array'en heter 8bit:
8bit[0] = 0
8bit[1] = 0
8bit[2] = 0
8bit[3] = 1
8bit[4] = 1
8bit[5] = 1
8bit[6] = 0
8bit[7] = 0
PS. nybörjare .DS
Jag använder AVR studio 5 och försöker programmera i C.
Jag får numret 00111000 som är deklarerat med uint8_t.
Hur kan jag göra för att ladda det numret in i en array så att det ser ut så här om vi säger att array'en heter 8bit:
8bit[0] = 0
8bit[1] = 0
8bit[2] = 0
8bit[3] = 1
8bit[4] = 1
8bit[5] = 1
8bit[6] = 0
8bit[7] = 0
PS. nybörjare .DS
Re: Bryta upp ett nummer och ladda in i en array
Varför vill du göra det? Om du vill kunna kolla de enskilda bitarna så finns det nog bättre sätt.
Googlade lite snabbt och i på den här sidan finns en massa olika tips:
http://stackoverflow.com/questions/4798 ... e-bit-in-c
Googlade lite snabbt och i på den här sidan finns en massa olika tips:
http://stackoverflow.com/questions/4798 ... e-bit-in-c
Re: Bryta upp ett nummer och ladda in i en array
Det finns olika sätt och vilket som är bäst beror på vad man vill använda bit-en till. Om man har dom som flaggor och måste snäla på minnet kan man deklarera:
Då kan man komma åt båda hela bytes (The_One.As_Byte) och varje bit (The_One.Bits.B0 - The_One.Bits.B7).
Men om man vill göra om ett värde till en binär utskrift är det bättre att lösa det på ett annat sätt.
Kod: Markera allt
union
{
struct
{
uint8 B0 : 1;
uint8 B1 : 1;
uint8 B2 : 1;
uint8 B3 : 1;
uint8 B4 : 1;
uint8 B5 : 1;
uint8 B6 : 1;
uint8 B7 : 1;
} Bits;
uint8 As_Byte;
} The_One;
Men om man vill göra om ett värde till en binär utskrift är det bättre att lösa det på ett annat sätt.
Re: Bryta upp ett nummer och ladda in i en array
Jo, för att sedan kunna loopa igenom array'n och skicka respektive 0 och 1 i tur och ordning till en shiftregister. Som vill bli matad ett nummer i taget.
Av länken där förstod jag inte mycket
Av länken där förstod jag inte mycket

Re: Bryta upp ett nummer och ladda in i en array
Om du vill skriva ut ett värde som '0' och '1', alltså det binära mönster, är det bättre att shifta - men det verkar du förstå.
Länken anger hur man kan använda bitmässiga konstanter men jag ser den inte som speciellt bra beskrivning.
Så egentligen behöver vi nog veta: vad vill du med det? Vad ska det göra?
Länken anger hur man kan använda bitmässiga konstanter men jag ser den inte som speciellt bra beskrivning.
Så egentligen behöver vi nog veta: vad vill du med det? Vad ska det göra?
Re: Bryta upp ett nummer och ladda in i en array
Finns många sätt att komma åt varje enskild bit, ett av dem är
(1 << 2) betyder att du skiftar en etta två steg åt höger så du får 0b00000100 (4 decimalt) om du sedan kör en and med detta
då återstår bara att skifta biten a tillbaka två steg.
Eftersom det är konstanter i detta fallet skulle du lika gärna kunna skriva
Men det blir kanske inte lika lättläst för en ovan kodare.
men som ekman säger så kan det, beroende på vad du försöker göra, vara lika bra att använda t ex (num & (1 << 2)) >> 2 direkt i koden där du vill ha bit med index 2.
vill jag loopa igenom varje bit så brukar jag personligen göra något i stil med detta
Vill man istället spara flaggor på ett kompakt sätt är Icecaps variant väldigt bra.
Kod: Markera allt
uint8_t num = 0b00111000;
8bit[0] = num & 1;
8bit[1] = (num & (1 << 1)) >> 1;
8bit[2] = (num & (1 << 2)) >> 2;
8bit[3] = (num & (1 << 3)) >> 3;
osv...
Kod: Markera allt
0bXXXXXaXX
and
0b00000100
=
0b00000a00
Eftersom det är konstanter i detta fallet skulle du lika gärna kunna skriva
Kod: Markera allt
uint8_t num = 0b00111000;
8bit[0] = num & 1;
8bit[1] = (num & 2) >> 1;
8bit[2] = (num & 4) >> 2;
8bit[3] = (num & 8) >> 3;
osv...
men som ekman säger så kan det, beroende på vad du försöker göra, vara lika bra att använda t ex (num & (1 << 2)) >> 2 direkt i koden där du vill ha bit med index 2.
vill jag loopa igenom varje bit så brukar jag personligen göra något i stil med detta
Kod: Markera allt
uint8_t = 0b00111000;
uint8_t i;
for(i = 0; i < 8; i++)
{
bit = num && 1;
num = num >> 1;
}
Re: Bryta upp ett nummer och ladda in i en array
eller såhär:
/johan
Kod: Markera allt
for(uint8_t i=0; i < 8; i++)
{
sendtoshiftregister( num & ( 1 << i ) );
}
Re: Bryta upp ett nummer och ladda in i en array
Om man är säker på att funktionen sendtoshiftregister() hanterar värdet som en boolean. Annars kan det vara bra att lägga till en extra ">> i" efter.
Re: Bryta upp ett nummer och ladda in i en array
Tack för svaren. Nu förstår jag bättre. Tyvärr så verkar problemet ligga någon annanstans. Det jag försöker göra är att använda en shiftregister för att skicka data till LCD (HD44780). Avr -> Shiftregister -> LCD.
RS,RW,E pinnarna på LCD'n är kopplad direkt till Avr'n. Tänkte jag skulle vara smart och använda mindre I/O pinnar och testa med shiftregister
Tror det blir fel med timeingen? då jag fått för mig att det är rätt kritiskt. LCD koden har jag hittat på AVRfreaks forum och försökt anpassat. Är rätt trött nu och ska ta en pause för att försöka hitta felet senare (ikväll för förhoppningsvis). Men tänkte först visa hur jag försökte implementera den funktionen jag frågade efter:
Jag tänkte på en sak. När jag använder denna funktion och skriver till ex. LcdSendByte(0x38); så tänkte jag att uint8_t gjorde om hex talet till binärt? till 00111000 ? om den inte göra det så funkar ju det inte
Ps. Jag vet att jag tog förmodligen vatten över huvudet med shiftregistert. Ska testa bara Avr -> LCD, efter lite mer försök
.ds
RS,RW,E pinnarna på LCD'n är kopplad direkt till Avr'n. Tänkte jag skulle vara smart och använda mindre I/O pinnar och testa med shiftregister

Tror det blir fel med timeingen? då jag fått för mig att det är rätt kritiskt. LCD koden har jag hittat på AVRfreaks forum och försökt anpassat. Är rätt trött nu och ska ta en pause för att försöka hitta felet senare (ikväll för förhoppningsvis). Men tänkte först visa hur jag försökte implementera den funktionen jag frågade efter:
Kod: Markera allt
void LcdSendByte(uint8_t theByte)
{
// Short delay needed here...
_delay_us(50);
// Output the byte (to shiftregister)
PORTD &= (0<<3); // Set Register pin LOW
for(uint8_t i=0; i < 8; i++)
{
Send(theByte & ( 1 << i ));
}
PORTD |= (1<<3); // Set Register pin HIGH to show change
// Toggle the E line
LCD_CTRL_PORT |= (1<<LCD_E); // Going up..
// Short delay needed here...
_delay_us(50);
LCD_CTRL_PORT &= ~(1<<LCD_E); // ..and down.
}
Jag tänkte på en sak. När jag använder denna funktion och skriver till ex. LcdSendByte(0x38); så tänkte jag att uint8_t gjorde om hex talet till binärt? till 00111000 ? om den inte göra det så funkar ju det inte

Ps. Jag vet att jag tog förmodligen vatten över huvudet med shiftregistert. Ska testa bara Avr -> LCD, efter lite mer försök

Re: Bryta upp ett nummer och ladda in i en array
Det kan fungera helt OK med ett shiftregister men du måste ha koll på att det inte blir kastat om på MSB och LSB.
Jag ser omedelbart ett par problem som kan göra det hela lite svårare att läsa allt, du bör alltså förtydliga för dig själv. Du använder (1<<3) som en bit men om du vore lite bättre på att göra läsbara program hade du, först i programmet, skrivit:
#define Set_Shift_Latch() (PORTD |= (1<<3))
#define Clear_Shift_Latch() (PORTD &= ~(1<<3))
Sedan använder du Set_Shift_Latch(); eller Clear_Shift_Latch(); i programmet, det är extremt mycket enklare att läsa.
Och samma sak ger vilket fel du gör!
"PORTD &= (0<<3); // Set Register pin LOW"
Detta kommando nollar hela PORTD! Du ska skriva:
"PORTD &= ~(1<<3);" istället.
Jag ser omedelbart ett par problem som kan göra det hela lite svårare att läsa allt, du bör alltså förtydliga för dig själv. Du använder (1<<3) som en bit men om du vore lite bättre på att göra läsbara program hade du, först i programmet, skrivit:
#define Set_Shift_Latch() (PORTD |= (1<<3))
#define Clear_Shift_Latch() (PORTD &= ~(1<<3))
Sedan använder du Set_Shift_Latch(); eller Clear_Shift_Latch(); i programmet, det är extremt mycket enklare att läsa.
Och samma sak ger vilket fel du gör!
"PORTD &= (0<<3); // Set Register pin LOW"
Detta kommando nollar hela PORTD! Du ska skriva:
"PORTD &= ~(1<<3);" istället.
Senast redigerad av Icecap 13 december 2011, 14:04:09, redigerad totalt 1 gång.
Re: Bryta upp ett nummer och ladda in i en array
Det ser ut som du fått bra hjälp i inlägget ovan, så jag tänkte svara på den här frågan istället:
) när man programmerar.
Nedanstående rader betyder alla samma sak:
Ett ganska vanligt missförstånd i början 
Om ett tal är hex, binärt, decimalt eller octalt spelar ingen roll, det är bara för att göra det enklare (eller svårareekman skrev:Jag tänkte på en sak. När jag använder denna funktion och skriver till ex. LcdSendByte(0x38); så tänkte jag att uint8_t gjorde om hex talet till binärt? till 00111000 ? om den inte göra det så funkar ju det inte

Nedanstående rader betyder alla samma sak:
Kod: Markera allt
uint8_t x;
x = 12; // decimalt
x = 0xC; // Hexadecimalt
x = 014; // Octalt
x = 0b1100 // Binärt

Re: Bryta upp ett nummer och ladda in i en array
Precis, en dator jobbar i princip ALLTID med binära tal. Sen kan de i och för sig "tolkas" på olika sätt (som flyttal, heltal, bokstäver).
Re: Bryta upp ett nummer och ladda in i en array
Sätt en fördröjning på en sekund mellan varje förändring på utgången och sätt dit lysdioder så ser du i vilken ordning det kommer ut (om du inte har ett oscilloskop förstås, då är det enklare - men ändra tiderna så att du kör med millisekunder - inte mikrosekunder - då är du säker på att det inte är för korta tider i alla fall - sedan, när allt fungerar , kan du prova att öka hastigheten).Tror det blir fel med timeingen? då jag fått för mig att det är rätt kritiskt.
Nu vet jag inte riktigt vad "register pin" är för något? Kan du inte rita ett schema på hur du har kopplat så vi får se? Annars kan det vara svårt att avgöra om du gör rätt eller fel.
Kod: Markera allt
Send(theByte & ( 1 << i ));
/************ Här kommer överkurs för oss programmeringstokiga:
När man loopar en variabel, i och sedan gör (1 << i) inne i loopen kan det kanske ta en massa onödig tid, om den i varje varv ska shifta i antal gånger. Nu kan det hända att GCC ser dett och optimerar bort det, men om den inte gör det , så är detta alltså ett klumpigt sätt för processorn att shifta ett åttabitars tal. **************/
Jag hade gjort så här:
Kod: Markera allt
for (i = 0; i<8 ; i++) {
send(data & 1);
data >> 1;
}
Jag tor att du shiftar ut bitarna i fel ordning. Om du sänder bit 0 först , så kommer den till slut att hamna sist i shiftregistret, dvs på utgång Q7, den sista biten du shiftar in (bit 7 ) kommer att hamna i Q0. Om du vill ha det i rätt ordning ska du alltså börja med bit 7 och sluta med bit 0.
Re: Bryta upp ett nummer och ladda in i en array
Nu har jag försökt debuggat lite mer. Jag har satt data pinnarna från shiftregistret ut till 8st LED's. Så nu kan jag visuellt se vilka pinnar som blir höga osv.
men jag kan fortfarande inte läs in theByte bit för bit.
Jag försökte först med Johano's exempel med:
Men inget utslag.
Så då tänkte jag att jag ska lägga in bit för bit i en array som LHelge visade. Så här gjorde jag:
Men helt dött. Men då testade jag att slänga in en '1' mitt i arrayen. Och då lyser respektive LED upp
Jag gissar på att dom laddas med fler än ett nummer?
Jag försökte till och med, med någon slags if statement som skulle sortera in 1 och 0 i array'n. Så här:
Detta innan jag skickar till Shiftregister.
Inte heller det lyckades. Så har ni några fler förslag?
ps. Jag har ändrat PORTD &= (0<<3); till PORTD &= ~(1<<3); .ds
men jag kan fortfarande inte läs in theByte bit för bit.
Jag försökte först med Johano's exempel med:
Kod: Markera allt
for(uint8_t i=0; i < 8; i++)
{
send( theByte & ( 1 << i ) );
}
Så då tänkte jag att jag ska lägga in bit för bit i en array som LHelge visade. Så här gjorde jag:
Kod: Markera allt
uint8_t ShiftArray[8];
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;
Kod: Markera allt
uint8_t ShiftArray[8];
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] = 1; //(theByte & 6) >> 5;
ShiftArray[6] = (theByte & 7) >> 6;
ShiftArray[7] = (theByte & 8) >> 7;

Jag försökte till och med, med någon slags if statement som skulle sortera in 1 och 0 i array'n. Så här:
Detta innan jag skickar till Shiftregister.
Kod: Markera allt
uint8_t ShiftArray[8];
for(int k=0; k<8; k++)
{
//Ladda array
if((theByte<<k)==1)
{
ShiftArray[k] = 1;
} else
{
ShiftArray[k] = 0;
}
}

ps. Jag har ändrat PORTD &= (0<<3); till PORTD &= ~(1<<3); .ds
Re: Bryta upp ett nummer och ladda in i en array
Kan ju vara intressant å se min send rutin som jag har för att ladda shiftregistern:
Jag vet att jag ändrar hela port B. Och att jag borde använt mig av define. Får snygga till det 
Kod: Markera allt
void Send(int g)
{
if (g == 1)
{
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
}
