Behöver nybörjarhjälp att programmera i C
Re: Behöver nybörjarhjälp att programmera i C
> ...utan jag måste uppdatera själv hela tiden genom att klicka på variablen.
Men även det är ju väldigt mycket bättre än att inte veta någonting alls.
Men även det är ju väldigt mycket bättre än att inte veta någonting alls.
- Magnus_K
- EF Sponsor
- Inlägg: 5854
- Blev medlem: 4 januari 2010, 17:53:25
- Ort: Skogen mellan Uppsala-Gävle
Re: Behöver nybörjarhjälp att programmera i C
Så, nu fungerar det! Förstår mig inte på debuggern riktigt utan fick debugga på ett mycket effektivare sätt, ändra en massa och se vad som händer! (Kanske inte så effektiv men har visat sig fungera i 1 fall av 1000)
Då jag ändrade NUMBER-arrayen från const till unsigned så ändrade samtidigt DIGIT-arrayen till unsigned. Det är den som väljer vilken anod som ska vara aktiv, dvs vilken LED-display som ska lysa.
Trodde absolut inte att detta var vad som orsakade att siffrorna började fladdra men efter att ändra tillbaka DIGIT till const så fungerar det.
Så här ser det ut live -> Litet test av funktionen
Så här ser också rutinen ut nu:
Då jag ändrade NUMBER-arrayen från const till unsigned så ändrade samtidigt DIGIT-arrayen till unsigned. Det är den som väljer vilken anod som ska vara aktiv, dvs vilken LED-display som ska lysa.
Trodde absolut inte att detta var vad som orsakade att siffrorna började fladdra men efter att ändra tillbaka DIGIT till const så fungerar det.
Så här ser det ut live -> Litet test av funktionen
Så här ser också rutinen ut nu:
Kod: Markera allt
LATA &= (PORTA & 0x00); // Släck anod
LATD &= (PORTD & 0x00); // Nolla segmenten
i++; // Räkna upp vilken display som ska laddas nästa gång
if(i >= 4) {i = 0;} // Om >3 så nolla
j = voltage[i]; // Ge j värdet som respektive element innehåller
if(i == 3) {
NUMBER[j] &= 0x7f; // Om tecken 3 så AND:a in en 0:a, dvs tänd decimaltecknet
LATD |= NUMBER[j]; // Aktivera rätt segment beroende på ovan
LATA |= DIGIT[i]; // Tänd ny anod enligt räknaren
NUMBER[j] |= 0x80; // Återställ siffran med att OR:a in en 1:a
} else {
LATD |= NUMBER[j]; // Aktivera rätt segment beroende på ovan
LATA |= DIGIT[i]; // Tänd ny anod enligt räknaren
Re: Behöver nybörjarhjälp att programmera i C
Då DIGIT ju aldrig ändras måste den vara en const. Detta betyder att den sparas i ROM.
Hade den varit icke-const ville den ligga i RAM och skulle dels laddas från ROM vid uppstart och dels kunde det skrivas fel värden i den.
Hade den varit icke-const ville den ligga i RAM och skulle dels laddas från ROM vid uppstart och dels kunde det skrivas fel värden i den.
Re: Behöver nybörjarhjälp att programmera i C
Några tankar och tips...
Rad 1:
"LATA &= (PORTA & 0x00);" PORTA & 0x00 blir alltid noll. Alltså gör du LATA = LATA & 0, vilket också alltid är noll. Mao kan du istället skriva "LATA = 0".
Som du har skrivit nu ser det ut som att du förväntar dig något annat än att alltid sätta LATA till noll.
Rad 2:
Samma som rad 1.
Rad 4:
"if(i >= 4) {i = 0;}" kan skrivas kortare: "i &= 0x03", dvs du använder bara de två lägsta bitarna och behöver inte använda något villkor.
Rad 6 och framåt:
Det är mindre "snyggt" att ändra värdet i din tabell för att sätta decimalkommat. Istället kan du lägga värdet i en temporär variabel och ändra det där. Ett annat sätt är att göra det direkt i registret... I båda fallen kan du låta tabellen kvarstå som const (vilket är att föredra).
Denna kod ersätter rad 6-13.
EDIT: Ändrade typo avs Rad 4. Du använder de två (inte tre) lägsta bitarna.
Rad 1:
"LATA &= (PORTA & 0x00);" PORTA & 0x00 blir alltid noll. Alltså gör du LATA = LATA & 0, vilket också alltid är noll. Mao kan du istället skriva "LATA = 0".
Som du har skrivit nu ser det ut som att du förväntar dig något annat än att alltid sätta LATA till noll.
Rad 2:
Samma som rad 1.
Rad 4:
"if(i >= 4) {i = 0;}" kan skrivas kortare: "i &= 0x03", dvs du använder bara de två lägsta bitarna och behöver inte använda något villkor.
Rad 6 och framåt:
Det är mindre "snyggt" att ändra värdet i din tabell för att sätta decimalkommat. Istället kan du lägga värdet i en temporär variabel och ändra det där. Ett annat sätt är att göra det direkt i registret... I båda fallen kan du låta tabellen kvarstå som const (vilket är att föredra).
Kod: Markera allt
LATD = NUMBER[j]; // Notera att du inte behöver OR i tilldelningen, eftersom du redan nollat registret.
if (i==3)
LATD &= 0x7F; // Tänd decimalkommat
LATA = DIGIT[i]; // Inget OR behövs då registret redan är nollat.
EDIT: Ändrade typo avs Rad 4. Du använder de två (inte tre) lägsta bitarna.
Senast redigerad av ie 15 december 2014, 18:55:50, redigerad totalt 1 gång.
Re: Behöver nybörjarhjälp att programmera i C
> LATD = NUMBER[j]; // Notera att du inte behöver OR i tilldelningen, eftersom du redan nollat registret.
Om man ändå använder hela NUMBER[j] så spelar det ändå mindre roll, det
som ska nollas kommer att nollas i alla fall, behövs ingen nollning i förväg.
Samma sak med "LATA = DIGIT;", kommentaren "Inget OR behövs då
registret redan är nollat" är inte helt korrekt. "Inget OR behövs då
hela registret uppdateras i alla fall", är mer korrekt.
Om man ändå använder hela NUMBER[j] så spelar det ändå mindre roll, det
som ska nollas kommer att nollas i alla fall, behövs ingen nollning i förväg.
Samma sak med "LATA = DIGIT;", kommentaren "Inget OR behövs då
registret redan är nollat" är inte helt korrekt. "Inget OR behövs då
hela registret uppdateras i alla fall", är mer korrekt.
Re: Behöver nybörjarhjälp att programmera i C
Ungefär vad jag menade...
OR är användbart då man bara vill uppdatera (1-ställa) vissa bitar och låta andra bitar vara opåverkade. (Dvs endast delar av registret påverkas.) I det fallet blir det stor skillnad på en "|=" resp "="-tilldelning. Men eftsom han i detta fall redan valt att nollställa hela registret tidigare, så tillför inte en |="-tilldelning något i detta fall. Det är vad min kommentar avsåg.
(Hoppas det blev tydligare
)
OR är användbart då man bara vill uppdatera (1-ställa) vissa bitar och låta andra bitar vara opåverkade. (Dvs endast delar av registret påverkas.) I det fallet blir det stor skillnad på en "|=" resp "="-tilldelning. Men eftsom han i detta fall redan valt att nollställa hela registret tidigare, så tillför inte en |="-tilldelning något i detta fall. Det är vad min kommentar avsåg.
(Hoppas det blev tydligare

Re: Behöver nybörjarhjälp att programmera i C
Ja, det var orsakssambandet som var lite oklart... 
Det som var otydligt var att nollställningen (om den sker direkt
innan) inte *heller* tillför något.
För en del är det kanske
solklart, men det kan kanske misstolkas. Aja, utrett!

Det som var otydligt var att nollställningen (om den sker direkt
innan) inte *heller* tillför något.

solklart, men det kan kanske misstolkas. Aja, utrett!
- Magnus_K
- EF Sponsor
- Inlägg: 5854
- Blev medlem: 4 januari 2010, 17:53:25
- Ort: Skogen mellan Uppsala-Gävle
Re: Behöver nybörjarhjälp att programmera i C
@Icecap: Ahaa, så datan lägger sig i olika sorters minne beroende på hur jag deklarerat variablerna. Det visste jag inte men hänger med på skillnaden mellan RAM och ROM.
Verkligen snällt av er att hjälpa mig tänka i rätt banor. Alla de tips du presenterade ie kommer jag anamma. Kanon!
Jag påbörjade ett svar tidigare och förstod inte riktigt hur du fick den AND:ningen att ersätta if-satsen men efter att ha grunnat ett tag ohc testat så var det ju en utmärkt lösning.
Jämförde också i asm-koden hur mycket det skiljde på de två olika sätten och ditt sätt sparar faktiskt runt 6 instruktionscykler.
Idén med att skriva decimaltecknet separat var jättebra också. Kändes lite fel att hålla på och manipulera tabellen på mitt sätt.
En förtydling är heller aldrig fel. Har antagligen blivit lite OR och AND-galen efter fått lära mig hur det fungerar men efter era inlägg vet jag nu skillnaden på när detta är onödigt. Tack!
Två frågor:
Tänkte ge mig på att införa en "case-sats" eller ett "case" eller vad man nu säger.
- Anses detta vara en funktion som man gärna undviker för den tar mycket processortid att utföra?
- Om använder tex 4 st "cases", är det möjligt att välja inte bara ett case utan man kan plocka tex 2 och 3 att utföra?
Ska givetvis läsa på mer om det här med case ikväll men första frågan komme rnog bli svår att klura ut själv.
Verkligen snällt av er att hjälpa mig tänka i rätt banor. Alla de tips du presenterade ie kommer jag anamma. Kanon!
Jag påbörjade ett svar tidigare och förstod inte riktigt hur du fick den AND:ningen att ersätta if-satsen men efter att ha grunnat ett tag ohc testat så var det ju en utmärkt lösning.
Jämförde också i asm-koden hur mycket det skiljde på de två olika sätten och ditt sätt sparar faktiskt runt 6 instruktionscykler.
Idén med att skriva decimaltecknet separat var jättebra också. Kändes lite fel att hålla på och manipulera tabellen på mitt sätt.
En förtydling är heller aldrig fel. Har antagligen blivit lite OR och AND-galen efter fått lära mig hur det fungerar men efter era inlägg vet jag nu skillnaden på när detta är onödigt. Tack!
Två frågor:
Tänkte ge mig på att införa en "case-sats" eller ett "case" eller vad man nu säger.
- Anses detta vara en funktion som man gärna undviker för den tar mycket processortid att utföra?
- Om använder tex 4 st "cases", är det möjligt att välja inte bara ett case utan man kan plocka tex 2 och 3 att utföra?
Ska givetvis läsa på mer om det här med case ikväll men första frågan komme rnog bli svår att klura ut själv.
Re: Behöver nybörjarhjälp att programmera i C
switch - Case fungerar på följande sätt:
MEN - vissa kompilers kan faktisk bygga upp en tabell över delrutinerna och sedan indexera i den tabell med X och då spara tid. Detta sköts av kompilern och man ska bara programmera utan att bry sig om vilket.
Kod: Markera allt
switch(X)
{
case 0:
break:
case 1:
break;
case 2:
break;
case 4:
// Jepp, det SKA saknas en 'break'!
case 5:
break;
default:
// Alla som inte är ovan
break;
}
motsvarar:
if(X == 0)
{
}
else if(X == 1)
{
}
else if(X == 2)
{
}
else if(X == 3)
{
}
else if((X == 4) || (X == 5))
{
}
else
{ // default
}
- Magnus_K
- EF Sponsor
- Inlägg: 5854
- Blev medlem: 4 januari 2010, 17:53:25
- Ort: Skogen mellan Uppsala-Gävle
Re: Behöver nybörjarhjälp att programmera i C
Switch case hette det ja! Tack Icecap.
Det här är intressant. Kan man då på något sätt i ditt exempel få rutinen/funktionen(?) att utföra först case 1 och sen case 3 för att avsluta med default? Och allt detta utan att loopa om?
Tack vare dig Icecap förstår jag nu varför man ibland utelämnar "break;", men i detta fallet hjälper det nog inte riktigt.
Är rädd för att svaret kommer vara att man måste loopa och ändra "x = 1" och "x = 3" mellan gångerna.
Det här är intressant. Kan man då på något sätt i ditt exempel få rutinen/funktionen(?) att utföra först case 1 och sen case 3 för att avsluta med default? Och allt detta utan att loopa om?
Tack vare dig Icecap förstår jag nu varför man ibland utelämnar "break;", men i detta fallet hjälper det nog inte riktigt.
Är rädd för att svaret kommer vara att man måste loopa och ändra "x = 1" och "x = 3" mellan gångerna.
Re: Behöver nybörjarhjälp att programmera i C
Lite mer tips.
Skapa egna variabeltyper så är det möjligt att portar koden till annan kompilator. Då vet du alltid att "din int" är exvis 16 bitar. Om du byter kompilator och behöver ändra alla till kan det vara tusentals ställen som ska kontrolleras och ändras. Med en define krävs bara en ändring!
Exempelvis:
Undvika "magic numbers", dvs skriv inte
utan
Detta kommer göra att du undviker många slarvfel.
Skapa egna variabeltyper så är det möjligt att portar koden till annan kompilator. Då vet du alltid att "din int" är exvis 16 bitar. Om du byter kompilator och behöver ändra alla
Kod: Markera allt
int
Kod: Markera allt
short int
Exempelvis:
Kod: Markera allt
typedef unsigned char card8 ; // 8 bit unsigned. card = cardinal number
typedef card8* card8P ; // Pointer to 8 bit unsigned
typedef unsigned int card16 ; // 16 bit unsigned
typedef card16* card16P ; // Pointer to 16 bit unsigned
typedef unsigned long card32 ; // 32 bit unsigned
typedef card32* card32P ; // Pointer to 32 bit unsigned
typedef signed char int8 ; // Sign + 7 bit
typedef int8 int8P ; // Pointer to sign + 7 bit
typedef signed int int16 ; // Sign + 15 bit
typedef int16 int16P ; // Pointer to sign + 15 bit
typedef signed long int32 ; // Sign + 31 bit
typedef int8 int32P ; // Pointer to sign + 31 bit
typedef unsigned char char8 ; // unsigned 8 bit char to prevent random
// results from:
typedef char8* char8P ; // char c; if ( c == 0x80 ) do() ;
// Signed char expansion is platform
// dependent.
typedef signed char boolean ; // Some embedded compilers can handle "bit".
// bool is a part of C++
#define TRUE (-1) // For use with the boolean type
#define FALSE (0) // For use with the boolean type
Kod: Markera allt
for (i = 0; i < 8; i++)
Kod: Markera allt
#define NO_OF_PORTS 8 // Number of ports to read in IC nn
for (i = 0; i < NO_OF_PORTS; i++)
Re: Behöver nybörjarhjälp att programmera i C
Vad jag vet finns oftast <stdint.h> att inkludera och den ska alltid innehålla bra defines med namn för olika typer och bör redan finns tillgänglig på "alla" plattformar/processorer.
T.ex.
uint8_t my_byte;
istället för
unsigned char my_byte;
Jag är klart för #defines av magic numbers när det tillför tydlighet, t.ex. att de förekommer ofta eller där man kan förvänta sig att de ändrar sig, eller när det bara blir mycket tydligare med
en define istället för en till synes random siffra.
Men ibland (jag säger inte att detta är regeln) men ibland är faktiskt själva siffran det allra tydligaste. Kommer inte på något exempel just...
MVH: Mikael
T.ex.
uint8_t my_byte;
istället för
unsigned char my_byte;
Jag är klart för #defines av magic numbers när det tillför tydlighet, t.ex. att de förekommer ofta eller där man kan förvänta sig att de ändrar sig, eller när det bara blir mycket tydligare med
en define istället för en till synes random siffra.
Men ibland (jag säger inte att detta är regeln) men ibland är faktiskt själva siffran det allra tydligaste. Kommer inte på något exempel just...
MVH: Mikael
Re: Behöver nybörjarhjälp att programmera i C
Magnus_K: Det går såklart...
Om 1 alltid ska efterföljas av 3 men att 3 "ensam" ska gå med kan man göra:
case 1:
... bla bla ...
case 3:
... bla bla ...
break;
case 2:
... bla bla ...
break;
Då kan du aktivera 1 som då automatisk fortsätter "ner i" 3. Men aktiverar du 3 utförs bara den del.
Om 1 alltid ska efterföljas av 3 men att 3 "ensam" ska gå med kan man göra:
case 1:
... bla bla ...
case 3:
... bla bla ...
break;
case 2:
... bla bla ...
break;
Då kan du aktivera 1 som då automatisk fortsätter "ner i" 3. Men aktiverar du 3 utförs bara den del.
- Magnus_K
- EF Sponsor
- Inlägg: 5854
- Blev medlem: 4 januari 2010, 17:53:25
- Ort: Skogen mellan Uppsala-Gävle
Re: Behöver nybörjarhjälp att programmera i C
Tack för tipsen hummel och adent!
Igår lyckades jag lägga till stdint-header i mitt program. Har dock inte ändrat något annat men ikväll ska jag implementera alla tips jag fått och presentera koden.
Ber om att få återkomma med ett par frågor.
@Icecap:
Det är jag som inte kan förklara. Om vi tar ett riktigt exempel:
Här nedan har jag gjort en switch-rutin. I varje case finns det en specifik funktion. Det jag undrar över är om det finns något sätt jag kan nyttja detta till att första gången switch-rutinen körs så kallar jag bara case 0 och 2, nästa gång det loopat om så ändrar jag "x" så jag kanske kallar 1, 2 och 4 osv. Med andra ord att genom att endast ändra "x" så får jag switch-rutinen att utföra de specifika funktioner jag önskar just då.
Det kanske i det här fallet inte är en switch-rutin jag ska använda, kanske finns annat?
Igår lyckades jag lägga till stdint-header i mitt program. Har dock inte ändrat något annat men ikväll ska jag implementera alla tips jag fått och presentera koden.
Ber om att få återkomma med ett par frågor.
@Icecap:
Det är jag som inte kan förklara. Om vi tar ett riktigt exempel:
Här nedan har jag gjort en switch-rutin. I varje case finns det en specifik funktion. Det jag undrar över är om det finns något sätt jag kan nyttja detta till att första gången switch-rutinen körs så kallar jag bara case 0 och 2, nästa gång det loopat om så ändrar jag "x" så jag kanske kallar 1, 2 och 4 osv. Med andra ord att genom att endast ändra "x" så får jag switch-rutinen att utföra de specifika funktioner jag önskar just då.
Det kanske i det här fallet inte är en switch-rutin jag ska använda, kanske finns annat?
Kod: Markera allt
switch(X)
{
case 0:
TempFunc();
break:
case 1:
VoltageFunc();
break;
case 2:
PowerFunc();
break;
case 3:
SomeFunc();
break;
case 4:
SomeotherFunc();
break;
default:
CurrentFunc();
break;
}
Re: Behöver nybörjarhjälp att programmera i C
Du missar fortfarande frågan: är det varje gång det ska ske? Om Function_X() alltid ska följas av Function_Y() ska de såklart vara under samma case.
I en switch() har du en variabel att använda för att välja - och hur ska det då ske att du välja olika kombinationer?
En lösning är/kan vara:
case 0:
Function_A();
break;
case 1:
Function_B();
break;
case 2:
Function_C();
break;
...
case 100:
Function_A();
Function_B();
break;
case 101:
Function_A();
Function_C();
break;
osv.
I en switch() har du en variabel att använda för att välja - och hur ska det då ske att du välja olika kombinationer?
En lösning är/kan vara:
case 0:
Function_A();
break;
case 1:
Function_B();
break;
case 2:
Function_C();
break;
...
case 100:
Function_A();
Function_B();
break;
case 101:
Function_A();
Function_C();
break;
osv.