Jesses följetång om AVR programmering i C...

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Jesses följetång om AVR programmering i C...

Inlägg av bearing »

Kod: Markera allt

char *dataP;

...

dataP=(char*)data;
for (i = 0 ; i < antalBytesInStruct; i++) {
      SPI_SendByte(*dataP++);
}
Det borde även gå att göra en union mellan structdefinitionen och den önskade arrayen för att kunna göra det du önskar. Men jag tror att ovanstående är snabbare.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Jag gjorde visst ett fel: *bytepekare + i ska vara *(bytepekare + i), då stämmer det. Orsaken att jag adderar i till adressen istället för som du föreslår skriva bytepekare++ är att jag vill behålla startadressen till nästa överföring utan att behöva räkna ut den igen...

Det där med unioner har jag inte studerat än, men jag är nöjd så här. Det verkar effektivt.
PTC
Inlägg: 2337
Blev medlem: 11 juni 2009, 20:04:12
Ort: Skövde

Re: Jesses följetång om AVR programmering i C...

Inlägg av PTC »

Önskar jag kunde programmera i det
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

PTC: du menar själva programmeringsspråket C ?
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Jesses följetång om AVR programmering i C...

Inlägg av bearing »

jesse skrev:jag vill behålla startadressen till nästa överföring utan att behöva räkna ut den igen...
Men dataP=(char*)data; är ingen uträkning, bara lagring av ett värde, motsvarande att skriva adress=10;.

*(bytepekare + i) är däremot en beräkning, motsvarande att skriva adress+i, den behöver dessutom göras varje varv i loopen. Så det är faktiskt mindre effektivt än det jag föreslog.

Det finns ett enkelt sätt att få fram antalBytesInStruct. Det är genom att skriva sizeof(dataformat). Detta är heller inte någon beräkning, utan förkompileringen byter ut sizeof(dataformat) mot siffran 8.

EDIT: för att göra det effektivare borde det vara bättre att byta ut for-loopen mot en while-.

Kod: Markera allt

char *dataP;

...

dataP=(char*)data;
i=sizeof(dataformat);
while(i--)
{
      SPI_SendByte(*dataP++);
}
Det tar nämligen längre tid att utföra i++ samt i < sizeof(dataformat) (alltså i < 8), än --i och jämförelse med noll. Det brukar nämligen finnas en instruktion som "minskar med ett, jämför med noll och hoppar", vilket går snabbare än att först "inkrementera med ett" och sedan "jämföra / hoppa".

Slutligen, undrar jag varför du (m.fl.) lägger blockstart ({) på samma rad som satsen. Detta försvårar att hitta starten på ett avslutat block i nästlade block, tycker jag (såvida inte editorn färgmarkerar sånt). Detta gör att blockfel blir frekventare, enligt min erfarenhet.
Senast redigerad av bearing 31 december 2009, 01:18:35, redigerad totalt 1 gång.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

tack för hjälpen :tumupp:

pekaren: jo, du har rätt. Jag tror jag ska göra på ditt sätt.

while(--i) var ju smart, hade jag nog inte kommit på själv. :)

blockstart { ... jag valde det efter att ha sett båda varianterna och tyckte helt enkelt att jag sparade lite plats om jag slipper slösa en extra rad på ett enda tecken... Men ju mer kod jag skriver desto mer luft lägger jag in, för att få det läsligt, så jag kanske övergår till ditt sätt att skriva så småningom... (den värdelösa editorn i AVR studio håller ju inte nån koll alls på { och } )

men så var det en sak till.... det verkar ju inte finnas något bra sätt att kopiera en struct till en annan:

Kod: Markera allt

struct datatyp readings = { 0,0,0,0,0xFF};
struct datatyp transmit = readings; // ERROR 
Så det blir väl att ta en pekare och göra en loop där också. Tveksamt om kompilatorn gör det lika effektivt om jag skriver:

Kod: Markera allt

transmit.summa  =  readings.summa;
transmit.antal  = readings.antal;
transmit.status = readings.status;
transmit.crc    = readings.crc;
(orsaken till att jag kopierar denna struktur är att jag har två interruptstyrda händelser: (1) inläsning av data från ADC, (2) skicka data via SPI på begäran av master... om dessa krockar ska det alltid finnas ett korrekt värde att skicka, även om data som håller på att läsas in inte är klart.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Jesses följetång om AVR programmering i C...

Inlägg av bearing »

Kom på att jag kommit fram till att detta är ännu mer effektivt, iaf med CC5X för PIC16.

Kod: Markera allt

do
{
      SPI_SendByte(*dataP++);
}while(--i);
Hm, --i var (nog) fel i mitt föregående förslag. Det ska stå i-- där för att den ska loopa rätt längd, om jag inte tänker fel. Jag ändrar.

Tänk dock på att om i skulle råka vara noll innan båda ovanstående while-loopar kommer den loopa 256/16536/o.s.v. gånger.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Re: Jesses följetång om AVR programmering i C...

Inlägg av speakman »

bearing skrev:Slutligen, undrar jag varför du (m.fl.) lägger blockstart ({) på samma rad som satsen. Detta försvårar att hitta starten på ett avslutat block i nästlade block, tycker jag (såvida inte editorn färgmarkerar sånt). Detta gör att blockfel blir frekventare, enligt min erfarenhet.
Det är naturligtvis helt subjektivt vad som är "bäst". Men skulle din slutsats gälla så skulle Linuxkärnan vara ganska full i blockfel eftersom den kräver måsvingarna på samma rad som while/for/if osv (endast funktioner har på egen rad).

Personligen föredrar jag Linux-modellen eftersom den ger kompaktare funktioner som blir lättare att överblicka utan att scrolla och/eller flytta ögonen för mycket. Men på det hela taget så är det som sagt väldigt subjektivt.


Däremot undrar jag lite över alla dessa sätt att skriva "optimalt" för kompilatorn (dina exempel ovan). Är man ute efter säker och tydlig kod så bör man undvika premature optimization tills det verkligen behövs. Ibland är det inte ens säkert att optimeringen blev det optimala i slutändan, då koden kanske blev annorlunda -- då har man bara kompromissen av kodläsbarhet kvar vilket man bara förlorar på.
hatten
Inlägg: 94
Blev medlem: 9 maj 2008, 22:16:23
Ort: Uppsala

Re: Jesses följetång om AVR programmering i C...

Inlägg av hatten »

Det här med kodformatering/indenteringsstilar har väl stötts och blötts många gånger utan att någon slags konsensus har uppstått, således en ren smaken-som-baken-diskussion (vilket naturligtvis inte innebär att den saknar berättigande) där jag antar att den stil man först bekantat sig med är den som känns mest naturlig.

K&R-indentering är mitt förstaval (och 1TBS god tvåa), antagligen är det för att koden blir mer kompakt som jag upplever den som långt snyggare och trevligare. Visst ökar läsbarheten, om än ganska lite, med Allman-stil men samtidigt får man ofta scrolla ihjäl sig och då tycker jag att en stor del av "överblickbarheten" försvinner. Tyvärr är det många IDEs som inte håller med mig! :x :wink:
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Jag progrmmerar även i DEV C++ och den vill indentera helt annorlunda än jag själv vill, irriterande :x
Jag hade tidigare närmast som sport att skriva så kompakt som möjligt. Det var väl innan jag påbörjat något större projekt. Nu ser jag mer och mer fördelarna med luftiga källkoder, även om det slösar papper om man vill skriva ut.

innan: apa=(manniska+djur)/2;
efter: apa = ( manniska + djur ) / 2;

ett tag fick jag för mig att även pekare-operatorn "stjärna" i : *foo och motsvarande (vad heter det: &foo) skulle skrivas separat: * foo , men det blev ju inte bra - det förväxlas lätt med multiplikationsoperatorn och bitvis och.
Användarvisningsbild
BEEP
EF Sponsor
Inlägg: 1593
Blev medlem: 21 januari 2006, 16:57:56
Ort: Mölndal

Re: Jesses följetång om AVR programmering i C...

Inlägg av BEEP »

Jag skulle ha skrivit det så här.
apa = (manniska+djur) / 2;
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Stötte på en märklig sak i GCC som jag funderar över:

jag råkade skriva SPI_stop; istället för att anropa funktionen med SPI_stop();

Jag har ingen macro som heter SPI_stop, men jag har alltså funktionen void SPI_stop( void ); . Ändå fick jag varken error eller varning. Men när jag satte på optimeringen så klagade den: "warning: statement with no effect".

Men varför blir det inte error när jag skriver funktionsnamnet utan parenteser? Vad tror den att jag vill göra? Hämta funktionens adress eller nåt? Hade jag inte haft optimeringen på hade jag inte upptäckt felet... (förutom att inget hade fungerat och jag hade blivit galen).
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: Jesses följetång om AVR programmering i C...

Inlägg av SvenW »

I och men att SPI_stop är deklarerad som funktion så finns den.
Skriver man SPI_stop utan parenteser och argument får man en funktionspekare.
Alltså är det helt i sin ordning. Optimeraren ser att den inte används och tar bort satsen med en varning.
Jfr följande kod:

Kod: Markera allt


int
SPI_stop(void)
{
  return 3;
}

int
main()
{
  int i;
  int (*fprt) (void);  /* Deklaration av funktionspekare */

  fptr =  SPI_stop;     /* Detta är OK, sätter funktionspekaren */
  i = fptr();           /* Detta är OK , i blir tre */

  i;                    /* Detta är OK men ger ingen effekt*/
  fptr;                 /* Detta är OK men ger ingen effekt */
  SPI_stop;             /* Detta är OK men ger ingen effekt */
}
Senast redigerad av SvenW 3 januari 2010, 16:41:26, redigerad totalt 2 gånger.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Jag får väl lära mig att inte glömma parenteserna då! :roll:
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: Jesses följetång om AVR programmering i C...

Inlägg av SvenW »

I GCC m.fl. kompilatorer kan man sätta på extra varningsflaggor.
Ex:
gcc x.c -W -Wextra -Wall -pedantic

Se vidare o GCC-manualen under 'Warning Options'.

Vad gäller programmeringsstil så läste jag nån gång att man skall välja en stil och försöka hålla sig till den. Det är väl med det som med typsnittet (fonten). Ögat vänjer sig vid ett typsnitt och om man byter får man ont i ögonen och blir vimmelkantig.
Läser man kod med 'fel' programmeringstil blir hjärnan fyrkantig och man blir på dåligt humör.

Se t.ex.
http://en.wikipedia.org/wiki/Indent_style

Vilken stil föredrar ni? Jag gillar av någon anledning inte K&R-stilen, utan gillar mer GNU-stilen. Kanske ett fråga för omröstning?
Skriv svar