Jesses följetång om AVR programmering i C...
Re: Jesses följetång om AVR progrannering i C...
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...
> 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.
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...
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...
Vad är det som måste "anropas" av andra filer?
Re: Jesses följetång om AVR programmering i C...
ehhh... varför blev detta så viktigt?
... 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.

... 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...
Därför att semantik ÄR viktigt inom programmering.
Re: Jesses följetång om AVR programmering i C...
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:
och skall skicka en 24 bitars adress lagrad i en uint32_t variabel.
Jag skickar:
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:
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?)
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);
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
Kod: Markera allt
SPI_TransmitByte(adress>>16); // AA byte 2
SPI_TransmitByte((adress>>8)); // AA byte 1
SPI_TransmitByte(adress); // AA byte 0
Re: Jesses följetång om AVR programmering i C...
Tyvärr är detta beteende kompilerberoende varför det bör undvikas.
Och det kan enkelt fixas på annat sätt:
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.
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;
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...
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:
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.
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
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...
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å:
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...
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.
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...
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....
Dom har säkert patent på det där. Undrar vad det kallas?
what endian? mixed endian? intelligent endian?
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:
Detta blir i kompilatorn i slutet av loopen:
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:
och, ja, det fungerar:
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.
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
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....

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

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++ ) ...
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
Kod: Markera allt
for ( uint8_t i=antal; i<255; i-- ) ...
Kod: Markera allt
2d0: 81 50 subi r24, 0x01
2d2: d8 f7 brcc .-10

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

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...
Premature optimization is the root of all evil -- DonaldKnuth
Re: Jesses följetång om AVR programmering i C...
************* NYTT ÄMNE *************
Jag skulle vilja göra en struct som ser ut så här:
sedan vill jag skicka denna byte för byte på SPI bussen, typ:
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?
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;
Kod: Markera allt
for (i = 0 ; i < antalBytesInStruct; i++) {
SPI_SendByte(data[i]);
}
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...
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:
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 ...
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);
...om den nu pekar rätt bara ...
