So habe alles soweit am laufen und mit den makefiles verstanden, mc ist angeschlossen und ich kann lesen+schreiben, nur werde ich aus dem tollen tutorial nicht schlau.... ich will im prinzip ein programm schreiben, was die zwei ports der taster auf dem atmega16 ablauscht und wenn taster1 gedrückt wird soll led1 auf 'on' gesetzt werden, wird taster 2 gedrückt, taster auf 'on'. mehr soll erstmal garnicht passieren, das würd mir schon ne riesen freude bereiten... jetzt weiß ich nur nicht, wie ich herausfinde, wie die ports heissen und wie die der leds heissen... (wo schlägt man sowas nach) ? dann weiß ich schonmal das ich folgende header einbinden muss #include <avr/io.h> #include <stdint.h> uint8_t foo; void main(void) { } so das ist dann auch schon alles was ich weiß und weiter komme ich auch einfach nicht, habe mir auf www.atmel.com die atmega16 summary runtergeladen, aber da stht nichts von adressen bzw ports der taster/leds drin... bitte helft mir, das tutorial ist super, aber nen sample-code würde mir mehr helfen.... DANKE DANKE DANKE
Hast du wirklich im AVR-GCC-Tutorial nachgelesen? Dort steht Sample-Code. I/O-Register. Und damit du weist wo sich die Ports hardwaremässig auf deinem µC befinden hilft ein Blick ins Datenblatt, zumeist Seite 2 Pin-Configurations.
Hallo! Das kommt natürlich darauf an, an welchen Port Du Deine Taster bzw. LEDs anschließt. Du kannst sie an Port A oder auch an Port C anschließen, wie Du willst. Wo die Ports sind, siehst Du gleich auf Seite 2 im Datenblatt (Port A hat die Pins 33-40, Port C die Pins 22-29 usw. )Die Ports sind jeweils 8 Bit breit. Ein kleines Beispielprogramm (ohne Taster, nur mit LEDS), es sind 8 LEDs an Port A angeschlossen: #include <avr/io.h> #include <stdint.h> int main(void) { DDRA = 0xFF; /*Port A als Ausgang definieren*/ PORTA = 0x0F; /*LEDs an */ } Mit dem Befehl DDRA legst Du fest, daß der gesamte Port A Ausgang ist. Mi dem Befehl PORTA schickst Du Daten an Port A. Schickst Du eine 0 an einen Pin des Ports, geht die jeweilige LED an, schickst Du eine 1, geht sie aus. Das Beispiel oben bewirk, dass die 4 LEDs an den Pins 37-40 angehen, die 4 LEDs an den Pins 33-36 ausbleiben. Alles klar? Viel Spaß noch! Pete
Anmerkung: Du mußt den Port so mit den LEDs und Widerständen beschalten, wie im Tutorial, also: Portpin -> Widerstand -> Kathode der LED (platte Seite) -> Anode der LED (runde Seite) -> +5V
Du brauchst das complete-Datenblatt, das summary ist für Krämerseelen gedacht, da steht nur Händlerwissen drin. ...
Hi, ok habe alles so gemacht wie ihr gesagt habt (naja ich hoffe doch) also led angeschlossen kathode an PA0 (steht auf der anschlussskizze vom board) und anode an +5v. (Speicher des uc ist leer -> led aus !! dann programm mit winavr (makefile ist richitg!!) makeall gemacht und .hex datei mit ponyprog in uc geladen.... soweit so gut, aber leider geht die led nich an, muss ich das programm dann noch starten oder startet das autom. wenns in den uc geladen wurde... ? hier das programm (keine error beim compilen !!) #include <avr/io.h> #include <stdint.h> void main(void) { DDRA = 0xFF; /*Port A als Ausgang definieren*/ PORTA = 0x0F; /*LEDs an */ } also unabhängig vom programm tut die led wenn ich die kathode an PA5 anschliesse, also die led funzt(nur wieso ist port PA5 gesetzt, bevor ich das programm geldaen hatte ??)
Ja, das ist genau so, wie es sein soll. PORTA = 0x0F bedeutet die Bits 0-3(PA0-PA3) werden auf 1 gesetzt -> LED aus, die Bits 4-7(PA4-PA7) werden auf 1 gesetzt -> LED an. Schließt Du die LED an die Pins PA0-PA3 an, leutet sie nicht, schließt Du sie an die Pins PA4-PA7 an, leuchtet sie. -> It works! Besser ist vielleicht folgende Schreibweise: DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4); besser zu verstehen als die Hex-Darstellung, macht aber genau dasselbe.
>>DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << >>DDB4); Soll natürlich statt DDRB PORTA heißen, statt DDB0 PB0 usw...
Verdammt nochmal! Immer noch falsch, sorry. Ist glaub ich schon zu spät für mich... So ist's (hoffentlich ;-) richtig: PORTA = (1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 << PA4); Gute Nacht!
tut leider nicht, denn sie geht ja nicht an :) bevor ich das programm überhaupt compiliert habe, habe ich die led angeschlossen und zu testzwecken bin ich mit der kathode mal an den ports entlang um zu sehen ob was gesetzt ist... war ja auch an PA5.. also hab ich an die led an PA0 angeklemmt und das prog compiliert: #include <avr/io.h> #include <stdint.h> void main(void) { DDRA = 0xFF; /*Port A als Ausgang definieren*/ //PORTA = 0x0F; /*LEDs an */ PORTA = 0x1F; /*LEDs aus */ } und danach mit #include <avr/io.h> #include <stdint.h> void main(void) { DDRA = 0xFF; /*Port A als Ausgang definieren*/ PORTA = 0x0F; /*LEDs an */ //PORTA = 0x1F; /*LEDs aus */ } aber da tut sich nichts an PA0 bleibt die led stets aus und an PA5 bleibt sie stets an.... ?? woran kann das liegen ?? vielleicht doch makefile falsch ?
was ich eingestellt habe beim MFile programm Name der datei superprog.c (ohne .c natürlich) MCU type (atmega16) unter avrdude programmer avrisp unter port lpt1 sollte ja alles richtig sein !! oder
Also wenn ich hingehe und lösche den gesamten inhalt ausm uc und lade dann folgendes programm in den uc : #include <avr/io.h> #include <stdint.h> void main(void) { DDRA = 0xFF; /*Port A als Ausgang definieren*/ PORTA = (0 << PA0) | (0 << PA1) | (0 << PA2) | (0 << PA3) | (0 << PA4); } dann gehen die drei leds an (grün an PA0, Gelb an PA4 und rot an Pa5) aber wie kriege ich sie wieder aus ?? habe das nun konventionell gelöst, und alles gelöscht (mit FFFF überschrieben).... wenn ich folgende zeile verwende geht es nicht PORTA = (1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 << PA4); ??????? gähn und gute nacht für heute :)
@Studiologe Nichts für ungut, aber Du solltest Dir etwas Zeit nehmen und C (die Sprache) etwas besser kennenlernen. Besorge Dir ein C Buch und arbeite zumindest mal die ersten Kapitel durch, damit Du weisst, wie ein C-Prog aufgebaut werden muss. Dann nehme das Datenblatt zum Controller und schaue nach, was welche Bits wo machen. Parallel zu allem ist das GCC Tutorial ganz hilfreich, da es die Kombination von C und AVR darstellt. Aller Anfang ist, zumindest nicht leicht; und ein kleines Erfolgserlebnis ist vielleicht motivierend :-) Hier das Beispiel für CodevisionAVR (auch eine C Entwicklungsumgebung, nicht Kostenlos ausser der Demo) und einem ATTiny2313: #include <tiny2313.h> #include <io.h> int main(void) { DDRB=0xff; /*PortB ist Ausgang*/ PORTB=0x00; /*LEDs aus*/ DDRD=0x00; /*PortD ist Eingang*/ PORTD=0x00; /*Pullups aus*/ while (1) /*Endlosschleife starten*/ { if(PIND.1==1) /*wenn D.1 einen High Pegel bekommt,dann*/ { PORTB.1=1; /*LED an B.1 EIN */ } if(PIND.2==1) /*analog zu obigen, nur eben mit D.2 und B.2*/ { PORTB.2=1; } PORTB=0x00; /*LEDs an PortB alle ausschalten */ } /*Endlosschleife schliessen*/ return 0; } /*Ende von main()*/ Das Programm ist veryquickanddirty aber läuft (ist auch schon spät bzw. früh)! Gruß
Ach ja nochwas: Vielleicht ist es ganz hilfreich für Dich die binäre Schreibweise zu nehmen, damit kann man sich vieles einfach besser vorstellen: Anstatt PORTB=0xff geht auch PORTB=0b11111111; anstatt PORTB.1=1 geht auch PORTB=0b00000001; analog dazu PORTD.5=1 geht auch PORTD=00010000. Man zählt quasi von hinten nach vorne. Müsste auch in GCC gehen. Gruß
Sorry, Fehler: Bei der binären Schreibweise alle einsen eine Stelle nach links wegen: 7 6 5 4 3 2 1 0
Jo moin, also c-Kenntnisse sollte ich wie allgemein programmierkenntnisse genug haben, mir is das alles nur noch neu mit der ganzen hex sache und der ports, habe vorher nur wenig mit hex gearbeitet :) hab immer davor gedrückt, also die binäre schreibweise ist echt besser zu verstehen, werds gleich mal ausprobieren, werde mich sonst nochmal melden (und euch hoffentlich nicht nerven) aber am anfang erstmal ein erfolgserlebnis zu haben ist echt motivierend ! war gestern abend schon recht große freude, als die leds angingen :) nur aus gingen sie halt nicht mehr probiere ich gleich mal aus :) also danke leute !!
Hi folks ! also habe nun eine Ampelschaltung programmiert.... habe drei LEDs angeschlossen, alle an port A (rot an 0, gelb an 1 und grün an 2) und folgendes programm geschrieben: #include <avr/io.h> #include <stdint.h> void main(void) { DDRA = 0xFF; /*Port A als Ausgang definieren*/ while(1) { PORTA=0b11111110; //rote LED an PORTA=0b11111101; //gelbe LED an PORTA=0b11111111; //alle LEDs aus PORTA=0b11111011; //grüne LED an PORTA=0b11111111; //alle LEDs aus PORTA=0b11111101; //gelbe LED an PORTA=0b11111111; //alle LEDs aus PORTA=0b11111110; //rote LED an } } so schön so gut, doch leider leuchten immer alle LEDs, was ich mir dadurch erkläre, das das Programm zu schnell durchlaufen wird... also muss ne sleep routine her !, nur wie mach ich das, habe da irgendwas im script gelesen, mit quarz(um eine genaue zeitsteuerung zu erhalten). also meine fragen: 1) wie finde ich raus, was fürn quarz bei meinem board den takt vorgibt? 2)welche bibs muss ich zusätzlich einbinden (time.h???) 3)wie lautet der befehl, welche parameter übergebe ich ?(Sleep(6000)) (ms angabe??) 4)muss ich zusätzlich zum ganz normalen sleep noch dem controller was anderes mitteilen, wegen der taktung...? :=Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke,
Ja da hast du recht, das Programm wird zu schnell durchlaufen. Das sieht für das menschliche Auge aus, als ob sie die ganze Zeit leuchten würden aber eigentlich blinken sie ganz schnell. Da musst du dir wohl ne Art Verzögerung einfallen lassen. Suche mal im Netz nach Delay-Routinen oder so. Ich habe für meinen Atmega32 eine gefunden, weiß aber nicht ob sie bei dir funktionieren würde. Ich kann sie dir gerne mal geben aber dann müsstest du deinen Takt auf 4 MHz ändern(oder die Routine umschreiben). Möchtest du sie haben? Du brauchst nicht zwingend einen Timer aber das wäre auch nicht so schlimm :p (bin da gerade selber am Basteln, Timer funktioniert aber leider nicht genau wie ich es möchte,leider zu ungenau. Für deine Anforderung würde er aber genügen)
ja wäre ganz gebräuchlich :) aber wie ändere ich den takt, habe im avr-gcc-tutorial nur was über sleep-routinen gefunden, also die bin dafür hab ich eingebunden, leider funktioniert der sleep modus (sleep(6000)) nicht, weil die routinen für was anderes gedacht sind (teile des uc in den sleepmodus zu versetzen und nicht den programmfluss kurzzeitig einzufrieren)... trotzdem danke
entweder "bastelts" du dir ne Ablaufsteuerung mit einem Timer, dessen Zeit du für jede Ampelphase einstellst, oder du benutzt erst mal die "Schweinemethode" mit For-schleifen (quick'n'dirty). Bei der Timer-Variante kann man den Timer noch für andere schöne Sachen (Tastenentprellung u.ä.) benutzen.
@Studiologe
Guten Morgen,
was Du benötigst ist ein sog. delay.
#include <delay.h>
....
delay_ms(wert)
....
Natürlich kannst Du auch einen Timer verwenden, aber versuchs erst mal
mit delay. Kann sein dass es auch delay_us(wert) heisst. Schau einfach
mal in die delay.h rein.
> also c-Kenntnisse sollte ...
Eine Andere Möglichkeit ist, dass Du Dir eine Funktion bastelt, die Dir
eine Zeitverzögerung im größeren Maß bringt. Pass nur auf, dass der
Compiler sie nicht wegoptimiert.
Gruß
Also diese Routine verwende ich immer mit meinem Atmega32 und 4 MHz Takt. void delay_ms(unsigned short ms) /* delay for a minimum of <ms> */ /* with a 4Mhz crystal, the resolution is 1 ms */ { unsigned short outer1, outer2; outer1 = 200; while (outer1) { outer2 = 1000; while (outer2) { while ( ms ) ms--; outer2--; } outer1--; } }
Habs schon gelöst ! die idee mal in die util/delay.h reinzusehen brachte den absoluten durchbruch.... der befehl lautet dann _delay_ms(250); also sollte rein logisch folgender code ein delay von 1 sekunde bringen _delay_ms(250); _delay_ms(250); _delay_ms(250); _delay_ms(250); tuts aber wegen der taktung nicht !(habs mit 10 sekunden ausprobiert) habe dafür ne funktion geschrieben, der ich die direkte anzahl an sekunden übergeben und dann durchläuft der ne schleife, in der er den zähler von angegebner sekundenzahl pro durchlauf um 0.25 herabsetzt. übermittle ich ne 1 durchläuft er die schleife 4 mal (bis er bei 0 ist) und führt jedes mal das _delay_ms(250); aus !! wie kann ich denn nu herausfinden, was für ne taktung mir der quarz auf meinem atmega16 liefert ? in meinem armseligem datenblatt steht es nicht ! und wie setze ich das dann mit dem takt so, das eine sekunde auch wirklich eine sekunde wird :)
Kannst du nicht mittels der Fuse-bits den internen Takt festlegen? In winAVR geht das jedenfalls und ich bin mir sicher, daß geht auch mit deinem Programm. Viele hier bevorzugen das sogar.
> wie kann ich denn nu herausfinden, was für ne taktung mir der > quarz auf meinem atmega16 liefert Hast Du denn einen Quarz angeschlossen? (Der Chip selbst hat keinen echten Quarz eingebaut, wohl aber einen Schwingkreis) Wenn ja, dann steht auf dem Quarz drauf, wie schnell er tickt. Wenn nein: Hast Du an den Fuses gedreht? Wenn ja: Ueber die Fuses kann man eine andere Frequenz einstellen. Dann musst Du schon selbst wissen auf wieviel Du ihn gestellt hast. Wenn nein: Dein Mega16 läuft so wie Atmel ihn ausliefert. Und das bedeutet: 1 Mhz Mehr oder weniger. Der interne Taktgenerator ist nicht sehr genau und ist u.A. von der Temperatur, der Versorgungsspannung und dem Wasserstand im Rhein abhängig. Mann kann diesen Takt mit OSCAL (Oscillator callibration) noch genauer fine-tunen. Wenn Dir allerdings ein exaktes Timing wichtig ist, dann ist das beste Du schliesst einen Quarz oder einen externen Oszillator an.
>ist u.A. von der Temperatur, der Versorgungsspannung und dem >Wasserstand im Rhein abhängig. komisch, bei uns das eher von Ost- und Westwind abhängig...
Hab mal ne ganz dumme Frage dazu: Wisst ihr ungefähr, inwieweit sich der Takt eines µC ändern kann(auf eure netten Anspielungen bezogen). Mich würde mal interessieren, wie stark er von den angegebenen Taktraten abweicht, aufgrund Temperatur usw..
Dazu guckst du am besten in das jeweilige Datenblatt; da gibt es so schöne Graphen (oder inzwischen mit "f"?), die das Frequenzverhalten zur Temperaturänderung angeben.
Ok, den hinteren Teil des Datenblattes kann man aber auch ganz schnell übersehen ;)
Nee hab keinen Oszillator angeschlossen und von Fusebits hab ich schonmal was gehört, aber dran rumgedreht mit sicherheit nicht... wüsste auch garnicht wo... 1) also kann ich das alles garnicht auf sekunden genau bringen ohne oszillator ?? 2) auf dem board sind jede menge ports, gibt es so kleine steckerchen, dafür ?? habe das nu so gelöst, das ein käbelchen vorne ein wenig abisoliert habe und dann halt mit nen bisschen lötzinn "verstärkt" habe, aber wirklich tight sitzen die nicht in den ports... gibts da also so steckerchen, an die ich meine kabel löten kann... ??
Wenn ich wüsste, welches Board du hast...(Steckbrett?) Sonst bietet sich Klingeldraht an; oder halt Steckverbinder,die dafür vorgesehen sind.
habe ein Atmel ATMega16 Entwicklungsboard... nur wie heissen diese kleinen steckerchen ?? einfach portpinns oder sowas ? hab schon gegoogelt und bei conrad geguck finde aber nichts gescheites... weil mir der name davon fehlt :)
keine ahnung wie der name lautet hab es bei ebay gekauft und da waren nur zwei zettel dabei, auf denen nichts von name steht und auf dem board selber steht auch nur atmega16 !! aber andere frage zu tastern, habe ausm tutorial folgendes programm gebastelt... #include <avr/io.h> #include <avr/io.h> #include <stdint.h> #include <util/delay.h> inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) { if ( !(*port & (1 << pin)) ) { _delay_ms(100); if ( !(*port & (1 << pin)) ) { _delay_ms(100); return 1; } } return 0; } void main(void) { DDRD &= ~( 1 << PD0 ); PORTD |= ( 1 << PD0 ); while(1) { if (debounce(&PIND, PD0)) { PORTA = 0b11111000; } } } so an +5v draht zum taster, vom taster draht zum PORTD 0, dann led an PORTA 0, wird der taster kurz gedrückt soll led an, wird er wieder gedrückt, led aus... aber tut einfach nicht, im tut steht: Der Anschluss mechanischer Kontakte an den Mikrocontroller gestaltet sich ebenfalls ganz einfach, wobei wir zwei unterschiedliche Methoden unterscheiden müssen (Active Low und Active High) naja finde ich allerdings bisher noch nicht :P
> keine ahnung wie der name lautet hab es bei ebay gekauft und da > waren nur zwei zettel dabei, auf denen nichts von name steht und > auf dem board selber steht auch nur atmega16 !! Mach doch mal ein Photo. Es gibt Unmengen von verschiedenen Steckern und Buchsen. > so an +5v draht zum taster, vom taster draht zum PORTD 0, dann led > an PORTA 0, wird der taster kurz gedrückt soll led an, wird er > wieder gedrückt, led aus... Aber nicht mit diesem Programm. Zunaechst zur Hardware. Wie man Taster und Led's richtig anschliesst, siehst Du im Assembler-Tutorial im Abschnitt: I/O Grundlagen. Da muessen also mindestens noch ein paar Widerstaende rein. Oder Du sparst dir die Widerstaende am Taster und aktivierst die AVR-internen Pull-up Widerstaende. Dann muessen die Taster aber nach Masse schalten und nicht nach 5V. Hast Du ein Multimeter? Wenn ja, dann klemm das mal am Chip an den Port-Pin. Dort muessen sauber 5V bzw. 0V anliegen, je nachdem ob der Taster gedrueckt ist oder nicht. Bei den Led's hast Du nicht soviel Auswahl: Mach Dir mal folgende Schaltung Draht -> 330 Ohm Widerstand -> Led -> +5V Wenn Du jetzt den Draht an Masse haelts, dann muss die Led leuchten. Tut sie das nicht, ist die Led falsch rum. Also umdrehen, jetzt muss sie leuchten. Danach klemmst Du die Led an den Port - Pin. So. Jetzt ist die Hardware fertig und Du kannst loslegen mit dem Programm. Versuch zunaechst einfach mal die Led nur einschalten bzw. ausschalten. Achtung: So wie die Led geschaltet ist, muss man einen 0 am Portpin ausgeben, damit die Led leuchtet. Und dann kannst Du an den Taster gehen. Ignorier zunaechst einfach mal das Tastenprellen. Ziel: Ist der Taster gedrueckt soll die Led leuchten. Ist der Taster nicht gedrueckt, soll die Led ausgehen. Wenn Du das hast (als zusaetzliche Uebung auch mal umgekehrt: Taster gedrueckt -> Led aus; Taster nicht gedrueckt -> Led ein ), dann hast Du eigentlich schon genug gelernt, dass Dir das Tastenentprellen und Umschalten der Led mit dem Taster keine Schwierigkeiten machen sollten. Aber erst musst Du die Hardware in Ordnung bringen.
Sehe grade: Das heist 'AVR-Tutorial' und nicht 'Assembler-Tutorial' http://www.mikrocontroller.net/tutorial/io-basics
Hallo, ich will nun nicht klugsch...., aber ich bin der Meinung, das es besser ist, erst mal mit Assembler anzufangen um den Controller erst mal kennenzulernen. Das Datenblatt sollte dabei immer griffbereit sein, so das man die einzelnen Bestandteile des Controllers mal austesten kann. (Timer,Counter,PWM,ADC usw.) Wenn man es geschafft hat in Assembler eine LED blinken zu lassen, dann kann man daran denken das auch in C zu programmieren. Es grüsst, Arno
Ich habe noch etwas vergessen, zum programmieren und Testen der Versuche in Assembler eignet sich hervorragend das AVR-Studio. Damit kann man auch sehr schön und vor allem ungefährlich die Fuses setzen, für den Takt zB. Es grüsst, Arno
Hallo habe nun alles so wie ich es in den Tutorials gefunden habe angeschlossen. Also +5V -> R(10kOhm) -> PORTD0 GND -> Taster -> PORTD0 +5V -> R(330Ohm) -> grüne LED -> PORTA0 +5V -> R(330Ohm) -> rote LED -> PORTA1 so wird nun der Taster gedrückt, soll die LED an PORTA0 (grün) leuchten und die rote soll aus sein, wird der Taster wieder losgelassen, grüne LED aus, rote wieder an.... hier das Programm: #include <avr/io.h> #include <stdint.h> void main(void) { DDRA = 0xff; //Port A als Ausgang definieren DDRD = 0x00; //PortD ist Eingang PORTA = 0b11111111; //alle LED aus while(1) { if(PORTD == 0b11111110) { PORTA = 0b11111110; //grüne LED an } else { PORTA = 0b11111101; //rote LED an } } } Aber nur die rote LED leuchtet und das unabhängig ob ich den Schalter drück oder nicht :( Könnt ihr mir sagen, woran das liegt ?? DANKE ihr seid definitiv die allerbesten :D !!!!!!
> if(PORTD == 0b11111110) PortD ist auf Eingabe geschaltet ! if( PIND == 0b11111110 ) Bei Einem Port der auf Eingabe geschaltet wurde, werden ueber die PORTx die Pull-Up Widerstaende ein-/ausgeschaltet. Dein Code hat also nachgesehen, ob die Pull-Up Widerstaende aktiviert wurden und benutzt das Ergebnis um eine LED einzuschalten :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.