Anoniem
Hallo,
Ik heb het volgende stukje code geschreven (bij elkaar geplukt). De bedoeling was dat een tiptoets aangesloten van PA1 naar de GND met een pullup zou worden uitgelezen en aan de hand daarvan een led aan dan wel uit zou worden geschakeld (gesitueerd op PA0). Voor zover ik weet werkt de if-else statement wel. maar de rest weigert dienst.
#include <avr/io.h>
#include <util/delay.h>
int main()
{
PORTB = 0b00000001;
while(1)
{
if ( PA1 == 0 )
{
PORTA |= (1 << PA0);
}
else
{
PORTA &= ~(1 << PA0);
}
}
return 0;
}
Ik denk zelf dat het fout gaat bij het instellen van de poorten (input/output instellen). Heeft er iemand een goede beschrijving over het definiëren van de poorten in C? of aanraders tot het werkend maken van mijn code?
Alvast bedankt.
RES
RES
Zonder ontdender code (of hardwarematige ontdender) werkt het niet goed.
Werk het wel als je eerst het tiptoets ingedrukt houdt en dan pas de AVR inschakelt? Zo ja, dan is het de dender afkomstig van de tiptoets die roet in het eten gooit.
Anoniem
Op 17 december 2008 18:53:53 schreef RES:
Zonder ontdender code (of hardwarematige ontdender) werkt het niet goed.
Werk het wel als je eerst het knopje ingedrukt houdt en dan pas de AVR inschakelt? Zo ja, dan is het de dender afkomstig van de schakelaar die roet in het eten gooit.
Nee. Maar ik denk dat het flink wat te maken heeft met mijn poort initialisatie. Want daar snap ik vrij weinig van.
Het valt me trouwens wel op dat er veel minder basistutorials zijn voor AVR's dan voor PIC's.
maak van PORTB maar eens DDRB
DDRB = poorten in of uitgangen maken.
PORTB = Poort Hoog of Laag maken. (*en pullups aan/uit)
Eerst stel je DDRA. De datarichtings register 0 is input en 1 is output.
Dan stel je de pull-up in met PORTA
De pull-ups worden geactiveert met een 1 te schrijven naar de juiste bit van PORTA.
Deze regsister wordt ook gebruik om output te setten.
#include <avr/io.h>
#include <util/delay.h>
int main()
{
DDRA = 0b00000001;
//of
DDRA = (1<<PA0);
//Dit moet PORTA worden
PORTA = 0b00000001;
//of
PORTA = (1<<PA1);
while(1)
{
if (((PINA>>PA1) & 0x01) == 0x00)
{
PORTA |= (1 << PA0);
}
else
{
PORTA &= ~(1 << PA0);
}
}
return 0;
}
Als een ingang wilt uitlezen dan doe je dat met het PINA register. PA0 stelt alleen de waarde 0 voor. PA7 dus 7.
#define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01)
Dit is een macro die kijk of die pin hoog is.
while(1)
{
if (!IsPinHigh(PINA,PA1))
{
PORTA |= (1 << PA0);
}
else
{
PORTA &= ~(1 << PA0);
}
}
return 0;
}
Dit is iets leesbaarder.
MvG
Robin
Edit Ik schrijf te traag
Anoniem
#include <avr/io.h>
#include <util/delay.h>
#define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01)
int main()
{
DDRA = 0b00000010; //interne pull-up aan op PA1
PORTA = 0b00000001; //PA0 is een output de rest is input
while(1)
{
if ( !IsPinHigh(PINA,PA1) )
{
PORTA |= (1 << PA0);
}
else
{
PORTA &= ~(1 << PA0);
}
}
return 0;
}
Heb ik nu, de led brand nu echter zwakjes. Zie ik iets over het hoofd?
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Init is fout. Je wil dit, denk ik:
PORTA = 0b00000010; // Pull-up voor PA1 activeren
DDRA = 0b00000001; // PA0 = uitgang
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Op 17 december 2008 19:01:47 schreef robint91:
#define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01)Dit is een macro die kijk of die pin hoog is.
[/code]
Dat is geen slimme macro. De bit shift vindt namelijk pas plaats wanneer je de instructie uitvoert, de compiler kan hier niet optimaliseren. Schrijf het liever zo (ook de AVR standaard als je kijkt naar voorbeelden van Atmel)
if(PINA & (1 << PA0))Het deel (1 << PA0) wordt tijdens compileren al bepaald en zal dus nooit door de AVR worden uitgevoerd, die hoeft alleen nog maar een bitwise and te doen.
Overigens heeft AVR libc hier zelf al een macro voor nml. bit_is_set(PORTx, Pxn)
http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html Nog een reden om die niet zelf te schrijven.
Anoniem
Op 17 december 2008 19:19:22 schreef pros:
Init is fout. Je wil dit, denk ik:PORTA = 0b00000010; // Pull-up voor PA1 activeren DDRA = 0b00000001; // PA0 = uitgang
Nu werkt ie.
PORTX is dus om de pullups aan/uit te zetten.
DDRX = om de functie van de pinnen in te stellen
@Marcel:
Ik begrijp deze notatie echter niet helemaal (mede door mijn gebrekkige kennis van C denk ik)
if(PINA & (1 << PA0))
en
PORTA |= (1 << PA0);
en
PORTA &= ~(1 << PA0);
Anoniem
if (bit_is_set(PORTA, PA1))Als dit klopt, dan werkt het niet zoals ik het wil laten werken.
[Bericht gewijzigd door Anoniem op (83%)]
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Op 17 december 2008 19:40:40 schreef Peter Rus:
PORTX is dus om de pullups aan/uit te zetten.
Enkel als de pin als ingang geschakeld is! Anders maak je de pin "hard" hoog (of laag).
Er is ook nog een bit_is_clear(PORTx, Pxn) macro.
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Op 17 december 2008 19:43:55 schreef robint91:
@marcel(PINA & (1 << PA0))==
(PINA == 0b00000001);Dit is het zelfde.
Nee, dat is zeker niet hetzelfde. De eerste code is een bitwise and, de tweede een vergelijking.
Een kleine uitleg, ook voor Peter.
PA0 t/m PA7 zijn bit definities (ookwel constanten)
In de AVR libc zijn deze gedefineert als
PA0 = 0
PA1 = 1
PA2 = 2
etc...
Het zijn gewoon de bit nummers van een poort. Door het getal 1 met het bit nummer naar links te schuiven verkrijg je de bit waarde. << is in C een bitshift naar links en >> naar rechts.
Lees meer http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/bitshift.html
(1 << PA0) = 1 (0b00000001)
(1 << PA1) = 2 (0b00000010)
(1 << PA2) = 4 (0b00000100)
(1 << PA3) = 8 (0b00001000)
etc...
De bit waarde kan je gebruiken in vergelijkingen en toekenningen. In het voorbeeld and ik de bit waarde met de poort waarde. Als het bit niet aan is zal de and 0 terug geven anders geeft de and de bit waarde terug. In C is een if() waar zolang de conditie groter is dan 0.
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Op 17 december 2008 19:40:40 schreef Peter Rus:
Ik begrijp deze notatie echter niet helemaal (mede door mijn gebrekkige kennis van C denk ik)if(PINA & (1 << PA0)) en PORTA |= (1 << PA0); en PORTA &= ~(1 << PA0);
In feite gaat het allemaal om spelen met bits. Lees bijvoorbeeld dit eens http://irc.essex.ac.uk/www.iota-six.co.uk/c/e4_bitwise_operators_and_o…
a |= b is een verkorte schrijfwijze voor a = a | b
a &= b is een verkorte schrijfwijze voor a = a & b
Anoniem
Oke, dat verheldert een hele boel.
Ik heb nu hetvolgende:
#include <avr/io.h> #include <util/delay.h> #define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01) //Niet gebruiken, eigenlijk... int main() { PORTA = (1 << PA1); //interne pull-up aan op PA1 (=0b00000010) DDRA = (1 << PA0); //PA0 is een output de rest is input (=0b00000001) while(1) { if (!IsPinHigh(PINA, PA1)) //Niet gebruiken, eigenlijk... { PORTA |= (1 << PA0); } else { PORTA &= ~(1 << PA0); } } return 0; }Ik probeer nu alleen nog bit_is_clear() onder de knie te krijgen.
ik probeerde hetvolgende:
if (bit_is_clear(PORTA, PA1)) { PORTA |= (1 << PA0); } else { PORTA &= ~(1 << PA0); }Maar dat scheen niet te werken en ik ben teruggekeerd naar de door robint91 voorgestelde IsPinHigh() die wel z'n werk doet, maar niet is zoals het hoort (deze laatste is heeft mijn voorkeur). Ook
if (bit_is_clear(PORTA, (1 << PA1)))werkt niet.
En ook dit is opgelost.
en wel als volgt:
if (bit_is_clear(PINA, PA1))
Iedereen mag zich als bedankt beschouwen (:
Als jullie dit als correct beschouwen kan ik nog wel een commentaar-enhanced versie van de code neerzetten, dit kan makkelijk zijn voor anderen met dezelfde vragen. Uw mening graag.
Erelce
**** De beschikbare ruimte van een werkplek is omgekeerd evenredig met de grootte van deze werkplek **** AVR-Oefeningen op Electronics 4 Fun
Op 17 december 2008 18:57:01 schreef Peter Rus:
[...]Het valt me trouwens wel op dat er veel minder basistutorials zijn voor AVR's dan voor PIC's.
dat is zo, in het Nederlands toch.
Op mijn site zie je enkele beginners oefeningen in het Ned.
Binnenkort komen er een heleboel bij, ook met ADC en zo.
Maar als je een beetje Engels of Duits versta zijn er enkele hele goeie tutorials bij. Kijk maar eens in mijn URL-Links.
Ook bij AVR-Freaks zul je veel vinden bij de Newbie Tutorial.
Wat ik ook opmerk is dat er weinig in AVR-Assembly geprogrammeerd wordt...nochtans vind ik dit een gemakkelijke taal eenmaal je sommige dingen beet hebt.
Maar het begin is moeilijk, da's waar.
Het beste leer je door met eenvoudige dingen te beginnen.
Anoniem
Op 17 december 2008 23:57:31 schreef Erelce:
[...]dat is zo, in het Nederlands toch.
Op mijn site zie je enkele beginners oefeningen in het Ned.
Binnenkort komen er een heleboel bij, ook met ADC en zo.
Maar als je een beetje Engels of Duits versta zijn er enkele hele goeie tutorials bij. Kijk maar eens in mijn URL-Links. Ook bij AVR-Freaks zul je veel vinden bij de Newbies Tutorial.
Wat ik ook opmerk is dat er weinig in AVR-Assembly geprogrammeerd wordt...nochtans vind ik dit een gemakkelijke taal eenmaal je sommige dingen beet hebt.
Maar het begin is moeilijk, da's waar.
Het beste leer je door met eenvoudige dingen te beginnen.
Ik heb je site bekeken, maar zag toen dat je inderdaad in assembly progt, dit vindt ik zelf minder fijn (mede ook omdat ik erg veel houdt van functies en klassen).
Op avrfreaks kom ik eerlijk gezegd alleen maar de wat meer geavanceerdere projectjes tegen en basisbeginselen in alleen ASM, op het gebied van C en de basisprincipes van AVR/GCC kan ik m'n draai daar niet vinden.
Op 18 december 2008 00:05:11 schreef Peter Rus:
[...]Ik heb je site bekeken, maar zag toen dat je inderdaad in assembly progt, dit vindt ik zelf minder fijn (mede ook omdat ik erg veel houdt van functies en klassen).
Als het zo nodig in classes moet, wat doe je dan op een μC??
Op avrfreaks kom ik eerlijk gezegd alleen maar de wat meer geavanceerdere projectjes tegen en basisbeginselen in alleen ASM, op het gebied van C en de basisprincipes van AVR/GCC kan ik m'n draai daar niet vinden.
Er staat genoeg in C. Echter, assembly is en blijft de basis.
Maar eh... wellicht een stomme vraag... Waar heb je een tutorial voor nodig? De gemiddelde AVR heeft een stevig uitgekauwde datasheet. Als je dan ook nog ergens een assembly guide vandaan plukt, heb je toch alles wat je nodig zou kunnen hebben?
Wellicht begin je te ingewikkeld. Als je helemaal geen ervaring hebt, begin dan eens met een knipperende LED. Op een nieuwe architectuur doe ik dat nog steeds, alhoewel de LED meestal vervangen wordt door een scoop.
Anoniem
Op 18 december 2008 06:36:59 schreef Marco69:
[...]Als het zo nodig in classes moet, wat doe je dan op een μC??[...]Er staat genoeg in C....
begin dan eens met een knipperende LED. Op een nieuwe architectuur doe ik dat nog steeds, alhoewel de LED meestal vervangen wordt door een scoop.
Ik zeg ook niet persee dat ik klassen wil gebruiken. Maar mijn voorkeur gaat zogezegd uit naar hogere programmeertalen vanwege de tijdsbesparing en het gemak dat het opbrengt.
Een knipperende led is overigens al gelukt
dit was zeg maar mijn les over input op de AVR. De volgende stap wordt denk ik een LCD.
Gatze
Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously
Een goed site voor de avr gcc beginner is deze http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial Daar staan al de antwoorden op die je in het begin had. (wel duits).
Voor assembly heb ik deze veel gebruikt http://www.avr-asm-tutorial.net/avr_en/index.html (engels of duits).