Sida 1 av 13
Jesses följetång om AVR programmering i C...
Postat: 20 oktober 2009, 11:02:03
av jesse
a) Varför använder man _BV(bitnr) istället för (1<<bitnr) i AVR-GCC? Är det en fördel eller bara ett annat sätt att skriva samma sak?
b) omvandling av olika former av integer:
Är det OK att blanda heltal med olika bitlängd eller kan det bli konstiga fel då? Hur skulle jag gjort annars?
Kod: Markera allt
int16_t a,b;
int8_t c,d;
a=b+c+d; // addera 8 bitars och 16 bitars
c=a>>8; // plocka ut de högsta 8 bitarna
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 11:23:07
av JockeE
a) Inte insatt i AVR-GCC, men jag gissar att det bara är ett tydligare (?) sätt att åstadkomma samma sak.
b) Det bör inte vara något problem att blanda på det där viset. Vill man vara säker bör man använda
type casting.
Kod: Markera allt
int16_t a, b;
int8_t c, d;
a = b + (int16_t) c + (int16_t) d; // addera 8 bitars och 16 bitars
c = (int8_t) (a>>8); // plocka ut de högsta 8 bitarna
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 11:27:34
av jesse
OK
(flyttade detta stycket från första inlägget då det lades till senare)
När jag ändå är igång och frågar ... kan man göra bitvis operationer i C på enstaka bitar som motsvarar t.ex. sbr r0,bit eller sbi port,bit och cbi port,bit... lite onödigt att gå omvägen att ladda ner och göra or / and för att sedan spara igen, t.ex.
Framför allt använder jag bitinstruktionerna i assembler för flaggor, då de ryms 8 st i en byte. ska man använda char som flaggor tar det 8 ggr minnesutrymme. Finns det något bekvämare sätt att sätta/resetta/ändra i en bit i en variabel än
Kod: Markera allt
flaggor |= flagga3; // sätt flagga3
if (flagga&flagga3) ...
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 11:36:13
av eqlazer
Det där är ju en bitvis operation (|). Har du kollat list-filen hur assemblerkoden ser ut? Kanske är det precis som du brukar göra.
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 11:42:49
av E85
Ibland brukar jag använt bit fields, såhär:
Kod: Markera allt
struct {
unsigned ready:1;
unsigned error_occured:1;
unsigned b2:1;
unsigned b3:1;
unsigned b4:1;
unsigned b5:1;
unsigned b6:1;
unsigned b7:1;
} config;
config.ready = 1;
Fast hur det ser ut i assembler har jag inte undersökt.
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:09:11
av Johanb
jesse skrev:a) Varför använder man _BV(bitnr) istället för (1<<bitnr) i AVR-GCC? Är det en fördel eller bara ett annat sätt att skriva samma sak?
Det gör man inte mig veterligen, det var vanligt förr men nu är det nog inte många som skriver så.
Edit: klantade citatet
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:15:11
av MicaelKarlsson
jesse skrev:
När jag ändå är igång och frågar ... kan man göra bitvis operationer i C på enstaka bitar som motsvarar
Har du testat:
Kod: Markera allt
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:25:15
av hornfeldt
jesse skrev:a) Varför använder man _BV(bitnr) istället för (1<<bitnr) i AVR-GCC? Är det en fördel eller bara ett annat sätt att skriva samma sak?
http://www.nongnu.org/avr-libc/user-man ... faq_use_bv
_BV är ett macro för att göra det mer läsvänligt. Kompilatorn gör ingen skillnad på uttrycken.
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:40:59
av jesse
MicaelKarlsson skrev:Har du testat:
Kod: Markera allt
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
Det märks att jag är nybörjare på C. Det tog lite tid att fatta dessa macron, särskilt den översta tills jag fattade att den inte är en "operation" utan ett uttryck.
men
bit_clear(PORTB,1<<PB2); skulle vara ett korrekt användande väl?
I så fall kanske jag kunde köra
istället, så slipper jag 1<< för varje bit.... (om nu bitarna definieras som 0,1,2,3 och inte 1,2,4,8,16...). Nackdelen är förstås att detta macro bara kan nolla en bit åt gången, men det var ju också det jag ville åt. Om detta nu översätts till sbi PORTB,(1<<PB0) så blir det ju grymt bra.
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:47:49
av jesse
fortsätter väl min AVR-C tråd med mer tjafs... kan bli en väldigt lång tråd om alla problem eller undringar jag stöter på ska pratas om här
men: försökte göra ett enkelt UART program... (har inte testat i hårdvara än) och kunde lite låta bli att försöka få ihop det så det funkade med
printf(...). Men herregud vilken mängd kod det genererade... 3368 bytes! Det var precis det fick plats i min ATMega48. Då gäller det att man inte vill göra något annat än att skicka tecken till /från UART...
hoppas nu bara att det stämmer att printf() kopplas till mina egna uart_putch() rutiner och inte nån annastans??? ENda sättet att verifera det är väl att testa i hårdvaran antar jag!
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:50:16
av MicaelKarlsson
Jag brukar för enkelhets skull skriva så här:
För att i koden senare använda uttrycket:
Om det är lättläst eller ej? Ja och nej.... för mig är det enkelt eftersom jag är van vid att skriva så.
Men det känns enklare/mer lättläst än att skriva:
vilket i mina ögon säger: "Sätt PC0 till ett"
Medan uttrycket:
säger att relä 1 dras (eller aktiveras eftersom jag i detta fall använde slutande reläer)
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:58:41
av stekern
om du gjort som man ska så kommer den redirektas till din putchar rutin
men som du märkt så tar printf mycket plats, så jag brukar undvika att använda den.
Vill jag skriva ut ett siffervärde till en sträng så använder jag nån funktion liknande denna:
Kod: Markera allt
char string[10];
char *uint_to_string(uint16_t value) {
char *p;
p = (string + 10);
*--p = '\0';
do {
char ch = value % 10 + '0';
if (ch > '9')
ch += 'a' - '9' - 1;
*--p = ch;
value /= 10;
} while (value);
return p;
}
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 12:59:46
av bearing
Jag är personligen emot dessa makron. Tycker koden blir mer lättläst utan. Kanske är vi olika. Jag har svårt att hålla innebörden av makron i huvet, men tycker att en rad fylld med shift/OR/XOR/AND osv i kombination inte är så svår att tyda.
Kompilatorn kan ställas in att producera en fil som innehåller resultatet av kompilatorns arbete som assemblerkod, med C-koden som kommentarer. Filen kan t.ex. användas för att kontrollera att en C-kod inte genererat onödigt krångliga instruktioner.
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 15:29:37
av jesse
Makron som andra har skrivit kan ju vara helt obegripliga om man inte letar upp definitionen. Men jag gillar själv att använda macron , till en viss gräns. det kan bli överdrivet annars - man vill ju inte bygga ett helt nytt eget programspråk!
Onödiga macron:
#define loopTenTimes for(i=0;i<10;i++) {
#define endOfLoop }
#define endOfWhatever }
#define AddOne(x) (x)+=1
osv...
Re: lite undringar om AVR progrannering i C
Postat: 20 oktober 2009, 15:45:34
av jesse
Men vad är detta
Kod: Markera allt
#define F_OSC 8000000
#define BAUDRATE 19200
#define BAUD_PRESCALE (F_OSC/(16*BAUDRATE)-1)
UBRR0L = BAUD_PRESCALE;
UBRR0H = (BAUD_PRESCALE >> 8);
och detta ger: ../uarttest.c:26: warning: integer overflow in expression
för både UBRR0L och UBRR0H.
Värdena som matas in är 121(L) och 254(H)
aha... kom på det medan jag skrev... F_OSC är ju 8E+6 vilket tar upp 23 bitar vilket borde fått plats i ett vanligt integer, men i AVR-GCC är per default "integer" en 16-bitarstyp. Så genom att skriva #define F_OSC 8000000UL så fick det plats. Så löstes det också.... jobbigt i början med så många detaljer man måste vara vaksam på när man inte är van.
