Sida 1 av 1
AVR C
Postat: 19 december 2010, 18:43:41
av SeaGull
Hej!
Har för några år sedan testat AVR och STK200, men assembler är inte min grej.
När jag såg att nu finns möjligheten att köra AVRStudio med AVR GCC som plugin gratis blev jag sugen igen.
Har köpt en AVRISP MK2, ett exprimentkort och en ATMEGA48.
Har lött ihop grejorna och första uppgiften var att få en lysdiod att blinka, redan där körde jag fast. Har fått lysdioden att blinka, men förstår inte riktigt varför.
Om jag i koden nedan kommenterar bort raden 'charSlask=charSlask' så slutar dioden blinka, den lyser fast. Förstår inte varför, akn nån förklara?
En annan sak är simulatorn, om jag kör debuggen på denna så fungerar det delvis, men det blir lite tokigt. Skall detta fungera?
/Stefan
Kod: Markera allt
#include <avr/io.h>
signed long VCount;
int Vartannat;
char charSlask;
int main(void) {
PORTB = 0b11111110; // Aktivera pullup-motstånd på ingångar
DDRB=0b00000001; // Bit 0 utgång, övriga ingångar
Vartannat=0;
VCount=1L;
while(1){
if(VCount++>10000L) {
if(PORTB&0b00000001)
PORTB=PORTB&0b11111110;
else
PORTB=PORTB|0b00000001;
VCount=0L;
}
charSlask=charSlask;
// PORTB=PORTB;
// charSlask=PINB;
}
Re: AVR C
Postat: 19 december 2010, 19:16:51
av eqlazer
Använd code-taggarna för att få vettig formatering på texten.
Re: AVR C
Postat: 19 december 2010, 19:28:02
av sodjan
Med code-taggarna avses altså att skriva något i stil med:
Kod: Markera allt
[code]
...
Här kopierar du in din kod...
...
...
[/code]
Re: AVR C
Postat: 19 december 2010, 19:44:19
av thepirateboy
Prova att använda "toggle-funktionen" istället PORTB ^= (1<<PB0); // Toggle LED
För att köra i simulatorn är det bra om man avaktiverar optimeringen under Config Options. ändra från -Os till t ex -O0
En snyggare variant är att använda en timer:
Kod: Markera allt
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/wdt.h>
volatile unsigned char timer10ms = 0;
// Configures the board hardware and chip peripherals for the demo's functionality.
void SetupHardware(void)
{
// Disable watchdog if enabled by bootloader/fuses
MCUSR &= ~(1 << WDRF);
wdt_disable();
clock_prescale_set(clock_div_1);// Disable clock division
DDRB = (1<<PB0); // LED port as output
// Init timer 0, Compare Match A
TCCR0A = (1<<WGM01); // CTC Clear timer on compare match
TCCR0B = (1<<CS02) | (1<<CS00); // Clock/1024
OCR0A = 78; // 10ms
TIMSK0 = (1<<OCIE0A); // Interrupt enable
}
int main(void)
{
SetupHardware();
sei();
for (;;)
{
if(timer10ms >= 50) // Blink every 0.5 sec
{
timer10ms = 0;
PORTB ^= (1<<PB0); // Toggle LED
}
}
}
// Timer 0 CTC ISR, firing every 10 millisecond to keep track of time.
ISR(TIMER0_COMPA_vect)
{
timer10ms++;
}
Re: AVR C
Postat: 19 december 2010, 23:32:06
av SeaGull
Blev klart elegantare med xor-toggle.
När jag tar bort optimeringen så fungerar blinkningen, och koden var verkligen optimerad, för blinkfrekvensen halverades. Det måste väl räknas som en bug i kompilatorn?
Ska testa timerfunktionen sen ...
Re: AVR C
Postat: 20 december 2010, 07:50:32
av ds77
Det räknas väl snarare som en bug hos programmeraren att inte läsa dokumentationen...
Re: AVR C
Postat: 20 december 2010, 09:37:14
av SeaGull
SeaGull skrev:Det räknas väl snarare som en bug hos programmeraren att inte läsa dokumentationen...
Du menar alltså att det är normalt att denna kod beter sig olika beroende på graden av optimering, hade jag ingen om.
Du får gärna utveckla detta mer, du som har koll ...
Re: AVR C
Postat: 20 december 2010, 09:48:45
av ds77
Vill du inte läsa dig till det så kan jag ge ett tips i alla fall: Väljer du att ha optimering(vilket i de flesta fall är bra..) så kommer kompilatorn jobba hårt för att leta upp saker som inte "gör något" och ta bort dessa, tex saker som bara tar tid utan att något intressant kan inträffa och avbryta(en klassiker är om man försöker få till en loop som bara ska ta tid och ge en fördröjning...) .
Som en övning kan du ju testa följande med optimering och se om det fungerar. Gör det det kan du ju leta lite i dokumentationen och fundera på varför.
Re: AVR C
Postat: 20 december 2010, 12:52:49
av SeaGull
Att sätta/nollställa en utgång måste väl ändå vara "något intressant".
Du hävdar alltså att detta är normalt för en kompilator?
Re: AVR C
Postat: 20 december 2010, 13:03:39
av sodjan
Men är det ens helt klart vilken skillnad på/av av optimeringen faktiskt gjorde ?
Har du kollat resultatet (assemblerkoden) från kompilatorn i båda fallen ?
> Du hävdar alltså att detta är normalt för en kompilator?
Jag kan inte se att det är helt klart vad "detta" syftar på.
Dessutom är det ju upp till kompilatorn att göra vad den vill
när man ber om optimering så länge slutresultatet blir detsamma.
Och exekveringshastigheten är bara en faktor, ofta kan man välja
vad den ska "optimera" på, exekveringshastighet *eller* kodstorlek.
Eller en kombination...
Sen så finns det exempel på kompilatorer som gör mer eller mindre
underliga saker när man kör med optimeringen avstängt. Ingen
aning om det är så i just detta fall dock...
Re: AVR C
Postat: 20 december 2010, 13:06:16
av jesse
Att det åtgår olika lång tid att utföra koden beror ju på att du inte någonstans i koden definierat några exakta tider. Du räknar ju upp Vcount tio tusen gånger, men du har ju inte berättat för varken kompilatorn eller processorn hur lång tid det ska ta. Alltså tar det den tid det tar. Att det blir olika beroende på optimeringen beror just på att koden
optimeras.
Därför brukar man mäta tid med timers så som thepirateboy visar. Annars finns även färdiga funktioner som heter _delay_ms() och _delay_us() som väntar en viss tid. (Men dessa förutsätter att optimeringen är påslagen för att räkna rätt). Då hade du kunnat ersätta din kod med:
Kod: Markera allt
while(1) {
PORTB ^= 0b11111110;
_delay_ms(500); // vänta 500 ms
}
Du behöver inkludera biblioteket för delay-funktionerna:
#include <util/delay.h>
Hjälpen till biblioteken hittar du under "hjälp" i AVRStudio.
Kod: Markera allt
Att sätta/nollställa en utgång måste väl ändå vara "något intressant".
Visst, men vad den gör däremellan (dvs räknar upp en variabel från 0 till 10000) kan göras mer eller mindre effektivt. Med optimering försöker kompilatorn göra det så snabbt som möjligt, därmed går det fortare. Kompilatorn kan ju inte veta att du
vill att det ska gå långsamt i just det här fallet.
Så en icke-optimerad kompilering tar fram variabelns värde från ramminnet, adderar med ett och lägger tillbaks i ramminnet igen. Men i en optimerad variant så ser kompilatorn att den inte kommer att göra så värst mycket annat tills nästa gång det är dags att addera med ett. Så den skippar helt enkelt att läsa och skriva till ramminnet och låter värdet ligga kvar i ett processorregister. Det går ungefär dubbelt så fort.
Re: AVR C
Postat: 20 december 2010, 14:01:07
av ds77
SeaGull skrev:Att sätta/nollställa en utgång måste väl ändå vara "något intressant".
Du hävdar alltså att detta är normalt för en kompilator?
Du säger att den inte gör det? Har du kollat med oscilloskop på pinnen, jag tror det går så snabbt att du inte ser det...
Re: AVR C
Postat: 20 december 2010, 15:00:15
av SeaGull
Tack Jesse för ett utförligt och trevligt svar!
... och jag får väl acceptera att kompilatorn gör dessa stora ändringar i min kod, optimeringen går ju som sagt att stänga av.
Jag ska, som jag skrev tidigare, testa timerfunktionerna vid tillfälle.
Re: AVR C
Postat: 20 december 2010, 15:06:28
av jesse
Den ändrar ju inget i din kod: den gör ju exakt vad du skriver att den ska göra. Och det gör den alltid. Exakt hur den gör det (i maskinkod) kan ju däremot variera. Med olika kompileringsmetoder blir resultatet olika, helt enkelt. Det är så alla kompilatorer för högnivåspråk fungerar.