Ik ben bezig met het programmeren van een een avr (tiny2313) in plat C.
het is de bedoeling een ledje te laten faden (en later natuurlijk vele uitbreidingen).

Ik heb een klein stuk code gekopierd voor het aansturen mbv PWM.

Alleen begrijp ik het eerste deel van de code nooit.
Hier een voorbeeld:

#include <avr/io.h>
#include <util/delay.h>

int main()
{
// TIMER 0 Fast PWM, clear OC0A, OC0B on match
TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
// TIMER 0 Prescaler ck/8
TCCR0B = (1 << CS02);

// TIMER 1 Fast PWM 8-bit, clear OC1A, OC1B on match
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10);
// TIMER 1 Prescaler ck/8
TCCR1B = (1 << CS12) | (1 << WGM12);

//PWM kanaal als uitgang

DDRB = (1 << PB3); //OC1A

// PWM kanalen

OCR1B = 0; //rood fade

while(1)
{
unsigned char i;

//fade rood
for(i = 0; i < 255; i++)
{

OCR1A = i;
_delay_ms(200);
}

for (i = 255; i> 0; i--)
{
OCR1A = i;
_delay_ms(200);
}

}

return 0;
}

Het laatste deel heb ik zelf geschreven en begrijp ik gewoon, maar de eerste 14 regels kan ik niet goed verklaren. Het heeft wat te maken met timers en toewijzing van poorten en pins maar wat het nu precies betekend begrijp ik niet. Ik heb ook al eens de datasheet doorgenomen maar kom er nog altijd niet wijs uit.
Wie kan me helpen begrijpen van deze eerste 14 regels.

#include betekent dat de compiler bepaalde files moet includen, meestal definities in een header file (vandaar die .h extensie)

het << teken betekent naar rechts schuiven, dus heeft als effect dat dat bit geset wordt. het | is een logische OR dus in
TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);

worden in feite bit COMOA1 COMOB1 WGM01 en WGMO0 geset.

Bedankt voor je reply

C zelf begrijp ik goed maar C toegepast op de micro nog niet.
Je zegt dat een bit word "geset" maar waarmee of waarom word deze bit geset. Wat is het resultaat hiervan. Het heeft iets met een timer te maken toch?>

In dit geval mag je TCCR0A zien als een register met 8 aan/uit schakelaars. Wanneer een bit in dir register ge'set' wordt (1) of juist ge'reset' wordt (0) veranderd dit het gedrag van de chip zelf.

Om het makkelijker te maken zijn de bit nummers voor verschillende functies ook benoemd (COM0A1, WGM00, etc..). Een bit nummer in deze context verteld waar de te setten bit zich bevind in het register.

Vanaf het weten welk register je moet hebben en het weten wat de naam is van het bitnummer dat je wilt zetten kun je het volgende doen om de waarde van het register aan te passen:

TCCR0A |= 1 << COM0A1

betekend TCCR0A wordt TCCR0A of (1 << COM0A1).

Met 1 << COM0A1 wordt het bitnummer vertaald in het getal dat erbij hoort door 1 te nemen (0000 0001) en die 'bitnummer' keer naar links te schuiven.

'of' of 'OR' of '|' betekend het volgdende:

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

Dus het bitnummer wordt geset of ie al aan staat of niet en de rest van de bits worden met rust gelaten.

Voor meer info over wat TCCR0A en de zijnen voorn functie hebben zul je echt in je datasheet moeten kijken, staat er allemaal in.

OGL bedankt!

Ik begrijp het een stuk beter

Eerste 2 regels betekenen gewoon dat je fast pwm mode aanschakeld.

Zoals ik al zei begrijp ik de meeste logische poorten en C functies.

Maar nu het probleem!

Als ik deze code op mijn atmel met een rode led bak dan knippert het ledje (wel steeds minder fel). Het is toch mogelijk het ledje veel sneller te laten knipperen zodat het lijkt dat het ledje dimt..

Wat doe ik fout?

Heeft iemand nog goede tuts voor toepassingen van een ledje met een avr in c?

Vervang


TCCR0B = (1 << CS02);

eens door


TCCR0B = (1 << CS00);

In het eerste geval ga je de klokfrequentie delen door 256; in het 2e geval wordt ze niet gedeeld.

Op 26 maart 2007 19:56:36 schreef pros:
Vervang


TCCR0B = (1 << CS02);

eens door


TCCR0B = (1 << CS00);

In het eerste geval ga je de klokfrequentie delen door 256; in het 2e geval wordt ze niet gedeeld.

bedankt!
Na dit toegepast te hebben werke het nog altijd niet maar na het volgende te doen wel.

voor
TCCR1B = (1 << CS12) | (1 << WGM12);

na
TCCR1B = (1 << CS10) | (1 << WGM12);

Nu nog twee vragen!

Ik gebruik _delay_ms(20) dit betekend dat ie tussen elke keer dat ie de loop doorloopt X sec wacht.
Hoe lang is dit?
Is het gewoon 20 ms of een andere waarde.

en als tweede vraag heb ik een iets moeilijker probleem.
Ik moet nog een ding weten voordat ik mijn projectje kan starten.
Hoe kan ik met behulp van een druk knop een waarde G laten verhogen (G=G+1)
Gaat dit gewoon dmv de volgende code of moeten er nog meer dingen plaats vinden.

if (pinnummer = 1)
{
G=G+1
}

nogmaals bedankt voor de reply's!

[Bericht gewijzigd door prowl op ]

De meeste vragen heb ik nu wel opgelost om nog eens op school na te vragen.

Maar ik zit nog altijd met een probleem

Ik wel met een drukknop een digitale waarde (g) ophogen

Op school zeiden ze dat ik de interne Pull up van de pin aan moest zetten en die pin als ingang zetten.

Maar niemand wist precies hier de codes voor..

De schakelaar zit op pin PD1

Wie kan me verder helpen de pull up te activeren en de pin declareren als ingang


cbi(DDRD, PD1);  // PD1 = ingang
sbi(PORTD, PD1); // Pull-up R inschakelen

Die "sbi(PORTD, PD1)" heeft een andere functie, indien de pin als ingang geschakeld is. Wil je de pin uitlezen, doe het dan zo:


if (bit_is_clear(PIND, PIND1)) {
    // code...
    }
//of
if (bit_is_set(PIND, PIND1)) {
    // code...
    }

Er zijn nog andere manieren, maar belangrijk is, dat je PIND1 van PIND uitleest, en niet PD1 van PORTD, want dan krijg je niet wat je wil.

pros bedankt voor je reply maar cbi en sbi zijn toch assembley commands en werken niet in c?

[Bericht gewijzigd door Henry S. op ]

Je kunt dit hetzeflde defenieren zoals in de rest van de code:


DDRD = (1<<PD1)

Op 28 maart 2007 22:00:32 schreef prowl:
pros bedankt voor je reply maar cbi en sbi zijn toch assembley commands en werken niet in c?

Als je met avr-gcc werkt:


#include <compat/deprecated.h>

Ik heb zo 't gevoel dat ik weer een uitbrander ga krijgen van Marcel... :-)

Op 28 maart 2007 22:12:10 schreef WilToyo:
Je kunt dit hetzeflde defenieren zoals in de rest van de code:


DDRD = (1<<PD1)

Het werkt!!!!!

Heel erg bedankt beide! (Heb het met beide werkend gekregen.)

Nu kan ik mijn projectje starten:)

Ok nu doet hij het ineens niet meer.... (sorry dat ik zo lastig ben)

zoek de fout :S



#include <avr/io.h>
#include <util/delay.h>
//#include <compat/deprecated.h>

int main()
{
  // fast pwm
  TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
  // timer normale snelheid
   TCCR0B = (1 << CS00);

  //TIMER 1 Fast PWM 8-bit
  TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10);
  // TIMER normale snelheid
  TCCR1B = (1 << CS10) | (1 << WGM12);

  //PWM kanaal als uitgang
  DDRB = (1 << PB3); //OC1A

  // PWM kanalen
  OCR1B = 0; //rood fade


  //schakelaar
  DDRD = (1 << PD1); //PD1 ingang
  PORTD = (1 << PD1); //pull-up PD1

 
  unsigned char G;
  unsigned char i;

  
if (bit_is_clear(PIND, PIND1))

 {
  	
	i=255;
    OCR0A = i;
	_delay_ms(100); 
 
 }

 if (bit_is_set(PIND, PIND1))

 {
  	
	i=0;
    OCR0A = i;
	_delay_ms(100); 
 
 }


}

Op 28 maart 2007 22:27:11 schreef pros:
[...]
Ik heb zo 't gevoel dat ik weer een uitbrander ga krijgen van Marcel... :-)

Haha, ik probeerde me juist in te houden :-)

@prowl


if (bit_is_clear(PIND, PIND1))

maak daar eens van


if (bit_is_clear(PIND, PD1))

Gaf die PIND1 geen compiler warning ?

Overigens werkt dit maar heel kort. Je scant de poort 1 maal en dan is het programma afgelopen, dat is vast niet de bedoeling. Plaats het scannen van de poort eens in een lus.

[Bericht gewijzigd door Marcel op ]

hij gaf geen compiler waarschuwing.

Ik heb met "goto" een sprong terug gemaakt tot net voor het scannen maar het werkt nog steeds niet...

Kan dit storing zijn>?

Op 28 maart 2007 22:56:07 schreef prowl:


// Beetje ingekort
unsigned char i;

if (bit_is_clear(PIND, PIND1)) {
    i = 255;
    OCR0A = i;
    _delay_ms(100);

}

if (bit_is_set(PIND, PIND1)) {
    i = 0;
    OCR0A = i;
    _delay_ms(100);

}

Dat maakt weinig zin IMHO. Druk je de toets in, dan neemt i een bepaalde waarde aan. Los je de toets terug, dan neemt i onmiddelijk een andere waarde aan.
Als je i zowel wil verhogen als verlagen, heb je 2 toetsen (of een schakelaar) nodig.
Of mis ik iets?

Op 28 maart 2007 23:20:52 schreef prowl:
hij gaf geen compiler waarschuwing.

Ik heb met "goto" een sprong terug gemaakt tot net voor het scannen maar het werkt nog steeds niet...

Kan dit storing zijn>?

"goto" in c?, volgens mij kan het wel, maar eerlijk gezegd heb ik het nog nooit gezien. Zo'n goto is zooo onoverzichtelijk. Je kan zo van een stuk willekeurig naar een ander deel van je programma springen. Wat is er mis met de standaard while of for loop.

En pros, volgens mij mis je niets.

Het is een test dus ik heb inderdaad niet netjes geprogt.
Een while lus of een goto hebben hetzelfde effect alleen is het wat minder net

Het programmatje wat hieronder staat is ook een test

Hieraan kon ik zien of de drukknop daadwerkelijk werkte door het ledje volledig aan (255) of uit (0) te zetten.

Maar op de een of andere manier werkt dit niet.
klasgenoot die nu naast me zit en ook wat verstand heeft van atmel snapt het ook niet (op het warrige programmeren na..)