Sida 7 av 13

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

Postat: 29 oktober 2009, 08:38:24
av jesse
Jag undrade just varför jag ibland fick en varning , ibland tre och iblans upp till 6 varningar. Hade antagligen ändrat i main.h som innehåller globala variabler och som anropas av alla källfiler.

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

Postat: 29 oktober 2009, 09:03:58
av speakman
> som innehåller globala variabler

Hur menar du nu? En .h-fil ska på sin höjd innehålla "extern"-deklarationer till globala variabler. Variablerna själva ska ligga i en av .c-filerna. Förslagsvis main.c om du har en sån.

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

Postat: 29 oktober 2009, 14:18:23
av jesse
jo ,det är extern-deklarationerna.... men just för att dom finns där måste den anropas av de andra filerna.

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

Postat: 29 oktober 2009, 23:46:19
av bos
Vad är det som måste "anropas" av andra filer?

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

Postat: 30 oktober 2009, 00:50:00
av jesse
ehhh... varför blev detta så viktigt? :roll:

... för att de globala variablerna används i de andra c-filerna, och då måste alltså main.h anropas av dessa (eller deras respektive h-filer) ... inkluderas kanske det heter.

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

Postat: 30 oktober 2009, 08:55:15
av bos
Därför att semantik ÄR viktigt inom programmering.

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

Postat: 23 november 2009, 22:24:17
av jesse
Jahapp... då är jag tillbaks igen med en liten fundering...

jag har en funktion som skickar ett 8-bitars unsigned int (uint8_t) på SPI-bussen:

Kod: Markera allt

void SPI_TransmitByte(uint8_t databyte);
och skall skicka en 24 bitars adress lagrad i en uint32_t variabel.

Jag skickar:

Kod: Markera allt

	SPI_TransmitByte(adress>>16);             // AA byte 2
	SPI_TransmitByte((adress>>8)&0xFF);   // AA byte 1
	SPI_TransmitByte(adress&0xFF);            // AA byte 0
Men det verkar som om det 32-bitars heltalet omvandlas till 8 bitars utan att jag behöver göra typomvandling, och det oavsett storlek på talet. Alltså borde jag kunna skippa &0xFF helt och ändå få ut rätt bitar:

Kod: Markera allt

	SPI_TransmitByte(adress>>16);    // AA byte 2
	SPI_TransmitByte((adress>>8));   // AA byte 1
	SPI_TransmitByte(adress);             // AA byte 0
Det ser ju till och med mer läsligt ut än det förra exemplet. Har nu lånat "Brian W Kernighans bok "Programmeringsspråket C" så det var ju lätt att konstatera att det inte blir några programfel att göra så. Den tar helt enkelt de lägsta 8 bitarna och spolar resten. Utan någon varning eller så. (Hade aldrig fungerat i Java. Hur det är med C++ vet jag inte?)

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

Postat: 24 november 2009, 09:07:23
av Icecap
Tyvärr är detta beteende kompilerberoende varför det bör undvikas.

Och det kan enkelt fixas på annat sätt:

Kod: Markera allt

union
  {
  unit32_t LWord;
  unit8_t Byte[1]; // Ska egentligen vara [4] men duger fint såhär...
  } Address;
Adressen används så att 32-bit värdet heter "Address.LWord" och 8-bit värden heter "Address.Byte[x]" där x är 0, 1, 2 eller 3. Detta betyder att det att sända 24 bit adress plötsligt ser ut såhär:
SPI_TransmitByte(Address.Byte[2]); // AA byte 2
SPI_TransmitByte(Address.Byte[1]); // AA byte 1
SPI_TransmitByte(Address.Byte[0]); // AA byte 0

Och detta är kompileroberoende, dock är det endian-beroende.

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

Postat: 24 november 2009, 12:55:54
av speakman
Enda sättet att vara säker på hur värdet skickas över är att göra som du gjort, men ta med type casting:

Kod: Markera allt

   SPI_TransmitByte((uint8_t)((adress>>16) & 0xFF));   // AA byte 2
   SPI_TransmitByte((uint8_t)((adress>>8) & 0xFF));    // AA byte 1
   SPI_TransmitByte((uint8_t)(adress & 0xFF));         // AA byte 0
Det är märkligt att inte kompilatorn klagar annars. Det är väldigt lite den brukar ta för givet.

EDIT: Jag provade ditt "extremexempel" i gcc, och den varnade ingenting. Inte ens med -pedantic påslaget. Jag hade dock ändå valt att göra som koden ovan.

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

Postat: 24 november 2009, 13:03:39
av jesse
Endianberoende.... är ju ungefär lika jobbigt som kompilatorberoende, om det nu varierar.

Frågan är vad olika kompilatorer skulle kunna hitta på i mitt exempel, förutom att trunkera, dvs bara skala bort de bitar som blir över.? Felkod eller varning kan ju vara ett alternativ kanske.

Men så här då:

Kod: Markera allt

	
	SPI_TransmitByte( (uint8_t) ( adress >> 8); // AA byte 1
eller
	SPI_TransmitByte( (uint8_t) (( adress >> 8) & 0xFF); // AA byte 1

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

Postat: 24 november 2009, 15:56:38
av speakman
Lite för lite parenteser, men med den senare så har du iallafall typat stenhårt. Den hade jag kört på.

Vad gäller endianess så spelar det ju ingen roll om man bara lagrar i minnet. Men ska man ut på bussar och skyffla mellan olika system så måste ju protokollet du använder eller skriver specificera byte order. Network byte order är ju inte så dumt så behöver man inte komma ihåg vad som använder vad. Standarder ftw. :)

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

Postat: 24 november 2009, 16:34:16
av jesse
Network byte order hehe , om det ändå hade varit så enkelt... jag har en krets som lagrar data i 12-bitars heltal. När jag ska läsa dem så tror du bitarna kommer i ordning 11 till 0 eller 0 till 11 ? Moooaaahahahaha... nejdå inte alls. Det skulle ju vara alldeles för simpelt:

Datan kommer förts i 8 bitar från "värde1" : bit 7 till 0.
Sedan kommer bit 3-0 i "värde2" följt av de högsta fyra bitarna i "värde1": 11 till 8.
nästa byte innehåller till sist de sista bitarna i "värde2": bit 7-0.
Sedan upprepas mönstret med "värde3" bit 7 till 0 osv....
:doh:

Dom har säkert patent på det där. Undrar vad det kallas?
what endian? mixed endian? intelligent endian? :mrgreen:

Well well.... nu till nästa roliga AVR-GCC fundering:

Jag har en massa loopar här och där som brukar se ut ungefär som:

Kod: Markera allt

for ( uint8_t  i=0;  i<antal;  i++ ) ...
Detta blir i kompilatorn i slutet av loopen:

Kod: Markera allt

 622:	1f 5f       	subi	r17, 0xFF	; 255
 624:	80 91 01 01 	lds	r24, 0x0101
 628:	18 17       	cp	r17, r24
 62a:	80 f3       	brcs	.-12    
givetvis måste jag testa om jag kan spara in en rad och tjäna 1 clockcykel per varv och en byte i programminnet, så det blev:

Kod: Markera allt

for ( uint8_t  i=antal;  i<255;  i-- ) ...
och, ja, det fungerar:

Kod: Markera allt

 2d0:	81 50       	subi	r24, 0x01
 2d2:	d8 f7       	brcc	.-10 
jag tjänade två bytes per loop - och en av looparna ingick i en inline funktion och sparade över 12 bytes kod bara när jag ändade på ett ställe. Och så gick loopen på 6 cykler istället för 8. :P

Men det är ju lite skumt att räkna ner ett otecknat , otäckent, otäckt...heltal (äsch, vad heter unsigned integer på svenska?) och sedan jämföra om det är mindre än 255.. kompilatorn skulle ju kunna få krupp :| Man kan ju använda signed integer och skriva i<0, men då är problemet:
1) om koden blir lika effektiv? och
2) jag begränsas till 128 varv.

jag kanske börjar bli lite för petig när det gäller att spara tid och minne... snart kanske GCC kraschar :?

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

Postat: 24 november 2009, 20:09:26
av SvenW
Premature optimization is the root of all evil -- DonaldKnuth

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

Postat: 30 december 2009, 21:21:12
av jesse
************* NYTT ÄMNE *************
Jag skulle vilja göra en struct som ser ut så här:

Kod: Markera allt

struct dataformat {
      int32_t summa;
      uint16_t antal;
      uint8_t status;
      uint8_t crc;
} data;
sedan vill jag skicka denna byte för byte på SPI bussen, typ:

Kod: Markera allt

for (i = 0 ; i < antalBytesInStruct; i++) {
      SPI_SendByte(data[i]);
}
Men hur adresserar jag enskilda bytes i en struct?
Går det att definiera en pekare för det? Eller går det att mixtra så att man skapar en uint8_t array[8] som ligger på samma adress som structen "data" och därmed kunna läsa enskilda bytes?

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

Postat: 30 december 2009, 22:36:07
av jesse
Verkar ha hittat lösningen själv, även om jag inte är 100% säker på att den gör exakt det jag vill...

Denna pekare går tydligen att deklarera utan problem, och kan användas i en loop:

Kod: Markera allt

uint8_t *bytepekare = (uint8_t*) & data;
SPI_SendByte( *bytepekare + i);
Den bör ju nu räkna upp byte för byte... *bytepekare blir i allafall en uint8_t...
...om den nu pekar rätt bara ... :roll: