Atmega8-Mikrocontroller. Atmega8-Programmierung für Anfänger. AVR-Mikrocontroller. Programmierung für Einsteiger Mikrocontroller atmega8 Schulung

Dezember 2015

1. Vorteile der vorgeschlagenen Methode

Geräteschaltungen auf Basis von Mikrocontrollern (MCUs) zeichnen sich in der Regel durch die Kombination zweier schwer kombinierbarer Eigenschaften aus: maximale Einfachheit und hohe Funktionalität. Darüber hinaus kann die Funktionalität in Zukunft geändert und erweitert werden, ohne dass Änderungen an der Schaltung erforderlich sind – allein durch einen Austausch des Programms (Flashen). Diese Merkmale erklären sich aus der Tatsache, dass die Entwickler moderner MKs versucht haben, alles, was ein Entwickler benötigen könnte, auf einem Chip unterzubringen elektronisches Gerät- zumindest so viel wie möglich. Infolgedessen verlagerte sich der Schwerpunkt von Schaltungen und Installation hin zu Software. Durch den Einsatz von MK muss der Schaltkreis jetzt weniger mit Teilen „beladen“ werden und es gibt weniger Verbindungen zwischen Komponenten. Dies macht die Schaltung natürlich sowohl für erfahrene als auch unerfahrene Elektronikingenieure attraktiver für die Wiederholung. Aber wie immer muss man für alles bezahlen. Auch dies verlief nicht ohne Schwierigkeiten. Wenn Sie einen neuen MK kaufen, ihn in einen aus wartungsfähigen Teilen korrekt zusammengesetzten Stromkreis einbauen und Strom anlegen, funktioniert nichts - das Gerät funktioniert nicht. Der Mikrocontroller benötigt ein Programm.

Auch hier scheint alles einfach zu sein – im Internet findet man viele Schemata mit kostenloser Firmware. Aber hier gibt es einen Haken: Die Firmware muss irgendwie in den Mikrocontroller „hochgeladen“ werden. Für jemanden, der dies noch nie zuvor getan hat, wird eine solche Aufgabe oft zum Problem und zum größten Abstoßungsfaktor, der ihn oft dazu zwingt, die Freuden der Verwendung von MK aufzugeben und nach Schemata zu suchen, die auf „lockerer“ und starrer Logik basieren. Aber alles ist nicht so kompliziert, wie es auf den ersten Blick scheinen mag.

Nach der Analyse der Veröffentlichungen im Internet können Sie feststellen, dass dieses Problem am häufigsten auf zwei Arten gelöst wird: durch den Kauf eines fertigen Programmierers oder durch die Herstellung eines selbstgebauten. Gleichzeitig sind veröffentlichte Schaltkreise selbstgebauter Programmierer sehr oft unverhältnismäßig komplex – viel komplexer als eigentlich nötig. Wenn Sie vorhaben, den MK jeden Tag zu flashen, ist es natürlich besser, einen „coolen“ Programmierer zu haben. Wenn jedoch von Zeit zu Zeit die Notwendigkeit eines solchen Verfahrens auftritt, können Sie ganz auf einen Programmierer verzichten. Nein, natürlich geht es nicht darum, dies mit der Kraft des Denkens zu lernen. Das heißt, wenn wir verstehen, wie der Programmierer beim Schreiben und Lesen von Informationen im Programmiermodus mit dem Mikrocontroller interagiert, können wir die verfügbaren Tools für einen umfassenderen Zweck nutzen. Diese Tools müssen sowohl die Software- als auch die Hardwareteile des Programmierers ersetzen. Die Hardware muss eine physische Verbindung zum MK-Mikroschaltkreis sowie die Möglichkeit bieten, logische Ebenen an seine Eingänge anzulegen und Daten von seinen Ausgängen zu lesen. Der Softwareteil muss den Betrieb des Algorithmus sicherstellen, der alle notwendigen Prozesse steuert. Wir weisen auch darauf hin, dass die Qualität der Aufzeichnungsinformationen im MK nicht davon abhängt, wie „cool“ Ihr Programmierer ist. Es gibt kein „besser aufgenommen“ oder „schlechter“. Es gibt nur zwei Möglichkeiten: „registriert“ und „nicht registriert“. Dies liegt daran, dass der Aufnahmevorgang im Kristall direkt vom MK selbst gesteuert wird. Sie müssen es lediglich mit qualitativ hochwertigem Strom versorgen (keine Störungen oder Welligkeiten) und die Schnittstelle richtig organisieren. Wenn die Ergebnisse der Testauslesung keine Fehler ergeben, ist alles in Ordnung – Sie können den Controller bestimmungsgemäß verwenden.

Um ein Programm in den MK zu schreiben, ohne einen Programmierer zu haben, benötigen wir einen USB-RS232TTL-Port-Konverter und außerdem. Mit dem USB-RS232TTL-Konverter können Sie über einen USB-Port einen COM-Port erstellen, der sich vom „echten“ nur dadurch unterscheidet, dass seine Ein- und Ausgänge TTL-Logikpegel verwenden, also eine Spannung im Bereich von 0 bis 5 Volt ( Mehr erfahren Sie im Artikel „“). Auf jeden Fall ist es sinnvoll, einen solchen Konverter in Ihrem „Haushalt“ zu haben. Wenn Sie also noch keinen haben, lohnt sich die Anschaffung auf jeden Fall. Was die logischen Ebenen betrifft, ist TTL in unserem Fall sogar ein Vorteil gegenüber einem normalen COM-Port, da die Ein- und Ausgänge eines solchen Ports direkt an jeden mit 5 V versorgten Mikrocontroller angeschlossen werden können, einschließlich ATtiny und ATmega. Versuchen Sie jedoch nicht, einen normalen COM-Port zu verwenden – dieser verwendet Spannungen im Bereich von -12 bis +12 V (oder -15...+15 V). In diesem Fall ist eine direkte Verbindung zum Mikrocontroller nicht akzeptabel!!!

Die Idee, ein Skript für das Programm Perpetuum M zu erstellen, das die Funktionen des Programmierers implementiert, entstand nach der Lektüre einer Reihe von Veröffentlichungen im Internet, die bestimmte Lösungen für die MK-Firmware anbieten. In jedem Fall wurden schwerwiegende Mängel oder übermäßige Schwierigkeiten festgestellt. Oft bin ich auf Programmierschaltkreise gestoßen, die einen Mikrocontroller enthielten, und gleichzeitig wurden ganz ernste Ratschläge gegeben wie: „… und um den Mikrocontroller für diesen Programmierer zu programmieren, brauchen wir … das stimmt – einen anderen Programmierer!“ Als nächstes wurde vorgeschlagen, zu einem Freund zu gehen und danach zu suchen kostenpflichtiger Service usw. Auch die Qualität der für diese Zwecke im Netzwerk verbreiteten Software war nicht beeindruckend – es wurden viele Probleme sowohl bei der Funktionalität als auch bei der „Trübung“ der Benutzeroberfläche festgestellt. Es nimmt oft viel Zeit in Anspruch, die Bedienung eines Programms zu verstehen – es muss selbst für die Ausführung der einfachsten Aktionen erlernt werden. Ein anderes Programm kann zwar lange und fleißig etwas erledigen, aber dass nichts in den MK geschrieben wird, erfährt der Anwender erst nach vollständiger Fertigstellung der gesamten Firmware und anschließendem Testauslesen. Außerdem tritt folgendes Problem auf: Der Benutzer versucht, seinen MK aus der Liste der unterstützten Quarze auszuwählen, dieser ist jedoch nicht in der Liste. In diesem Fall können Sie das Programm nicht nutzen – eine Aufnahme in die Liste der fehlenden MKs ist in der Regel nicht vorgesehen. Darüber hinaus sieht die manuelle Auswahl eines Controllers aus der Liste seltsam aus, wenn man bedenkt, dass der Programmierer in vielen Fällen den MK-Typ selbst bestimmen kann. All dies wird nicht gesagt, um bestehende Produkte zu beschmutzen, sondern um den Grund für das Erscheinen des in diesem Artikel beschriebenen Skripts für das Programm Perpetuum M zu erklären. Das Problem besteht tatsächlich und betrifft vor allem Einsteiger, denen es nicht immer gelingt, diese „Mauer“ zu überwinden, um den ersten Schritt in die Welt der Mikrocontroller zu wagen. Das vorgeschlagene Skript berücksichtigt die in anderen Programmen festgestellten Mängel. Es wurde maximale „Transparenz“ der Funktionsweise des Algorithmus implementiert, eine äußerst einfache Benutzeroberfläche, die keine Einarbeitung erfordert und keine Chance lässt, verwirrt zu werden und „das Falsche anzuklicken“. Wenn der erforderliche MK nicht zu den unterstützten gehört, können Sie seine Beschreibung selbst hinzufügen, indem Sie die erforderlichen Daten aus der Dokumentation entnehmen, die Sie von der Website des MK-Entwicklers heruntergeladen haben. Und was am wichtigsten ist: Das Drehbuch kann studiert und geändert werden. Jeder kann es, indem er sich öffnet Texteditor, studieren und bearbeiten Sie es nach eigenem Ermessen, ändern Sie vorhandene Funktionen nach Ihrem Geschmack und fügen Sie fehlende hinzu.

Die erste Version des Drehbuchs entstand im Juni 2015. Diese Version bietet nur Unterstützung für die Mikrocontroller der Serien ATtiny und ATmega von Atmel mit Funktionen zum Schreiben/Lesen von Flash-Speicher, zum Setzen von Konfigurationsbits und zur automatischen Erkennung des Controller-Typs. Das Schreiben und Lesen von EEPROM ist nicht implementiert. Es gab Pläne, die Funktionalität des Skripts zu ergänzen : Schreib- und Lese-EEPROM hinzufügen, Unterstützung für PIC-Controller implementieren usw. Aus diesem Grund wurde das Skript noch nicht veröffentlicht. Aber aus Zeitmangel verzögerte sich die Umsetzung des Plans, und so wird das Beste nicht Der Feind des Guten, es wurde beschlossen, die bestehende Version zu veröffentlichen. Wenn die bereits implementierten Funktionen nicht ausreichen, seien Sie bitte nicht verärgert. In diesem Fall können Sie versuchen, die gewünschte Funktion selbst hinzuzufügen. Ich werde nicht verbergen: Die Idee, dieses Skript zu erstellen, hat zunächst auch eine pädagogische Bedeutung. Wenn Sie den Algorithmus verstanden und etwas Eigenes hinzugefügt haben, können Sie die Funktionsweise des MK im Programmiermodus besser verstehen, sodass in In Zukunft werden Sie sich nicht in der Lage eines Mädchens wiederfinden, das vor einem kaputten Auto steht, nachdenklich das Innere betrachtet und nicht versteht, warum es „nicht funktioniert“.

2. MK-Schnittstelle im Programmiermodus

Es gibt verschiedene Möglichkeiten, die Steuerung in den Programmiermodus zu versetzen und in diesem Modus mit ihr zu arbeiten. Am einfachsten zu implementieren ist für Controller der Serien ATtiny und ATmega vielleicht SPI. Wir werden es nutzen.

Bevor wir jedoch beginnen, die zur Generierung von SPI erforderlichen Signale zu betrachten, werden wir eine Reihe von Vorbehalten anbringen. Der Mikrocontroller verfügt über Konfigurationsbits. Dies sind so etwas wie Kippschalter, mit denen Sie einige Eigenschaften der Mikroschaltung entsprechend den Anforderungen des Projekts ändern können. Physikalisch gesehen handelt es sich hierbei um nichtflüchtige Speicherzellen, wie sie etwa zum Schreiben eines Programms dienen. Der Unterschied besteht darin, dass es nur sehr wenige davon gibt (bis zu drei Bytes für ATmega) und sie nicht Teil des Adressraums eines Speichers sind. Das Schreiben und Lesen von Konfigurationsdaten erfolgt im MK-Programmiermodus durch separate Befehle. Nun ist es wichtig zu beachten, dass einige Konfigurationsbits die eigentliche Fähigkeit zur Verwendung von SPI beeinflussen. Bei einigen ihrer Werte kann es vorkommen, dass SPI nicht verwendet werden kann. Wenn Sie auf einen solchen Mikrocontroller stoßen, hilft Ihnen die in diesem Artikel vorgeschlagene Methode nicht weiter. In diesem Fall müssen Sie entweder die Einstellungen der Konfigurationsbits im Programmiergerät ändern, das einen anderen Programmiermodus unterstützt, oder einen anderen Mikrocontroller verwenden. Dieses Problem betrifft aber nur gebrauchte MKs, oder solche, mit denen jemand bereits erfolglos „herumgespielt“ hat. Tatsache ist, dass neue MCUs über Konfigurationsbiteinstellungen verfügen, die die Verwendung von SPI nicht verhindern. Dies wird durch die Testergebnisse des Programmierskripts für das Perpetuum M-Programm bestätigt, bei dem vier verschiedene MKs (ATmega8, ATmega128, ATtiny13, ATtiny44) erfolgreich geflasht wurden. Sie waren alle neu. Die anfängliche Einstellung der Konfigurationsbits stimmte mit der Dokumentation überein und beeinträchtigte die Verwendung von SPI nicht.

Vor diesem Hintergrund sollten Sie die folgenden Punkte beachten. Das SPIEN-Bit erlaubt oder verweigert explizit die Verwendung von SPI, daher muss sein Wert in unserem Fall aktivierend sein. Das RSTDISBL-Bit ist in der Lage, einen der Ausgänge der Mikroschaltung (vorbestimmt) in den Eingang des „Reset“-Signals umzuwandeln oder ihn nicht umzuwandeln (abhängig von dem in dieses Bit geschriebenen Wert). In unserem Fall ist der „Reset“-Eingang erforderlich (fehlt dieser, ist es nicht möglich, den MK über SPI in den Programmiermodus zu schalten). Es gibt auch Bits der CKSEL-Gruppe, die die Quelle des Taktsignals angeben. Sie verhindern nicht die Verwendung von SPI, müssen aber auch beachtet werden, denn wenn überhaupt keine Taktimpulse vorhanden sind oder ihre Frequenz niedriger ist als für eine bestimmte SPI-Geschwindigkeit akzeptabel, wird auch nichts Gutes passieren. Typischerweise sind bei neuen MCUs, die über einen internen RC-Oszillator verfügen, die CKSEL-Gruppenbits für die Verwendung konfiguriert. Das kommt uns sehr entgegen, die Stempelung erfolgt ohne zusätzlichen Aufwand unsererseits. Ein Löten des Quarzresonators oder der Anschluss eines externen Generators ist nicht erforderlich. Sollten die angegebenen Bits eine andere Einstellung enthalten, müssen Sie sich um die Taktung entsprechend der Einstellung kümmern. In diesem Fall kann es erforderlich sein, einen Quarzresonator oder einen externen Taktgenerator an die MCU anzuschließen. In diesem Artikel werden wir jedoch nicht darauf eingehen, wie dies geschieht. Die in diesem Artikel enthaltenen Beispiele für den Anschluss eines MK zur Programmierung sind für den einfachsten Fall konzipiert.

Reis. 1. Datenaustausch über SPI im Programmiermodus

Wenden wir uns nun Abbildung 1 zu, die der Dokumentation für den ATmega128A MK entnommen ist. Es zeigt den Vorgang des Sendens eines Bytes an den MK und des gleichzeitigen Empfangens eines Bytes vom MK. Wie wir sehen, verwenden beide Prozesse dieselben Taktimpulse, die vom Programmierer an den Mikrocontroller an seinem SCK-Eingang geliefert werden – einem der Pins der Mikroschaltung, denen im SPI-Programmiermodus eine solche Rolle zugewiesen wird. Zwei weitere Signalleitungen ermöglichen den Datenempfang und die Übertragung von einem Bit pro Taktzyklus. Über den MOSI-Eingang gelangen Daten in den Mikrocontroller und gelesene Daten werden vom MISO-Ausgang übernommen. Beachten Sie die beiden gepunkteten Linien von SCK zu MISO und MOSI. Sie zeigen, in welchem ​​Moment der Mikrocontroller das am MOSI-Eingang gesetzte Datenbit „schluckt“ und in welchem ​​Moment er selbst sein eigenes Datenbit auf den MISO-Ausgang setzt. Alles ist ganz einfach. Um den MK jedoch in den Programmiermodus zu versetzen, benötigen wir noch ein RESET-Signal. Vergessen wir auch nicht das gemeinsame GND-Kabel und die VCC-Stromversorgung. Insgesamt stellt sich heraus, dass nur 6 Drähte an den Mikrocontroller angeschlossen werden müssen, um dessen Firmware über SPI zu flashen. Im Folgenden werden wir dies genauer analysieren, aber vorerst hinzufügen, dass der Datenaustausch mit dem MK im Programmiermodus über SPI in Paketen von 4 Byte erfolgt. Das erste Byte jedes Pakets ist grundsätzlich ausschließlich der Befehlskodierung gewidmet. Das zweite Byte kann je nach erstem eine Fortsetzung des Befehlscodes oder Teil der Adresse sein oder einen beliebigen Wert haben. Das dritte Byte wird hauptsächlich zur Übertragung von Adressen verwendet, kann aber in vielen Anweisungen einen beliebigen Wert haben. Das vierte Byte überträgt normalerweise Daten oder hat einen beliebigen Wert. Gleichzeitig mit der Übertragung des vierten Bytes empfangen einige Befehle Daten vom Mikrocontroller. Einzelheiten zu den einzelnen Befehlen finden Sie in der Controller-Dokumentation in der Tabelle „SPI Serial Programming Instruction Set“. Wir stellen vorerst nur fest, dass der gesamte Austausch mit dem Controller aus einer Folge von 32-Bit-Paketen aufgebaut ist, in denen jeweils nicht mehr als ein Byte an Nutzinformationen übertragen wird. Das ist zwar nicht ganz optimal, funktioniert aber insgesamt gut.

3. Anschließen des MK zum Programmieren

Um sicherzustellen, dass alle notwendigen Signale an die Eingänge des Mikrocontrollers geliefert werden, um die SPI-Schnittstelle zu organisieren und Daten von ihrem MISO-Ausgang zu lesen, ist es nicht erforderlich, einen Programmierer zu erstellen. Dies lässt sich ganz einfach mit dem gängigsten USB-RS232TTL-Konverter bewerkstelligen.

Im Internet findet man oft Hinweise darauf, dass solche Konverter minderwertig seien und man damit nichts Ernsthaftes machen könne. Doch im Hinblick auf die meisten Konvertermodelle ist diese Meinung falsch. Ja, es gibt Konverter im Angebot, die im Vergleich zu einem Standard-COM-Port nicht über alle Ein- und Ausgänge verfügen (z. B. nur TXD und RXD), aber ein nicht trennbares Design haben (die Mikroschaltung ist mit Kunststoff gefüllt - das ist es). es ist unmöglich, die Stifte zu erreichen). Aber diese sind den Kauf nicht wert. In einigen Fällen können Sie die fehlenden Port-Ein- und Ausgänge erhalten, indem Sie die Verkabelung direkt an den Chip anlöten. Ein Beispiel für einen solchen „verbesserten“ Konverter ist in Abbildung 2 dargestellt (Chip PL-2303 – weitere Details zum Zweck seiner Pins im Artikel „“). Dies ist eines der günstigsten Modelle, hat aber bei der Verwendung in selbstgemachten Designs seine eigenen Vorteile. Weit verbreitet sind auch voll ausgestattete Adapterkabel mit einem standardmäßigen neunpoligen Stecker am Ende, etwa einem COM-Port. Sie unterscheiden sich von einem regulären COM-Port nur durch die TTL-Ebenen und die Inkompatibilität mit älteren Versionen Software und einige alte Geräte. Es lässt sich auch feststellen, dass sich die Kabel auf dem CH34x-Chip in verschiedenen Extremtests als deutlich zuverlässiger und stabiler erwiesen als Konverter auf dem PL-2303. Im normalen Gebrauch ist der Unterschied jedoch nicht spürbar.

Bei der Auswahl eines USB-RS232TTL-Konverters sollten Sie auch auf die Kompatibilität seines Treibers mit der Version des von Ihnen verwendeten Betriebssystems achten.

Schauen wir uns das Prinzip der Verbindung eines Mikrocontrollers und eines USB-RS232TTL-Konverters am Beispiel von vier genauer an verschiedene Modelle MK: ATtiny13, ATtiny44, ATmega8 und ATmega128. Abbildung 3 zeigt das allgemeine Diagramm einer solchen Verbindung. Es mag Sie überraschen, dass die RS232-Signale (RTS, TXD, DTR und CTS) unsachgemäß verwendet werden. Aber keine Sorge: Das Perpetuum M-Programm ist in der Lage, direkt mit ihnen zu arbeiten – Ausgabewerte festzulegen und Eingabezustände zu lesen. Auf jeden Fall bieten die weit verbreiteten USB-RS232TTL-Konverter auf CH34x- und PL-2303-Chips diese Fähigkeit – dies wurde bestätigt. Auch mit anderen gängigen Konvertern sollte es keine Probleme geben, da für den Zugriff auf den Port Standard-Windows-Funktionen genutzt werden.

Die im Gesamtschaltbild dargestellten Widerstände können grundsätzlich nicht eingebaut werden, es ist aber dennoch besser, sie einzubauen. Was ist ihr Zweck? Durch die Nutzung der TTL-Ein- und -Ausgänge des Konverters und der Fünf-Volt-Stromversorgung des Mikrocontrollers entfällt damit die Notwendigkeit, logische Ebenen zu koordinieren – alles ist schon ganz richtig. Das heißt, die Verbindungen können direkt sein. Aber bei Experimenten , kann alles passieren. Nach dem Gesetz der Gemeinheit kann zum Beispiel ein Schraubenzieher genau an der Stelle fallen, wo er unmöglich hinfallen könnte, und etwas kurzschließen, was auf keinen Fall kurzgeschlossen werden sollte. Natürlich kann alles erweisen sich als „Schraubendreher“. Widerstände reduzieren in diesem Fall manchmal die Folgen. Einer ihrer Zwecke besteht darin, einen möglichen Ausgangskonflikt zu beseitigen. Tatsache ist, dass der Mikrocontroller nach Abschluss der Programmierung in den normalen Betriebsmodus wechselt, und zwar möglicherweise Es kann vorkommen, dass sein mit dem Ausgang des Konverters (RTS, TXD oder DTR) verbundener Pin laut dem gerade im MK aufgezeichneten Programm auch zu einem Ausgang wird. In diesem Fall wird es sehr schlimm sein, wenn zwei direkt verbundene Ausgänge „kämpfen“. - Versuchen Sie, verschiedene logische Ebenen festzulegen. In einem solchen „Kampf“ kann jemand „verlieren“, aber das wollen wir nicht.

Die Werte der drei Widerstände sind auf dem Niveau von 4,3 KOhm gewählt. Dies gilt für Verbindungen zwischen dem Wandlerausgang und dem Mikrocontroller-Eingang. Die Genauigkeit der Widerstände spielt keine Rolle: Sie können ihren Widerstand auf 1 KOhm reduzieren oder auf 10 KOhm erhöhen (im zweiten Fall erhöht sich jedoch die Gefahr von Störungen, wenn auf dem Weg zum MK lange Leitungen verwendet werden). Für die Verbindung zwischen dem Wandlereingang (CTS) und dem Mikrocontroller-Ausgang (MISO) wird hier ein 100-Ohm-Widerstand verwendet. Dies erklärt sich aus den Besonderheiten des Eingangs des verwendeten Konverters. Bei den Tests wurde auf der Mikroschaltung PL-2303 ein Konverter verwendet, dessen Eingänge offenbar mit einem relativ geringen Widerstand (in der Größenordnung von mehreren hundert Ohm) mit dem Pluspol der Stromversorgung verbunden sind. Um den Pull-up zu „brechen“, musste ich einen Widerstand mit einem so kleinen Widerstand installieren. Sie müssen es jedoch überhaupt nicht installieren. Beim Konverter ist dies immer der Eingang. Es kann kein Ausweg sein, was bedeutet, dass es bei keiner Entwicklung der Ereignisse zu einem Auswegkonflikt kommen wird.

Wenn der Chip über einen separaten AVCC-Pin zur Stromversorgung des Analog-Digital-Wandlers verfügt (z. B. ATmega8 oder ATmega128), sollte er mit dem gemeinsamen VCC-Stromanschluss verbunden werden. Einige ICs verfügen über mehr als einen VCC-Stromanschluss oder mehr als einen GND. Beispielsweise verfügt ATmega128 über 3 GND-Pins und 2 VCC-Pins. Bei einem dauerhaften Design ist es besser, gleichnamige Pins miteinander zu verbinden. In unserem Fall können Sie beim Programmieren jeweils einen VCC- und einen GND-Pin verwenden.

Und so sieht die ATtiny13-Verbindung aus. Die Abbildung zeigt die Pinbelegung, die bei der Programmierung über SPI verwendet wird. Neben dem Foto sehen Sie, wie eine temporäre Verbindung in der Realität aussieht.


Manche mögen sagen, dass das nichts Ernstes ist – Verbindungen in der Verkabelung. Aber Sie und ich sind vernünftige Menschen. Unser Ziel ist es, den Mikrocontroller zu programmieren, dabei ein Minimum an Zeit und anderen Ressourcen dafür aufzuwenden und nicht vor jemandem anzugeben. Die Qualität leidet nicht. Die Methode „auf Drähten“ ist in diesem Fall sehr effektiv und gerechtfertigt. Das Flashen der Firmware des Controllers ist ein einmaliger Vorgang, daher macht es keinen Sinn, ihn mit Strasssteinen zu bedecken. Soll in Zukunft die Firmware geändert werden, ohne den Controller aus dem Stromkreis (im fertigen Produkt) zu entfernen, so wird dies beim Einbau bei der Herstellung des Gerätes berücksichtigt. Üblicherweise wird hierfür ein Anschluss (RESET, SCK, MOSI, MISO, GND) verbaut und der MK kann auch nach der Montage auf der Platine geflasht werden. Aber das sind kreative Freuden. Wir betrachten den einfachsten Fall.

Kommen wir nun zum ATtiny44 MK. Hier ist alles ziemlich gleich. Anhand der Zeichnung und des Fotos wird auch ein Anfänger keine Schwierigkeiten haben, den Zusammenhang herauszufinden. Wie beim ATtiny44 können Sie die Mikrocontroller ATtiny24 und ATtiny84 anschließen – die Pinbelegung dieser drei ist gleich.


Ein weiteres Beispiel für den vorübergehenden Anschluss eines Controllers zur Programmierung ist ATmega8. Hier gibt es mehr Pins, aber das Prinzip ist dasselbe – ein paar Drähte, und jetzt ist der Controller bereit, Informationen hineinzufüllen. Der zusätzliche schwarze Draht auf dem Foto, der von Pin 13 kommt, nimmt nicht an der Programmierung teil. Es dient dazu, ein Tonsignal zu entfernen, nachdem der MK den Programmiermodus verlässt. Dies liegt daran, dass beim Debuggen des Skripts für „Perpetuum M“ das Programm auf das MK heruntergeladen wurde Musikbox.


Oft ist ein Controller in verschiedenen Gehäusen erhältlich. In diesem Fall ist die Belegung der Pins je nach Gehäuse unterschiedlich verteilt. Wenn das Gehäuse Ihres Controllers nicht mit dem in der Abbildung gezeigten übereinstimmt, überprüfen Sie den Zweck der Pins in der technischen Dokumentation, die Sie von der Website des MK-Entwicklers herunterladen können.

Um das Bild zu vervollständigen, schauen wir uns die Verbindung einer MK-Mikroschaltung mit einer großen Anzahl von „Beinen“ an. Der Zweck des zusätzlichen schwarzen Kabels auf dem Foto, das von Pin 15 kommt, ist genau der gleiche wie beim ATmega8.


Sie sind wahrscheinlich bereits davon überzeugt, dass alles ganz einfach ist. Jeder, der weiß, wie man die Pins von Mikroschaltungen zählt (von der Markierung im Kreis gegen den Uhrzeigersinn), wird es herausfinden. Und vergessen Sie nicht die Genauigkeit. Mikroschaltungen lieben nette Menschen und verzeihen keine nachlässige Behandlung.

Bevor Sie mit dem Softwareteil fortfahren, stellen Sie sicher, dass der USB-RS232TTL-Konvertertreiber korrekt installiert ist (überprüfen Sie den Windows-Geräte-Manager). Merken oder notieren Sie sich die Nummer des virtuellen COM-Ports, der beim Anschließen des Konverters angezeigt wird. Diese Nummer muss in den Text des Skripts eingegeben werden, über den Sie weiter unten lesen können.

4. Skript – Programmierer für „Perpetuum M“

Wir haben den Hardware-Teil des „Programmierers“ herausgefunden. Das ist bereits die halbe Miete. Nun bleibt es noch, sich mit dem Softwareteil zu befassen. Seine Rolle übernimmt das Programm Perpetuum M unter der Kontrolle eines Skripts, das alle notwendigen Funktionen für die Interaktion mit dem Mikrocontroller implementiert.

Das Archiv mit dem Skript sollte in denselben Ordner entpackt werden, in dem sich das Programm perpetuum.exe befindet. In diesem Fall wird beim Ausführen der Datei perpetuum.exe auf dem Bildschirm ein Menü mit einer Liste der installierten Skripte angezeigt, darunter die Zeile „AVR MK Programmer“ (möglicherweise die einzige). Das ist die Linie, die wir brauchen.

Das Skript befindet sich im PMS-Ordner in der Datei „MK Programmer AVR.pms“. Diese Datei kann bei Bedarf in einem normalen Texteditor wie Windows Notepad angezeigt, studiert und bearbeitet werden. Bevor Sie das Skript verwenden, müssen Sie höchstwahrscheinlich Änderungen am Text vornehmen, der sich auf die Porteinstellungen bezieht. Überprüfen Sie dazu den Namen des verwendeten Ports im Windows-Geräte-Manager und nehmen Sie ggf. die entsprechende Änderung in der Zeile „PortName="COM4";“ vor. - Anstelle der Nummer 4 kann es auch eine andere Nummer geben. Wenn Sie ein anderes USB-RS232TTL-Konvertermodell verwenden, müssen Sie möglicherweise auch die Signalinvertierungseinstellungen ändern (Skriptzeilen, die mit dem Wort „High“ beginnen). Die Umkehrung der Signale durch den USB-RS232TTL-Konverter können Sie anhand eines der Beispiele in der Anleitung zum Programm Perpetuum M (Funktionsabschnitt zum Arbeiten mit dem Port) überprüfen.

Der Unterordner MK_AVR enthält Dateien mit Beschreibungen der unterstützten Controller. Sollte der von Ihnen benötigte Controller nicht dabei sein, können Sie analog dazu den benötigten selbst hinzufügen. Nehmen Sie eine der Dateien als Beispiel und geben Sie mithilfe eines Texteditors die erforderlichen Daten ein, indem Sie diese der Dokumentation Ihres Mikrocontrollers entnehmen. Hauptsache vorsichtig sein, die Daten fehlerfrei eingeben, sonst wird der MK nicht oder falsch programmiert. Die Originalversion unterstützt 6 Mikrocontroller: ATtiny13, ATtiny24, ATtiny44, ATtiny84, ATmega8 und ATmega128. Das Skript implementiert die automatische Erkennung des angeschlossenen Controllers – eine manuelle Angabe ist nicht erforderlich. Wenn die aus dem MK ausgelesene Kennung nicht zu den verfügbaren Beschreibungen gehört, wird eine Meldung angezeigt, dass der Controller nicht erkannt werden konnte.

Das Archiv mit dem Skript enthält auch Weitere Informationen. Der Ordner „AVR Controller Inc Files“ enthält eine sehr nützliche und umfangreiche Sammlung von Controller-Definitionsdateien. Diese Dateien werden beim Schreiben eigener Programme für MK verwendet. Vier weitere Ordner „MusicBox_...“ enthalten Dateien mit einem Programm in Assemblersprache und Firmware, die separat für ATtiny13, ATtiny44, ATmega8 und ATmega128 auf den MK heruntergeladen werden können. Wenn Sie, wie in diesem Artikel vorgeschlagen, bereits einen dieser MKs zum Programmieren angeschlossen haben, können Sie ihn jetzt flashen – Sie erhalten eine Spieluhr. Mehr dazu weiter unten.

Wenn Sie im Skriptmenü die Zeile „MK AVR Programmer“ auswählen, beginnt die Ausführung des Skripts. Gleichzeitig öffnet es den Port, sendet einen Befehl an den MK, in den Programmiermodus zu wechseln, erhält vom MK eine Bestätigung über den erfolgreichen Übergang, fordert die MK-Kennung an und sucht unter den verfügbaren nach einer Beschreibung dieses MK anhand seiner Kennung Dateien mit Beschreibungen. Wenn die benötigte Beschreibung nicht gefunden wird, wird eine entsprechende Meldung angezeigt. Wird eine Beschreibung gefunden, öffnet sich das Hauptmenü des Programmierers. Den Screenshot können Sie in Abbildung 8 sehen. Das weitere Verständnis ist nicht schwierig – das Menü ist sehr einfach.

In der ersten Version des Skripts sind einige Funktionen eines vollwertigen Programmierers nicht implementiert. Beispielsweise gibt es keine Möglichkeit, das EEPROM zu lesen und zu schreiben. Wenn Sie das Skript jedoch in einem Texteditor öffnen, werden Sie feststellen, dass es sehr klein ist, obwohl das Wesentliche bereits darin implementiert ist. Dies deutet darauf hin, dass das Hinzufügen der fehlenden Funktionen nicht so schwierig ist – die Sprache ist sehr flexibel und ermöglicht die Implementierung umfangreicher Funktionen in einem kleinen Programm. Doch in den meisten Fällen reichen bereits die vorhandenen Funktionen aus.

Einige Funktionseinschränkungen werden direkt im Skripttext beschrieben:
//Aufzeichnung nur ab der Nulladresse implementiert (Extended Segment Address Record wird ignoriert, LOAD OFFSET - auch)
//Die Reihenfolge und Kontinuität der Datensätze in der HEX-Datei wird nicht überprüft
//Prüfsumme wird nicht überprüft
Dies gilt für die Arbeit mit einer HEX-Datei, aus der der Firmware-Code für den MK entnommen wird. Wenn diese Datei nicht beschädigt ist, hat die Überprüfung der Prüfsumme keine Auswirkung. Wenn es verzerrt ist, kann es mit dem Skript nicht erkannt werden. In den meisten Fällen schaden die verbleibenden Einschränkungen nicht, Sie müssen sie aber dennoch im Hinterkopf behalten.

5. Spieluhr – ein einfaches Handwerk für Anfänger

Wenn Sie einen dieser Mikrocontroller besitzen: ATtiny13, ATtiny44, ATmega8 oder ATmega128, können Sie ihn ganz einfach in eine Spieluhr oder Musikkarte verwandeln. Dazu reicht es aus, die entsprechende Firmware in die MK zu schreiben – eine der vier, die sich in den Ordnern „MusicBox_…“ im selben Archiv wie das Skript befinden. Firmware-Codes werden in Dateien mit der Erweiterung „.hex“ gespeichert. Die Verwendung von ATmega128 für ein solches Fahrzeug ist natürlich „fett“, genau wie ATmega8. Dies kann jedoch zum Testen oder Experimentieren, also zu Bildungszwecken, nützlich sein. Die Texte der Programme in Assembler sind ebenfalls beigefügt. Die Programme wurden nicht von Grund auf erstellt – als Grundlage diente das Spieluhrprogramm aus dem Buch von A.V. Belov. AVR-Mikrocontroller in der Amateurfunkpraxis.“ Das ursprüngliche Programm hat eine Reihe bedeutender Änderungen erfahren:
1. angepasst für jeden der vier MKs: ATtiny13, ATtiny44, ATmega8 und ATmega128
2. Tasten wurden eliminiert – es muss nichts außer Strom und einem Soundgeber an den Controller angeschlossen werden (Melodien werden nacheinander in einer Endlosschleife abgespielt)
3. Die Dauer jeder Note wird um die Dauer der Pause zwischen den Noten verkürzt, um Störungen im musikalischen Rhythmus zu vermeiden
4. Die achte Melodie ist verbunden und wird in der Buchversion nicht verwendet
5. Subjektiv: einige „Verbesserungen“, um den Algorithmus zu optimieren und verständlicher zu machen

In manchen Melodien hört man Unwahrheiten und sogar grobe Fehler, besonders in „Smile“ – in der Mitte. Die Klingeltoncodes wurden dem Buch entnommen (bzw. zusammen mit der Original-ASM-Datei von der Website des Buchautors heruntergeladen) und nicht verändert. Offenbar liegen Fehler in der Kodierung der Melodien vor. Aber das ist kein Problem – jeder, der mit Musik „freundlich“ ist, kann es leicht herausfinden und alles reparieren.

In ATtiny13 musste aufgrund des Fehlens eines 16-Bit-Zählers ein 8-Bit-Zähler zur Wiedergabe von Notizen verwendet werden, was zu einer leichten Verschlechterung der Genauigkeit der Notizen führte. Das ist aber kaum hörbar.

Über die Konfigurationsbits. Ihre Einstellungen müssen dem Zustand des neuen Mikrocontrollers entsprechen. Wenn Ihr MK schon einmal irgendwo verwendet wurde, müssen Sie den Zustand seiner Konfigurationsbits überprüfen und diese gegebenenfalls an die Einstellungen des neuen Mikrocontrollers anpassen. Den Zustand der Konfigurationsbits des neuen Mikrocontrollers können Sie der Dokumentation zu diesem MK entnehmen (Abschnitt „Fuse Bits“). Die Ausnahme ist ATmega128. Diese MCU verfügt über das M103C-Bit, das den Kompatibilitätsmodus mit dem älteren ATmega103 ermöglicht. Durch die Aktivierung des M103C-Bits werden die Fähigkeiten des ATmega128 erheblich eingeschränkt, und dieses Bit ist auf dem neuen MK aktiv. Sie müssen den M103C in einen inaktiven Zustand zurücksetzen. Um Konfigurationsbits zu manipulieren, verwenden Sie den entsprechenden Abschnitt des Programmierskriptmenüs.

Es hat keinen Sinn, die Spieluhr schematisch darzustellen: Sie enthält nur einen Mikrocontroller, ein Netzteil und einen Piezo-Schallgeber. Die Stromversorgung erfolgt genauso wie bei der Programmierung des MK. Der Schallsender wird zwischen dem gemeinsamen Kabel (GND-Pin des Controllers) und einem der MK-Pins angeschlossen, deren Nummer in der Datei mit dem Programm-Assembler-Code (*.asm) zu finden ist. Am Anfang des Programmtextes steht für jeden MK in den Kommentaren eine Zeile: „ Tonsignal wird an Pin XX gebildet.“ Wenn das Programmierskript seine Arbeit beendet, verlässt der Mikrocontroller den Programmiermodus und geht in den normalen Betriebsmodus. Das Abspielen von Melodien beginnt sofort. Durch Anschließen des Soundsenders können Sie dies überprüfen. Sie können den Soundsender verlassen Während der Programmierung des Quarzes ist die Verbindung nur dann möglich, wenn das Audio von einem Pin kommt, der nicht vom SPI verwendet wird, andernfalls kann die zusätzliche Kapazität am Pin die Programmierung beeinträchtigen.

Aufgabe: Lassen Sie uns ein Programm zur Steuerung einer LED entwickeln. Beim Drücken der Taste leuchtet die LED auf und beim Loslassen erlischt sie.

Lassen Sie uns zunächst ein schematisches Diagramm des Geräts entwickeln. I/O-Ports werden verwendet, um beliebige externe Geräte an den Mikrocontroller anzuschließen. Jeder der Ports kann sowohl als Eingang als auch als Ausgang fungieren. Verbinden wir die LED mit einem der Anschlüsse und den Knopf mit dem anderen. Für dieses Experiment verwenden wir einen Controller Atmega8. Dieser Chip enthält 3 I/O-Ports, verfügt über 2 8-Bit- und 1 16-Bit-Timer/Zähler. Mit an Bord sind außerdem ein 3-Kanal-PWM, ein 6-Kanal-10-Bit-Analog-Digital-Wandler und vieles mehr. Meiner Meinung nach eignet sich ein Mikrocontroller hervorragend zum Erlernen der Grundlagen der Programmierung.

Um die LED anzuschließen, verwenden wir die Leitung PB0 und zum Auslesen der Informationen aus der Taste verwenden wir die Leitung PD0. Das Diagramm ist in Abb. 1 dargestellt.

Reis. 1

Über den Widerstand R2 wird dem Eingang PD0 eine Plus-Versorgungsspannung zugeführt, was einem logischen Eins-Signal entspricht. Beim Schließen des Tasters sinkt die Spannung auf Null, was einer logischen Null entspricht. Zukünftig kann R2 aus dem Stromkreis ausgeschlossen werden, indem man ihn durch einen internen Lastwiderstand ersetzt und die notwendigen Einstellungen im Programm vornimmt. Die LED ist über den Strombegrenzungswiderstand R3 mit dem Ausgang von Port PB0 verbunden. Um die LED zum Leuchten zu bringen, müssen Sie ein logisches Eins-Signal an die PB0-Leitung anlegen. Wir werden einen internen Master-Taktgenerator mit 4 MHz verwenden, da das Gerät keine hohen Anforderungen an die Frequenzstabilität stellt.

Jetzt schreiben wir das Programm. Ich nutze die Programmierumgebung, um Programme zu schreiben AVR Studio Und WinAvr.Öffnen Sie AVR Studio, ein Willkommensfenster erscheint, klicken Sie auf die Schaltfläche „Neues Projekt erstellen“, wählen Sie dann den Projekttyp – AVR GCC, geben Sie den Projektnamen ein, zum Beispiel „cod1“, aktivieren Sie sowohl „Projektordner erstellen“ als auch „Erstellen“. Aktivieren Sie die Kontrollkästchen „Initialisierungsdatei“, klicken Sie auf die Schaltfläche „Weiter“, wählen Sie „AVR-Simulator“ im linken Fenster und „Atmega8“-Mikrocontrollertyp im rechten Fenster. Klicken Sie auf die Schaltfläche „Fertig stellen“. Der Editor und der Projektkategoriebaum werden geöffnet Die Grundeinstellungen sind abgeschlossen.

Fügen wir zunächst einen Standardbeschreibungstext für Atmega8 hinzu, indem wir den Operator zum Anhängen externer Dateien verwenden: #enthalten

Direktivensyntax #enthalten

#enthalten<имя_файла.h>
#include „Dateiname.h“

Spitze Klammern< и >Geben Sie dem Compiler an, dass eingebundene Dateien zunächst im Standard-WinAvr-Ordner namens include gesucht werden müssen. Die doppelten Anführungszeichen „ und „ weisen den Compiler an, mit der Suche in dem Verzeichnis zu beginnen, in dem das Projekt gespeichert ist.

Jeder Mikrocontrollertyp verfügt über eine eigene Header-Datei. Für ATMega8 heißt diese Datei iom8.h, für ATtiny2313 - iotn2313.h. Am Anfang jedes Programms müssen wir die Header-Datei des von uns verwendeten Mikrocontrollers einfügen. Es gibt aber auch eine gemeinsame Header-Datei io.h. Der Präprozessor verarbeitet diese Datei und bindet je nach Projekteinstellungen die benötigte Header-Datei in unser Programm ein.

Für uns sieht die erste Zeile des Programms so aus:

#enthalten

Jedes C-Programm muss eine Hauptfunktion enthalten. Es heißt main. Die Programmausführung beginnt immer mit der Ausführung der Hauptfunktion. Eine Funktion hat einen Header – int main(void) und einen Body – sie ist begrenzt Geschweifte Klammern {}.

int main(void)
{
Funktionskörper
}

Wir werden unseren Code zum Hauptteil der Funktion hinzufügen. Der Rückgabetyp wird vor dem Funktionsnamen angegeben. Wenn die Funktion keinen Wert zurückgibt, wird der Schlüssel verwendet Leere.

int- Dies ist eine 2-Byte-Ganzzahl, der Wertebereich reicht von -32768 bis 32767

Nach dem Funktionsnamen werden in Klammern () die Parameter angegeben, die beim Aufruf der Funktion übergeben werden. Wenn die Funktion keine Parameter hat, wird das Schlüsselwort verwendet Leere. Funktion hauptsächlich enthält eine Reihe von Befehlen, Systemeinstellungen und die Hauptprogrammschleife.

Als nächstes konfigurieren wir den Port D am Eingang. Der Port-Betriebsmodus wird durch den Inhalt des Registers bestimmt DDRD(Informationsübertragungsrichtungsregister). In dieses Register schreiben wir die Zahl „0x00“ (0b0000000 – in binärer Form); mit diesem Port ist außer dem Button nichts verbunden, also konfigurieren wir den gesamten Port D als Eingang. Sie können den Port Stück für Stück konfigurieren, indem Sie die Zahlen 0 oder 1 in jedes Bit des Registers schreiben (0-Eingabe, 1-Ausgabe), zum Beispiel DDRD = 0x81 (0b10000001) – die erste und letzte Zeile von Port D funktionieren als Ausgabe, der Rest als Eingabe. Der interne Lastwiderstand muss ebenfalls angeschlossen werden. Das PORTx-Register steuert, ob die internen Widerstände ein- oder ausgeschaltet sind, wenn sich der Port im Eingabemodus befindet. Schreiben wir dort Einheiten.

Einrichten des Ports B zum Ausgang. Der Port-Betriebsmodus wird durch den Inhalt des Registers bestimmt DDRB. Nichts als eine LED zum Port B nicht verbunden, sodass der gesamte Port als Ausgang konfiguriert werden kann. Dies geschieht durch Schreiben in das Register DDRB Zahlen „0xFF“. Um zu verhindern, dass die LED beim ersten Einschalten aufleuchtet, schreiben Sie auf den Port B logische Nullen. Dies geschieht durch Aufnahme PORTB= 0x00;

Zum Zuweisen von Werten wird das Symbol „=“ verwendet, das als Zuweisungsoperator bezeichnet wird und nicht mit dem „Gleichheitszeichen“ verwechselt werden darf.

Die Portkonfiguration sieht folgendermaßen aus:

DDRD = 0x00;
PORTD = 0xFF;
DDRB = 0xFF;
PORTB = 0x00;

Wir schreiben die Hauptschleife des Programms. während(„while“ aus dem Englischen) – dieser Befehl organisiert eine Schleife und wiederholt den Schleifenkörper viele Male, bis die Bedingung erfüllt ist, d. h. solange der Ausdruck in Klammern wahr ist. In C gilt ein Ausdruck als wahr, wenn er ungleich Null ist, und als falsch, wenn er ungleich Null ist.

Der Befehl sieht so aus:

while (Bedingung)
{
Schleifenkörper
}

In unserem Fall besteht die Hauptschleife nur aus einem Befehl. Dieser Befehl weist ein Register zu PORTB Registerwert, der invertiert werden soll PORTD.

PORTB = ~PIND; //den Wert von Port D nehmen, invertieren und PORTB zuweisen (in PORTB schreiben)

// C-Ausdrücke werden von rechts nach links gelesen

PIND Informationseingaberegister. Um Informationen vom externen Ausgang des Controllers auszulesen, müssen Sie zunächst das gewünschte Bit des Ports in den Eingabemodus schalten. Das heißt, in das entsprechende Bit des Registers schreiben DDRx null. Erst danach kann diesem Pin ein digitales Signal von einem externen Gerät zugeführt werden. Als nächstes liest der Mikrocontroller das Byte aus dem Register PINx. Der Inhalt des entsprechenden Bits entspricht dem Signal am externen Pin des Ports. Unser Programm ist fertig und sieht so aus:

#enthalten int main (void) ( DDRD = 0x00; //Port D - Eingang PORTD = 0xFF; //Lastwiderstand anschließen DDRB = 0xFF; //Port B - Ausgang PORTB = 0x00; //den Ausgang auf 0 setzen while(1 ) ( PORTB = ~PIND; //~ bitweises Umkehrzeichen ) )

Kommentare werden in der C-Sprache häufig verwendet. Es gibt zwei Möglichkeiten zu schreiben.

/*Ein Kommentar*/
//Ein Kommentar

In diesem Fall achtet der Compiler nicht darauf, was im Kommentar steht.

Wenn Sie dasselbe Programm verwenden und 8 Tasten und 8 LEDs an den Mikrocontroller anschließen, wie in Abbildung 2 gezeigt, wird klar, dass jedes Bit des Ports vorhanden ist D entspricht seinem Portbit B. Durch Drücken der SB1-Taste leuchtet HL1, durch Drücken der SB2-Taste leuchtet HL2 usw.

Figur 2

Der Artikel verwendete Materialien aus dem Buch von A.V. Belov. „Tutorial für AVR-Geräteentwickler“

Ich habe mehr als ein- oder zweimal gesagt, dass das Erlernen von MK mit Assembler beginnen sollte. Ein ganzer Kurs auf der Website war diesem Thema gewidmet (obwohl es nicht sehr konsistent ist, aber ich kombiniere es nach und nach zu einem angemessenen Erscheinungsbild). Ja, es ist schwierig, das Ergebnis wird nicht am ersten Tag sein, aber Sie werden lernen zu verstehen, was in Ihrem Controller passiert. Sie werden wissen, wie es funktioniert, und nicht wie ein Affe die Quellen anderer Leute kopieren und versuchen zu verstehen, warum es plötzlich nicht mehr funktioniert. Darüber hinaus ist es für C viel einfacher, Redneck-Code zu erstellen, der im ungünstigsten Moment mit einer Mistgabel herauskommt.

Leider möchte jeder sofort Ergebnisse erzielen. Also beschloss ich, den anderen Weg zu gehen – ein Tutorial über C zu machen, aber seine Unterwäsche zu zeigen. Ein guter Embedder-Programmierer hält seine Hardware immer fest an der Schraube und lässt nicht zu, dass sie ohne Erlaubnis einen einzigen Schritt ausführt. Zuerst kommt also der C-Code, dann kommt das, was der Compiler produziert hat und wie das Ganze eigentlich funktioniert :)

Andererseits liegt die Stärke von C in der Codeportabilität. Wenn Sie natürlich alles richtig schreiben. Aufteilung der Arbeitsalgorithmen und ihrer Hardware-Implementierungen in verschiedene Teile des Projekts. Um den Algorithmus dann auf einen anderen Mikrocontroller zu übertragen, reicht es aus, nur die Schnittstellenschicht neu zu schreiben, in der alle Aufrufe an die Hardware geschrieben werden, und den gesamten Arbeitscode unverändert zu lassen. Und natürlich die Lesbarkeit. Der C-Quellcode ist auf den ersten Blick leichter zu verstehen (obwohl es mir zum Beispiel egal ist, worauf ich hinweisen soll – sei es C oder ASM :)), aber wiederum, wenn alles richtig geschrieben ist. Auf diese Punkte werde ich auch achten.

Als Experimentierhardware dient mein Debugboard, auf dem der Löwenanteil aller Beispiele installiert wird.

Das erste C-Programm für AVR

Auswahl eines Compilers und Einrichten der Umgebung
Es gibt viele verschiedene C-Compiler für AVR:
Das hier zunächst einmal IAR AVR C- gilt mit ziemlicher Sicherheit als der beste Compiler für AVR, weil Der Controller selbst wurde in enger Zusammenarbeit zwischen Atmel und Spezialisten von IAR entwickelt. Aber man muss für alles bezahlen. Und dieser Compiler ist nicht nur eine teure kommerzielle Software, sondern verfügt auch über so viele Einstellungen, dass es sehr aufwändig ist, ihn einfach darin zu kompilieren. Ich habe wirklich keine Freundschaft mit ihm aufgebaut; das Projekt verrottete aufgrund seltsamer Fehler in der Verknüpfungsphase (später fand ich heraus, dass es ein schiefer Riss war).

Der Zweite kommt WinAVR GCC- ein leistungsstarker optimierender Compiler. Vollständig Open Source, plattformübergreifend, im Allgemeinen alle Freuden des Lebens. Es lässt sich auch perfekt in AVR Studio integrieren, sodass Sie direkt dort debuggen können, was verdammt praktisch ist. Im Allgemeinen habe ich es gewählt.

Es gibt auch CodeVision AVR C ist ein sehr beliebter Compiler. Es wurde aufgrund seiner Einfachheit populär. In nur wenigen Minuten erhalten Sie darin ein funktionsfähiges Programm – der Startcode-Assistent erleichtert dies erheblich, indem er Standards für die Initialisierung aller möglichen Dinge festlegt. Ehrlich gesagt bin ich etwas misstrauisch – als ich ein von diesem Compiler geschriebenes Programm zerlegen musste, stellte sich heraus, dass es sich um eine Art Chaos und nicht um Code handelte. Eine schreckliche Menge unnötiger Bewegungen und Vorgänge, die zu einer beträchtlichen Menge an Code und einer langsamen Leistung führten. Möglicherweise liegt jedoch ein Fehler in der DNA der Person vor, die die Original-Firmware geschrieben hat. Außerdem will er Geld. Nicht so stark wie IAR, aber spürbar. Und im Demomodus können Sie nicht mehr als 2 KB Code schreiben.
Natürlich gibt es einen Riss, aber wenn man stehlen will, ist es eine Million im IAR-Sinne :)

Es gibt noch Image Craft AVR C Und MikroC aus der Mikroelektronik. Ich musste keines davon verwenden, aber S.W.G. sehr lobend MikroPascal, sagen sie, eine schrecklich praktische Programmierumgebung und Bibliotheken. Ich denke, MicroC wird nicht schlechter sein, aber es wird auch bezahlt.

Wie gesagt, ich habe mich entschieden WinAVR Aus drei Gründen: Es ist kostenlos, es lässt sich in AVR Studio integrieren und es gibt einfach eine Menge vorgefertigten Codes für alle Gelegenheiten.

Laden Sie also die WinAVR-Installation mit AVR Studio herunter. Als nächstes wird zunächst das Studio installiert, dann wird WinAVR darüber gerollt und in Form eines Plugins an das Studio angehängt. Ich empfehle dringend, WinAVR in einem kurzen Pfad zu installieren, etwa C:\WinAVR. Auf diese Weise vermeiden Sie viele Probleme mit Pfaden.

Ein Projekt erstellen
Also, das Studio ist installiert, C ist eingeschraubt, es ist Zeit, zu versuchen, etwas zu programmieren. Beginnen wir mit dem Einfachsten, dem Einfachsten. Starten Sie das Studio, wählen Sie dort ein neues Projekt als AVR-GCC-Compiler aus und geben Sie den Namen des Projekts ein.

Es öffnet sich ein Arbeitsfeld mit einer leeren *.c-Datei.

Jetzt kann es nicht schaden, die Anzeige der Pfade in den Studio-Lesezeichen zu konfigurieren. Gehen Sie dazu zu:
Menü Extras – Optionen – Allgemein – Dateiregisterkarten und wählen Sie „Nur Dateiname“ aus der Dropdown-Liste. Andernfalls ist die Arbeit nicht möglich – die Registerkarte enthält den vollständigen Pfad der Datei und es werden nicht mehr als zwei oder drei Registerkarten auf dem Bildschirm angezeigt.

Projektaufbau
Im Allgemeinen gilt es als klassisch, eine Make-Datei zu erstellen, in der alle Abhängigkeiten beschrieben sind. Und das ist wahrscheinlich richtig. Aber für mich, der mit vollständig integrierten IDEs aufgewachsen ist, gefällt es mir uVision oder AVR Studio Dieser Ansatz ist zutiefst fremd. Deshalb werde ich es auf meine Weise machen, alles mit Studiomitteln.

Drücken Sie den Knopf mit dem Zahnrad.


Dies sind Ihre Projekteinstellungen und genauere Einstellungen Automatische Generierung von Makefile. Auf der ersten Seite müssen Sie lediglich die Frequenz eingeben, mit der Ihr MK arbeiten soll. Dies hängt von den Sicherungsbits ab, daher gehen wir davon aus, dass unsere Frequenz 8000000 Hz beträgt.
Achten Sie auch auf die Optimierungslinie. Jetzt gibt es -Os – das ist Größenoptimierung. Lassen Sie es vorerst so, wie es ist, dann können Sie versuchen, mit diesem Parameter zu spielen. -O0 ist überhaupt keine Optimierung.

Der nächste Schritt besteht darin, die Pfade zu konfigurieren. Fügen Sie dort zunächst Ihr Projektverzeichnis hinzu – Sie fügen dort Bibliotheken von Drittanbietern hinzu. Der Pfad „.\“ erscheint in der Liste.

Die Make-Datei wurde generiert. Sie können sie im Standardordner Ihres Projekts ansehen. Werfen Sie einfach einen Blick darauf und sehen Sie, was sich dort befindet.


Das ist alles für den Moment. Klicken Sie überall auf OK und gehen Sie zur Quelle.

Formulierung des Problems
Ein leeres Blatt Papier ist verlockend, eine raffinierte Idee umzusetzen, da das banale Blinken einer Diode nicht mehr funktioniert. Lasst uns sofort den Stier bei den Hörnern packen und die Verbindung mit dem Computer herstellen – das ist das Erste, was ich mache.

Es wird so funktionieren:
Wenn eine Eins (Code 0x31) über den COM-Port ankommt, schalten wir die Diode ein, und wenn eine Null ankommt (Code 0x30), schaltet sie sich aus. Darüber hinaus wird alles über Interrupts erledigt und die Hintergrundaufgabe wird das Blinken einer anderen Diode sein. Einfach und sinnvoll.

Zusammenbau der Schaltung
Wir müssen das USB-USART-Konvertermodul mit den USART-Pins des Mikrocontrollers verbinden. Nehmen Sie dazu eine Brücke aus zwei Drähten und stecken Sie diese über Kreuz auf die Stifte. Das heißt, wir verbinden den Rx des Controllers mit dem Tx des Konverters und den Tx des Konverters mit dem Rx des Controllers.

Am Ende ist dies das Diagramm:


Ich denke nicht darüber nach, die restlichen Pins anzuschließen, mit Strom zu versorgen oder zurückzusetzen, das ist Standard.

Code schreiben

Lassen Sie mich gleich einen Vorbehalt machen, dass ich nicht speziell auf die Beschreibung der C-Sprache selbst eingehen werde. Dafür gibt es einfach riesig viel Material, angefangen von der klassischen „C Programming Language“ von K&R bis hin zu diversen Handbüchern.

Ich habe eine solche Methode in meinem Vorrat gefunden; ich habe sie einmal verwendet, um diese Sprache zu lernen. Alles dort ist kurz, klar und auf den Punkt gebracht. Ich stelle es nach und nach zusammen und ziehe es auf meine Website.

Es stimmt, dass noch nicht alle Kapitel übertragen wurden, aber ich denke, das wird nicht mehr lange dauern.

Es ist unwahrscheinlich, dass ich es besser beschreiben kann. Deshalb werde ich vom Schulungskurs aus statt einer detaillierten Erklärung der Feinheiten einfach direkte Links zu einzelnen Seiten dieses Handbuchs bereitstellen.

Bibliotheken hinzufügen.
Zunächst fügen wir die notwendigen Bibliotheken und Header mit Definitionen hinzu. Schließlich ist C eine universelle Sprache und wir müssen ihm erklären, dass wir speziell mit AVR arbeiten, also schreiben Sie die Zeile in den Quellcode:

1 #enthalten

#enthalten

Diese Datei befindet sich im Ordner WinAVR und es enthält eine Beschreibung aller Register und Ports des Controllers. Darüber hinaus ist alles dort knifflig, mit Bindung an einen bestimmten Controller, der vom Compiler über übermittelt wird machen Datei im Parameter MCU und basierend auf dieser Variablen wird eine Header-Datei mit einer Beschreibung der Adressen aller Ports und Register für diesen bestimmten Controller mit Ihrem Projekt verbunden. Wow! Ohne sie ist es auch möglich, aber dann können Sie keine symbolischen Registernamen wie SREG oder UDR verwenden und müssen sich die Adresse jedes einzelnen wie „0xC1“ merken, was Kopfschmerzen bereiten wird.

Das Team selbst #enthalten<имя файла> ermöglicht es Ihnen, Inhalte jeglicher Art zu Ihrem Projekt hinzuzufügen Textdatei, zum Beispiel eine Datei mit einer Funktionsbeschreibung oder ein anderer Code. Und damit die Direktive diese Datei finden konnte, haben wir den Pfad zu unserem Projekt angegeben (das WinAVR-Verzeichnis ist dort standardmäßig bereits registriert).

Hauptfunktion.
Ein C-Programm besteht ausschließlich aus Funktionen. Sie können in beliebiger Reihenfolge verschachtelt und voneinander aufgerufen werden verschiedene Wege. Jede Funktion verfügt über drei erforderliche Parameter:

  • Der Rückgabewert ist z.B. Sünde(x) gibt den Wert des Sinus von x zurück. Kurz gesagt, wie in der Mathematik.
  • Die übertragenen Parameter sind die gleichen X.
  • Funktionskörper.

Alle übertragenen und zurückgegebenen Werte müssen abhängig von den Daten von einem bestimmten Typ sein.

Jedes C-Programm muss eine Funktion enthalten hauptsächlich als Einstiegspunkt in das Hauptprogramm, sonst ist es überhaupt nicht C :). Anhand des Vorhandenseins von main im Quellcode einer anderen Person aus einer Million Dateien können Sie verstehen, dass dies der Hauptteil des Programms ist, in dem alles beginnt. Fragen wir also:

1 2 3 4 5 int main(void) ( return 0 ; )

int main(void) ( return 0; )

Das war's zunächst einmal einfachstes Programm geschrieben, es spielt keine Rolle, dass es nichts bringt, wir haben gerade erst angefangen.

Lassen Sie uns herausfinden, was wir getan haben.
int Dies ist der Datentyp, den die Hauptfunktion zurückgibt.

Natürlich in einem Mikrocontroller hauptsächlich Grundsätzlich kann nichts zurückgegeben werden, und theoretisch sollte dies auch der Fall sein void main(void), aber GCC wurde ursprünglich für den PC entwickelt und dort kann das Programm den Wert zurückgeben Betriebssystem nach Fertigstellung. Daher GCC auf void main(void) schwört auf Warnung.

Das ist kein Fehler, es wird funktionieren, aber ich mag keine Warnungen.

Leere Dies ist in diesem Fall die Art von Daten, die wir an die Funktion übergeben hauptsächlich kann daher auch nichts von außen annehmen Leere- Ein Dummy. Ein Stub wird verwendet, wenn keine Notwendigkeit besteht, etwas zu übertragen oder zurückzusenden.

Hier sind sie { } Geschweifte Klammern sind ein Programmblock, in diesem Fall der Rumpf einer Funktion hauptsächlich, der Code befindet sich dort.

zurückkehren- Dies ist der Rückgabewert, den die Hauptfunktion nach Abschluss zurückgibt. Da wir ein int, also eine Zahl, haben, müssen wir eine Zahl zurückgeben. Obwohl dies immer noch keinen Sinn ergibt, weil... Auf dem Mikrocontroller können wir von main aus nur nirgendwo hingehen. Ich gebe null zurück. Weil es egal ist. Der Compiler ist jedoch normalerweise intelligent und generiert für diesen Fall keinen Code.
Obwohl, wenn pervers, dann von hauptsächlich Sie können zum MK gehen – zum Beispiel in den Bootloader-Bereich gehen und ihn ausführen, aber dies erfordert ein leichtes Basteln an der Firmware, um die Übergangsadressen zu korrigieren. Im Folgenden werden Sie es selbst sehen und verstehen, wie es geht. Wofür? Das ist eine andere Frage, in 99,999 % der Fälle ist dies nicht notwendig :)

Wir haben es geschafft und sind weitergezogen. Fügen wir eine Variable hinzu, wir brauchen sie nicht wirklich und es macht keinen Sinn, Variablen ohne sie einzuführen, aber wir lernen. Wenn Variablen innerhalb des Funktionskörpers hinzugefügt werden, sind sie lokal und existieren nur in dieser Funktion. Wenn Sie die Funktion verlassen, werden diese Variablen gelöscht und der RAM-Speicher für wichtigere Zwecke reserviert. .

1 2 3 4 5 6 int main(void) (unsigned char i; return 0;)

int main(void) ( unsigned char i; return 0; )

ohne Vorzeichen bedeutet unsigniert. Tatsache ist, dass in der binären Darstellung das höchstwertige Bit dem Vorzeichen zugewiesen wird, was bedeutet, dass die Zahl +127/-128 in ein Byte (char) passt, aber wenn das Vorzeichen verworfen wird, passt es von 0 bis 255. Normalerweise ist das Zeichen nicht erforderlich. Also ohne Vorzeichen.
ich ist nur ein Variablenname. Nicht mehr.

Jetzt müssen wir die Ports initialisieren und UART. Natürlich können Sie die Bibliothek nehmen und verbinden und eine Art UartInit(9600) aufrufen; aber dann weiß man nicht, was wirklich passiert ist.

Wir machen das:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main(void ) ( unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider) ; UBRRH = HI(bauddivider) ; UCSRA = 0 ; UCSRB = 1<< RXEN| 1 << TXEN| 1 << RXCIE| 0 << TXCIE; UCSRC = 1 << URSEL| 1 << UCSZ0| 1 << UCSZ1; }

int main(void) ( unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO(Baudteiler); UBRRH = HI(Baudteiler); UCSRA = 0; UCSRB = 1<

Beängstigend? Tatsächlich gibt es nur fünf letzte Zeilen echten Codes. Alles das #definieren Es handelt sich um eine Präprozessor-Makrosprache. Fast das Gleiche wie in Assembly, aber die Syntax ist etwas anders.

Sie erleichtern Ihnen die routinemäßige Berechnung der erforderlichen Koeffizienten. In der ersten Zeile sagen wir stattdessen das XTAL Sie können 8000000 sicher ersetzen, und L- Angabe des Typs, wobei long die Taktfrequenz des Prozessors ist. Das selbe Baudrate— Häufigkeit der Datenübertragung über UART.

Baudteiler bereits komplizierter, stattdessen wird der nach der Formel aus den beiden vorherigen berechnete Ausdruck ersetzt.
Gut und L.O. Und HALLO Die Low- und High-Bytes werden aus diesem Ergebnis übernommen, weil Offensichtlich passt es möglicherweise nicht in ein Byte. IN HALLO X (der Makro-Eingabeparameter) wird achtmal nach rechts verschoben, sodass nur noch das höchstwertige Byte übrig bleibt. Und in L.O. Wir führen ein bitweises UND mit der Zahl 00FF durch, als Ergebnis bleibt nur das Low-Byte übrig.

Alles, was getan wird, ist also wie #definieren Sie können es getrost wegwerfen, die notwendigen Zahlen auf einem Taschenrechner berechnen und sie sofort in die Zeilen UBBRL = … eingeben. und UBBRH = …..

Dürfen. Aber! Mach das ABSOLUT UNMÖGLICH!

Es wird so oder so funktionieren, aber Sie werden so genannte haben magische Zahlen- Werte, die aus dem Nichts und aus unbekannten Gründen übernommen wurden, und wenn Sie in ein paar Jahren ein solches Projekt eröffnen, wird es verdammt schwierig sein, diese Werte zu verstehen. Selbst jetzt muss, wenn Sie die Geschwindigkeit oder die Quarzfrequenz ändern möchten, alles neu berechnet werden, aber Sie haben ein paar Zahlen im Code geändert und das war’s. Wenn Sie nicht als Programmierer abgestempelt werden möchten, sollten Sie Ihren Code im Allgemeinen so gestalten, dass er leicht lesbar, verständlich und leicht zu ändern ist.

Dann ist alles ganz einfach:
All diese „UBRRL und Co“ sind Konfigurationsregister des UART-Senders, mit dessen Hilfe wir mit der Welt kommunizieren werden. Und nun haben wir ihnen die erforderlichen Werte zugewiesen und sie auf die gewünschte Geschwindigkeit und den gewünschten Modus eingestellt.

Aufnahmetyp 1< Bedeutet Folgendes: Nimm 1 und platziere es RXEN in Byte. RXEN Dies ist das 4. Bit des Registers UCSRB, Also 1< bildet die Binärzahl 00010000, TXEN- das ist das 3. Bit, und 1< ergibt 00001000. Einzelnes „|“ es ist bitweise ODER, also 00010000 | 00001000 = 00011000. Auf die gleiche Weise werden die verbleibenden notwendigen Konfigurationsbits gesetzt und dem allgemeinen Heap hinzugefügt. Infolgedessen wird die gesammelte Nummer im UCSRB erfasst. Weitere Details sind im Datenblatt zum MK im Abschnitt USART beschrieben. Lassen wir uns also nicht von technischen Details ablenken.

Fertig, Zeit zu sehen, was passiert ist. Klicken Sie auf Kompilierung und starten Sie die Emulation (Strg+F7).

Debuggen
Allerlei Fortschrittsbalken liefen durch, das Studio veränderte sich und neben dem Eingang zur Hauptfunktion erschien ein gelber Pfeil. Hier läuft der Prozessor gerade und die Simulation ist pausiert.

Tatsache ist, dass es anfangs tatsächlich in der Zeile UBRRL = LO(bauddivider); Schließlich handelt es sich bei define nicht um Code, sondern lediglich um vorläufige Berechnungen, weshalb der Simulator etwas langweilig ist. Aber jetzt wurde ihm klar, dass die erste Anweisung abgeschlossen ist und wenn man auf den Baum klettert E/A-Ansicht Gehen Sie zum USART-Abschnitt und sehen Sie sich dort das UBBRL-Byte an. Sie werden sehen, dass der Wert bereits vorhanden ist! 0x33.

Gehen Sie noch einen Schritt weiter. Sehen Sie, wie sich der Inhalt des anderen Registers ändert. Gehen Sie sie also alle durch und achten Sie darauf, dass alle angegebenen Bits so gesetzt sind, wie ich es Ihnen gesagt habe, und dass sie gleichzeitig für das gesamte Byte gesetzt sind. Es geht nicht weiter als Return – das Programm ist beendet.

Öffnung
Setzen Sie nun die Simulation auf Null zurück. Klicken Sie dort Zurücksetzen (Umschalt+F5). Öffnen Sie die zerlegte Auflistung, nun sehen Sie, was tatsächlich im Controller passiert. Ansicht -> Disassembler. Und nicht YAAAAAA!!! Monteur!!! GRUSEL!!! UND ES IST NOTWENDIG. Damit man später, wenn mal etwas schiefgeht, sich im Code nicht dumm verhält und in den Foren keine lahmen Fragen stellt, sondern sich sofort ins Zeug legt und schaut, wo man nicht weiterkommt. Da gibt es nichts Beängstigendes.

Zunächst gibt es Tops aus der Serie:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +00000000: 940C002A JMP 0x0000002A Sprung +00000002: 940C0034 JMP 0x00000034 Sprung +00000004: 940C0034 JMP 0x00000034 Sprung +00000006: 940C0034 J MP 0 x00000034 Sprung +00000008: 940C0034 JMP 0x00000034 Sprung +0000000A: 940C0034 JMP 0x00000034 Sprung +0000000C: 940C0034 JMP 0x00000034 Sprung + 0000000E: 940C0034 JMP 0x00000034 Sprung +00000010: 940C0034 JMP 0x00000034 Sprung +00000012: 940C0034 JMP 0x00000034 Sprung +00000014: 940C0034 J MP 0x00000034 Sprung +00000016: 940C0034 JMP 0x00000034 Sprung +00000018: 940C0034 JMP 0x00000034 Sprung +0000001A: 940C0034 JMP 0x00000034 Sprung +000000 1C : 940C0034 JMP 0x00000034 Sprung +0000001E: 940C0034 JMP 0x00000034 Sprung +00000020: 940C0034 JMP 0x00000034 Sprung +00000022: 940C0034 JMP 0x0000 0034 Sprung +00000024: 940C0034 JMP 0x00000034 Sprung +00000026: 940C0034 JMP 0x00000034 Sprung +00000028: 940C0034 JMP 0x00000034 Springen

00000000: 940C002A JMP 0x0000002A Sprung +00000002: 940C0034 JMP 0x00000034 Sprung +00000004: 940C0034 JMP 0x00000034 Sprung +00000006: 940C0034 J MP 0 x00000034 Sprung +00000008: 940C0034 JMP 0x00000034 Sprung +0000000A: 940C0034 JMP 0x00000034 Sprung +0000000C: 940C0034 JMP 0x00000034 Sprung + 000000 0E : 940C0034 JMP 0x00000034 Sprung +00000010: 940C0034 JMP 0x00000034 Sprung +00000012: 940C0034 JMP 0x00000034 Sprung +00000014: 940C0034 JMP 0x0000 0034 Sprung +00000016: 940C0034 JMP 0x00000034 Sprung +00000018: 940C0034 JMP 0x00000034 Sprung +0000001A: 940C0034 JMP 0x00000034 Sprung +0000001C: 940C0034 JMP 0x00000034 Sprung +0000001E: 940C0034 JMP 0x00000034 Sprung +00000020: 940C0034 JMP 0x00000034 Sprung +00000022: 940C0034 JMP 0 x000000 34 Sprung +00000024: 940C0034 JMP 0x00000034 Sprung +00000026: 940C0034 JMP 0x00000034 Sprung +00000028: 940C0034 JMP 0x00000034 Sprung

Dies ist die Interrupt-Vektortabelle. Wir werden später darauf zurückkommen, aber jetzt schauen Sie einfach hin und denken Sie daran, dass es existiert. Die erste Spalte ist die Adresse der Flash-Zelle, in der sich der Befehl befindet, die zweite ist der Befehlscode, die dritte ist die Befehlsmnemonik, die gleiche Assembleranweisung, die dritte sind die Operanden des Befehls. Nun ja, automatischer Kommentar.
Wenn Sie also hinschauen, gibt es kontinuierliche Übergänge. Und der JMP-Befehlscode besteht aus vier Bytes, er enthält die rückwärts geschriebene Sprungadresse – das Low-Byte an der Low-Adresse und den Sprungbefehlscode 940C

0000002B: BE1F OUT 0x3F,R1 Ausgang zum E/A-Standort

Notieren Sie diese Null an der Adresse 0x3F. Wenn Sie sich die Spalte „E/A-Ansicht“ ansehen, sehen Sie, dass die Adresse 0x3F die Adresse des SREG-Registers ist – das Flag-Register des Controllers. Diese. Wir setzen SREG zurück, um das Programm unter Nullbedingungen auszuführen.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Sofort laden +0000002D: E0D4 LDI R29,0x04 Sofort laden +0000002E: BFDE OUT 0x3E,R29 Ausgang zum E/A-Standort +0000002F: BFCD OUT 0x3D,R28 Ausgang zum E/A-Standort

0000002C: E5CF LDI R28,0x5F Sofort laden +0000002D: E0D4 LDI R29,0x04 Sofort laden +0000002E: BFDE OUT 0x3E,R29 Ausgang zum E/A-Standort +0000002F: BFCD OUT 0x3D,R28 Ausgang zum E/A-Standort

Dadurch wird der Stapelzeiger geladen. Sie können nicht direkt in E/A-Register laden, sondern nur über ein Zwischenregister. Deshalb zuerst LDI zum Intermediate und dann von dort OUT zum I/O. Ich werde Ihnen später auch mehr über den Stapel erzählen. Beachten Sie zunächst, dass es sich um einen dynamischen Speicherbereich handelt, der am Ende des RAM hängt und Adressen und Zwischenvariablen speichert. Jetzt haben wir angegeben, wo unser Stapel beginnen soll.

00000032: 940C0041 JMP 0x00000041 Sprung

Springen Sie zum Ende des Programms, und dort gibt es ein Verbot von Interrupts und engen Schleifen auf sich selbst:

1 2 +00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relativer Sprung

00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relativer Sprung

Dies ist der Fall, wenn unvorhergesehene Umstände eintreten, beispielsweise das Verlassen der Hauptfunktion. Der Controller kann aus einer solchen Schleife entweder durch einen Hardware-Reset oder, was wahrscheinlicher ist, durch einen Reset durch einen Watchdog gebracht werden. Nun, oder, wie ich oben sagte, korrigieren Sie dies im Hex-Editor und galoppieren Sie dorthin, wohin unser Herz begehrt. Beachten Sie außerdem, dass es zwei Arten von Übergängen gibt: JMP und RJMP; die erste ist ein direkter Übergang zu einer Adresse. Es belegt vier Bytes und kann den gesamten Speicherbereich direkt durchspringen. Die zweite Art des Übergangs ist RJMP – relativ. Sein Befehl benötigt zwei Bytes, aber er bewegt sich von der aktuellen Position (Adresse) 1024 Schritte vorwärts oder rückwärts. Und seine Parameter geben den Versatz vom aktuellen Punkt an. Es wird häufiger verwendet, weil nimmt in einer Spülung die Hälfte des Platzes ein und lange Übergänge sind selten erforderlich.

1 +00000034: 940C0000 JMP 0x00000000 Sprung

00000034: 940C0000 JMP 0x00000000 Sprung

Und dies ist ein Sprung zum Anfang des Codes. Eine Art Neustart. Hier können Sie überprüfen, ob alle Vektoren springen. Die Schlussfolgerung daraus ist, dass, wenn Sie jetzt Interrupts aktivieren (sie sind standardmäßig deaktiviert) und Ihr Interrupt auftritt, aber kein Handler vorhanden ist, ein Software-Reset erfolgt – das Programm wird an den Anfang zurückgeworfen.

Funktion main. Alles ist ähnlich, man muss es nicht einmal beschreiben. Schauen Sie sich einfach an, wie die bereits berechnete Zahl in die Register eingetragen wird. Der Compiler-Präprozessor rockt!!! Also keine „magischen“ Zahlen!

1 2 3 4 5 6 7 8 9 10 11 12 <

00000036: E383 LDI R24,0x33 Sofortiges Laden +00000037: B989 OUT 0x09,R24 Ausgang zum E/A-Platz 15: UBRRH = HI(bauddivider); +00000038: BC10 OUT 0x20,R1 Out zum E/A-Standort 16: UCSRA = 0; +00000039: B81B OUT 0x0B,R1 Ausgang an E/A-Platz 17: UCSRB = 1<

Und hier ist der Fehler:

1 2 3 +0000003E: E080 LDI R24.0x00 Sofort laden +0000003F: E090 LDI R25.0x00 Sofort laden +00000040: 9508 RET Unterprogramm-Rückkehr

0000003E: E080 LDI R24.0x00 Sofort laden +0000003F: E090 LDI R25.0x00 Sofort laden +00000040: 9508 RET Unterprogramm-Rückkehr

Die Frage ist, warum der Compiler solche Spitzen hinzufügt. Und das ist nichts weiter als Return 0, wir haben die Funktion als int main(void) definiert und damit weitere vier Bytes umsonst verschwendet :) Und wenn Sie void main(void) machen, bleibt nur RET übrig, aber es erscheint eine Warnung , dass unsere Hauptfunktion nichts zurückgibt. Im Allgemeinen tun Sie, was Sie möchten :)

Schwierig? Scheinbar nicht. Klicken Sie im Disassembler-Modus auf Schritt-für-Schritt-Ausführung und sehen Sie, wie der Prozessor einzelne Anweisungen ausführt und was mit den Registern passiert. Wie erfolgt die Bewegung durch Befehle und die Endschleife?

Fortsetzung folgt in ein paar Tagen...

Off Top:
Alexei78 Ich habe ein Plugin für Firefox erstellt, das die Navigation auf meiner Website und im Forum erleichtert.
Diskussion und Download,


Mikrocontroller sind aus dem modernen Amateurfunk nicht mehr wegzudenken, und das liegt auf der Hand. In den letzten Jahrzehnten haben Mikrocontroller verschiedener Hersteller in verschiedenen Bereichen der menschlichen Tätigkeit Verbreitung gefunden. Sie sind oft in den unerwartetsten Geräten und Designs zu finden. Sie und ich sind Zeugen der Computerisierung und Automatisierung der Prozesse um uns herum. Die Wahrheit ist, dass es ohne Kenntnisse der Grundlagen der Programmierung fast unmöglich geworden ist, moderne, wettbewerbsfähige Geräte zu entwickeln ...

Wenn Sie diesen Artikel lesen, möchten Sie wahrscheinlich verstehen, wie Mikrocontroller funktionieren, und haben höchstwahrscheinlich Fragen:

4. Welche Literatur soll ich studieren?

Versuchen wir, diese Fragen zu beantworten.

1. Welchen Mikrocontroller sollte ich für den Job wählen?

8-Bit-Mikrocontroller erfreuen sich bei Funkamateuren großer Beliebtheit. Bild Mikrochip-Technologie und AVR Atmel, 16-Bit MSP430 von TI sowie 32-Bit-Mikrocontroller-Architekturen ARM.

In der Industrie, etwas anders, belegt mit großem Abstand der erste Platz Renesas Electronics auf dem zweiten Freescale, auf dem Dritten Samsung, dann geh Mikrochip Und T.I., dann der ganze Rest.
Die Beliebtheit wird durch Preis und Verfügbarkeit bestimmt; die Verfügbarkeit technischer Informationen und die Kosten für den Software-Support spielen eine wesentliche Rolle.

Wir werden 8-Bit-AVR-Mikrocontroller-Familien untersuchen ATMEGA 8- und 16-Serie. Ausschlaggebend für die Wahl waren wiederum die Zugänglichkeit, das Vorhandensein vieler Amateurentwicklungen und eine große Menge an Lehrmaterial. Das Vorhandensein einer Vielzahl eingebauter Komponenten und die Funktionalität dieser Familie.

2. Welche Entwicklungsumgebung sollte ich zum Programmieren des ausgewählten Mikrocontrollers verwenden?

Für AVR wurden verschiedene integrierte Entwicklungsumgebungen (IDE, Integrated Development Environment) erstellt.
IDE ist ein Softwaresystem, das von Programmierern zur Entwicklung von Software verwendet wird und Folgendes umfasst:
Texteditor,
Compiler und/oder Interpreter,
Werkzeuge zur Montageautomatisierung,
Debugger

Die häufigsten AVRStudio, ATmelStudio, WINAVR, CodeVision, IAR Embedded Workbench.
Um Programme zu schreiben, verwenden wir das kostenlose IDE ATmelStudio Version 6 und höher.
Sie können Atmel Studio nach der Registrierung von der offiziellen Website herunterladen (die Registrierung ist absolut kostenlos und verpflichtet Sie zu nichts!)

Mit ATmelStudio können Sie Projekte erstellen und Programme sowohl in Assembler als auch in SI schreiben.

Zunächst stellt sich immer die Frage: Welche Programmiersprache sollte ich wählen, um effektive Programme zu schreiben?

Meine Antwort ist einfach: Sie müssen in mindestens zwei Sprachen schreiben können: Assembler und SI. Assemblersprache ist einfach notwendig, wenn Sie schnelle und kompakte Unterprogramme und Makros sowie verschiedene Gerätetreiber schreiben müssen. Wenn Sie jedoch ohne SI-Kenntnisse ein großes Projekt erstellen müssen, das auf komplexen Algorithmen basiert, kann viel Zeit aufgewendet werden, insbesondere im Debugging-Prozess und wenn der Wunsch besteht, es auf eine andere Plattform, beispielsweise PIC18, zu übertragen , oder STM, kann es zu einem unlösbaren Problem werden.
Darüber hinaus sind mittlerweile Hardware-Computing-Plattformen erschienen Arduino, deren Arbeit Kenntnisse der SI++-Sprache erfordert.
Daher werden wir Programme sowohl in Assembler als auch in SI schreiben.

Um das Ergebnis Ihrer Arbeit deutlich zu sehen, ohne einen Lötkolben oder ein Steckbrett zu verwenden, installieren Sie einfach das Programm Proteus.

3. Wie wird der Controller geflasht und welche zusätzlichen Geräte und Zubehörteile werden benötigt, um bequem damit arbeiten zu können?

Wir verwenden Datagorian. Darüber hinaus müssen Sie Steckplatinen und ein Netzteil mit einer Ausgangsspannung von 5 Volt kaufen. Sie können es als Stromversorgung mit geringer Restwelligkeit verwenden, indem Sie eine 5-Volt-Zenerdiode verwenden.
Vielleicht werden Igor und ich im Laufe der Zeit ein Projekt zum Zusammenbau eines Debug-Boards vorschlagen.

4. Welche Literatur soll ich studieren?

Aber zum Beispiel:
Praktische Programmierung von AVR in Assembler. Revich, 2011
1000 und eine Mikrocontroller-Schaltung Vol. 1-2. Ryumik, 2010-2011
10 praktische Geräte zum AVR MK Book 1-2. Krawtschenko, 2008-2009
Ein Tutorial für einen Geräteentwickler, der den AVR MK verwendet. Belov, 2008
MK AVR-Familien Tiny und Atmega. Efstifeev, 2008
CodeVisionAVR. Ein Leitfaden für Anfänger. Lebedew, 2008
Mikroprozessorsteuerung von Geräten, Thyristoren, Relais. Belov, 2008
Analoge Schnittstellen MK. Steward, Ball, 2007
Wir erstellen Geräte auf dem AVR MK. Belov, 2007
MK AVR in der Amateurfunkpraxis. Vollständige Analyse von ATTINY2313. Belov, 2007
Netzwerk- und Internetdatenaustausch mit MK. Geh, 2007
MK AVR. Workshop für Einsteiger. Hartov, 2007
Anwendung von AVR-Schemata, Algorithmen, Programmen. Baranow, 2006
AVR-Mikrocontroller. Einführungskurs. Morton, 2006
Messung, Steuerung und Regelung mittels AVR. Trumpert, 2006
Programmierung in C-Sprache für AVR und PIC MK. Shpak, 2006
Design von Geräten auf MK. Belov, 2005
MK – ganz einfach, Band 1-3. Frunse, 2002-2003
Die Programmiersprache C, 2. Auflage. Kernighan, Ritchie, 2009
Programmierung von ATMEL-Mikrocontrollern in der Sprache S. Prokopenko, 2012

5. Wo im Internet kann man Fragen stellen und konkrete Antworten erhalten?

Sie können Fragen in unserem oder jedem anderen Forum stellen, in dem Themen zu Mikrocontrollern auf die eine oder andere Weise berührt werden. In Foren geht es vor allem darum, Fragen richtig zu formulieren, um eindeutige Antworten zu erhalten. Abstrakte Fragen sind nicht erwünscht und höchstwahrscheinlich erhalten Sie statt einer Antwort harsche Kritik, oder Ihre Frage bleibt unbeantwortet!

Schauen wir uns nun unseren Favoriten, den ATMEGA 8-Mikrocontroller, genauer an

8-Bit-AVR-Mikrocontroller mit hoher Leistung und geringem Stromverbrauch
Progressive RISC-Architektur
130 Hochleistungsanweisungen, die meisten Anweisungen werden in einem Taktzyklus ausgeführt
32 8-Bit-Allzweck-Arbeitsregister
Völlig statischer Betrieb
Nahezu 16 MIPS (bei 16 MHz) Leistung
Eingebauter 2-Zyklus-Multiplikator

Nichtflüchtiger Programm- und Datenspeicher
8 KB selbstprogrammierbarer Flash-Speicher im System
Bietet 1000 Lösch-/Schreibzyklen
Zusätzlicher Bootcode-Sektor mit unabhängigen Sperrbits
Bietet gleichzeitigen Lese-/Schreibmodus (Read-While-Write)
512 Byte EEPROM
Bietet 100.000 Lösch-/Schreibzyklen
1 KB On-Chip-SRAM
Programmierbare Sperre zum Schutz der Benutzersoftware

Eingebettete Peripheriegeräte
Zwei 8-Bit-Timer/Zähler mit separatem Vorteiler, einer mit Vergleichsmodus
Ein 16-Bit-Timer/Zähler mit separatem Vorteiler sowie Erfassungs- und Vergleichsmodi
Echtzeitzähler mit separatem Generator
Drei PWM-Kanäle
8-Kanal-A/D-Wandler (TQFP und MLF)
6 Kanäle mit 10-Bit-Präzision
6-Kanal-Analog-Digital-Wandler (im PDIP-Paket)
4 Kanäle mit 10-Bit-Präzision
2 Kanäle mit 8-Bit-Präzision
Byteorientierte 2-Draht-serielle Schnittstelle
Programmierbarer serieller USART
Serielle Schnittstelle SPI (Master/Slave)
Programmierbarer Watchdog-Timer mit separatem eingebautem Oszillator
Eingebauter Analogkomparator

Spezielle Mikrocontrollerfunktionen
Power-on-Reset und programmierbare Spannungsabfallerkennung
Eingebauter kalibrierter RC-Oszillator
Interne und externe Interrupt-Quellen
Fünf Modi mit geringem Verbrauch: Leerlauf, Energiesparmodus, Ausschalten, Standby und ADC-Rauschunterdrückung

I/O-Pins und Gehäuse
23 programmierbare I/O-Leitungen
28-poliges PDIP-Gehäuse, 32-poliges TQFP-Gehäuse und 32-poliges MLF-Gehäuse

Betriebsspannungen
2,7 - 5,5 V (ATmega8L)
4,5 - 5,5 V (ATmega8)

Arbeitsfrequenz
0 - 8 MHz (ATmega8L)
0 - 16 MHz (ATmega8)

Unterschiede zwischen ATMEGA16 und 8
16 KB selbstprogrammierbarer Flash-Speicher im System

JTAG-Schnittstelle (IEEE 1149.1-konform)
Peripherie-Scanfunktion gemäß JTAG-Standard
Erweiterte Unterstützung für eingebettetes Debugging
Programmierung über JTAG-Schnittstelle: Flash, EEPROM-Speicher, Jumper und Lockbits

Vier Kanäle PWM/PWM

8-Kanal-10-Bit-Analog-Digital-Wandler
8 unsymmetrische Kanäle
7 Differenzkanäle (nur TQFP-Paket)
2 Differenzkanäle mit programmierbarer Verstärkung von 1x, 10x oder 200x (nur TQFP-Paket)

Sechs Modi mit geringem Verbrauch: Leerlauf, Energiesparmodus, Ausschalten, Standby, erweiterter Standby und ADC-Rauschunterdrückung

32 programmierbare I/O-Leitungen

40-poliges PDIP-Gehäuse und 44-poliges TQFP-Gehäuse

AtmelStudio

Wenn Sie gerade erst anfangen, müssen Sie das AtmelStudio-Programm von der offiziellen Seite atmel.com herunterladen und installieren
Nach der Installation des AtmelStudio-Programms können Sie mit der Erstellung eines Projekts beginnen.
Projekt- Dies ist Ihr Programm, das Sie nach der Kompilierung in den Speicher des Mikrocontrollers schreiben, debuggen und flashen.

Um ein Projekt zu erstellen, müssen Sie das Programm öffnen. Der folgende Bildschirmschoner wird angezeigt:

und die Seite zur Projekterstellung wird geöffnet

Um ein neues Projekt zu erstellen, müssen Sie auf klicken "Neues Projekt..."
In diesem Fall öffnet sich ein neues Fenster, in dem Sie die Programmiersprache, den Namen des Projekts, seinen Speicherort, den Namen des Pakets mit den Projektdateien und die Möglichkeit auswählen können, ein Verzeichnis zur weiteren Verwendung in anderen projektübergreifenden Projekten zu erstellen . Um ein Projekt zu erstellen, in dem wir in Assembler programmieren, müssen wir Folgendes auswählen: Monteur, danach ändern wir den Namen des Projekts, seinen Speicherort und wählen OK.

Das folgende Fenster wird angezeigt

Wählen „megaAVR, 8-bit“ und den Mikrocontroller finden, den wir brauchen, wir haben uns entschieden ATmega8. Auf der rechten Seite des Bildschirmschoners erscheint eine Liste der Geräte, die mit diesem Mikrocontroller arbeiten, von denen wir eines verbinden können. Wählen OK.

Die Texteditorseite wird angezeigt, auf der Sie das Programm bearbeiten und debuggen können. Während die Seite leer ist, werden Uhrzeit und Datum der Erstellung sowie der Name der Projektdatei und der Benutzername angezeigt. Es gibt ein zusätzliches Fenster für E/A-Geräte und ein Fenster für Programmkompilierungsberichte. Jetzt wir


Wir können in Assembler programmieren.
Auf die gleiche Weise wird ein Projekt zur Programmierung in SI-Sprache erstellt.

Hallo, MySku-Bewohner! Der Held unseres Tests ist der Mikrocontroller Atmega8A-16PU. Ich erzähle Ihnen von der Programmierung dieses Mikrocontrollers in der integrierten Entwicklungsumgebung CodeVisionAvr, wir werden die LED blinken lassen und wir werden die Vor- und Nachteile der Arbeit in dieser Umgebung abwägen. Vielleicht dient Ihnen dies in Zukunft als Alternative zum bereits „populären“ Arduino. Wenn Sie interessiert sind, gehen Sie zum Schneiden.

Präambel.
Zufälligerweise begann ich meine Bekanntschaft mit MK mit Arduino. Ich ließ die LED blinken, schloss verschiedene Sensoren und Abschirmungen an und machte verschiedene Projekte. Alles hat funktioniert, ich war zufrieden, aber ich wollte noch mehr. Ich bin auf ein Projekt gestoßen, bei dem es um Atmega8A geht und für das ich die Firmware selbst schreiben muss. Er war es, der mich dazu drängte, den Prozess der Programmierung eines „nackten“ MK zu studieren.
Wir haben also einen Mikrocontroller von Atmel, AVR Atmega8A-Familie.

Technische Eigenschaften:


Pinbelegung:


Hier ist
Für den Betrieb und die Programmierung müssen Sie es nun gemäß dem Diagramm an den Programmierer anschließen:

Leider bin ich wie ein Schuhmacher – ohne Stiefel, jetzt habe ich keinen Programmierer zur Hand, also werde ich mit Arduino UNO die fertige Firmware in den Mikrocontroller laden und die Sicherungen konfigurieren. Sie müssen lediglich die „Arduinoisp“-Skizze aus dem Beispielordner der Arduino IDE herunterladen und sie gemäß dem Diagramm verbinden:


Diese Lösung hat jedoch einen erheblichen Nachteil, auf den ich etwas später eingehen werde. Bevor wir mit dem Schreiben eines Programms in CodeVisionAvr (im Folgenden als CvAvr bezeichnet) beginnen, müssen wir entscheiden, mit welcher Frequenz unser Mikrocontroller arbeiten soll. Standardmäßig arbeitet unser Held ab Werk mit einem internen RC-Generator mit einer Frequenz von 1 MHz (mit der Möglichkeit, auf 2, 4 und 8 MHz umzukonfigurieren). Da der interne RC-Generator im Werk unter bestimmten Bedingungen (genaue Spannung, Temperatur) kalibriert wird, kann die Genauigkeit seines Betriebs unter „Feldbedingungen“ zwischen 3 % und 10 % variieren. Bei Aufgaben, bei denen keine hohe Zeitgenauigkeit erforderlich ist, kann dies vernachlässigt werden; in anderen Fällen ist es besser, externen Quarz zu verwenden. In meinem Projekt habe ich einen externen Quarz mit einer Frequenz von 8 MHz verwendet. Jetzt müssen wir dem MC „erklären“, dass er mit externem Quarz arbeiten muss. Dies geschieht durch den Austausch der Sicherungen. Vereinfacht ausgedrückt ist das so etwas wie ein BIOS, wie auf einem Motherboard, wo man seine Betriebsmodi angibt; ebenso teilen wir dem MK neben der Frequenz mit, in welchen Modi er arbeiten soll. Alle Informationen werden im nichtflüchtigen Speicher gespeichert.
Ich erzähle Ihnen unter dem Spoiler, wie man die Firmware zusammenfügt. Wer weiß, wie man es selbst macht, kann weiter scrollen.

Weitere Informationen

Wie registriere ich dieselben Sicherungen?! Hierfür habe ich das Programm AvrDude verwendet, es ist kostenlos und leicht im Internet zu finden. Um die Sicherungen entsprechend der gewünschten Frequenz richtig einzustellen, schauen Sie sich das Datenblatt an oder verwenden Sie ein einfaches.
Wir stellen die Parameter wie im Bild ein.


Hier ist alles einfach:
Taktquelle – Stellen Sie die Frequenz (externer Quarz 3 – 16 MHz) vom externen Quarz ein.
Startzeit – MC-Startgeschwindigkeit, nachdem RESET entfernt oder Strom angelegt wurde (16K CK + 4,1 ms schnell).
Aktivieren Sie das Kontrollkästchen: Ext. Takt/RC-Osz./Niederfreq. Kristall: interne Kondensatoren aktivieren (36 pF)
Interner R/C-Osk.: deaktiviert lassen! Externer Quarz: Vollschwingung aktivieren (erforderlich für >8 MHz).
Somit haben wir Low Fuse 0xEF und High Fuse 0xC9. Großartig, die Hälfte der Arbeit ist erledigt. Jetzt verbinden wir den Mikrocontroller mit dem Arduino UNO bzw. den Arduino selbst mit dem Computer. Starten Sie die Befehlszeile und gehen Sie zum Ordner mit AvrDude. Geben Sie als Nächstes die Zeile ein: avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U lfuse:w:0xef:m -U hfuse:w:0xc9:m
So sieht es auf dem Bild aus:


Lassen Sie uns die von Ihnen eingegebene Zeile analysieren:
avrisp ist eine Art unseres Arduino-ähnlichen Programmierers
COM13 ist die COM-Port-Nummer, die unser Arduino im System identifiziert (in Ihrem Fall müssen Sie sie im Gerätemanager nachschlagen)
19200 - COM-Port-Geschwindigkeit, so belassen wie es ist
m8 – zeigt an, dass unser MK Atmega8 ist
-U lfuse:w:0xef:m -U hfuse:w:0xc9:m – hier werden unsere Low Fuse 0xEF und High Fuse 0xC9 angezeigt
Sei BITTE VORSICHTIG!!, Eine falsch spezifizierte Sicherung kann dazu führen, dass der MK kaputt geht (wir müssen nicht mit einem Tamburin tanzen, um ihn wiederherzustellen).
Wir drücken „Enter“ und am Ausgang erhalten wir das Ergebnis, wie im Bild:


Treten während des Vorgangs keine Fehler auf, ist die Arbeit erledigt, unser Mikrocontroller arbeitet nun mit externem Quarz.
Über Sicherungen können Sie sich ausführlich informieren und auch bei Google suchen.


Jetzt können wir mit der Programmierung beginnen. Für mich selbst habe ich mich für die CvAvr-Entwicklungsumgebung entschieden. Die Programmiersprache wird sich von Arduino unterscheiden; in CvAvr ist sie C-ähnlich. Lasst uns unseren ersten Blink schreiben.
Nach der Installation und dem Start der Umgebung verwenden wir den Projekterstellungsassistenten. Wählen Sie „Datei“ – „Neu“ – „Projekt“. Auf die Frage, ob wir den Assistenten nutzen werden, antworten wir mit „Ja“. Ziel-AVR-Chiptyp: AT90, ATtity, ATmega.
So sieht der Projektassistent aus:


Wählen Sie auf der Registerkarte „Chip“ die Option „ATmega8A, Takt 8,000000 MHz“ aus. Gehen Sie zur Registerkarte „Ports“. Unsere LED wird entsprechend der Pinbelegung - PB0 - an Pin 14 des Mikrocontrollers angeschlossen. Wählen Sie auf der Registerkarte Port B, Bit 0, wechseln Sie von IN nach OUT, d. h. Wir schalten den Betriebsmodus des 14. Beins unseres Mikrocontrollers auf den Ausgang um.


Damit ist die Arbeit des Meisters abgeschlossen. Wählen Sie „Programm“ – „Generieren, Speichern und Beenden“. Wir speichern unser Projekt beispielsweise unter dem Namen Blink.

Besorgen wir uns so ein Fußtuch

/*******************************************************
Dieses Programm wurde von erstellt
CodeWizardAVR V3.12 Advanced
Automatischer Programmgenerator
Chiptyp: ATmega8A
Programmtyp: Bewerbung
AVR-Kerntaktfrequenz: 8,000000 MHz
Speichermodell: Klein
Externe RAM-Größe: 0
Datenstapelgröße: 256
*******************************************************/
#enthalten
#enthalten
// Deklarieren Sie hier Ihre globalen Variablen

Void main(void)
{
// Deklarieren Sie hier Ihre lokalen Variablen

// Initialisierung der Eingabe-/Ausgabe-Ports
// Initialisierung von Port B
// Funktion: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
DDRB=(0<// Status: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PORTB=(0<

// Port-C-Initialisierung
// Funktion: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<// Status: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<

// Initialisierung von Port D
// Funktion: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<// Status: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<

// Initialisierung von Timer/Zähler 0

// Uhrwert: Timer 0 gestoppt
TCCR0=(0<TCNT0=0x00;

// Initialisierung von Timer/Zähler 1
// Taktquelle: Systemuhr
// Uhrwert: Timer1 gestoppt
// Modus: Normal top=0xFFFF
// OC1A-Ausgabe: Getrennt
// OC1B-Ausgabe: Getrennt
// Geräuschunterdrückung: Aus
// Eingabeerfassung bei fallender Flanke
// Timer1-Überlaufunterbrechung: Aus
// Input Capture Interrupt: Aus
// Vergleiche eine Übereinstimmungsunterbrechung: Aus
// Compare B Match Interrupt: Aus
TCCR1A=(0<TCCR1B=(0<TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Initialisierung von Timer/Zähler 2
// Taktquelle: Systemuhr
// Uhrwert: Timer2 gestoppt
// Modus: Normal top=0xFF
// OC2-Ausgabe: Getrennt
ASSR=0<TCCR2=(0<TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Zähler(s) Interrupt(s)-Initialisierung
TIMSK=(0<

// Externe Interrupt(s)-Initialisierung
// INT0: Aus
// INT1: Aus
MCUCR=(0<

//USART-Initialisierung
// USART deaktiviert
UCSRB=(0<

// Initialisierung des Analogkomparators
// Analogkomparator: Aus
// Der positive Eingang des Analogkomparators ist
// verbunden mit dem AIN0-Pin
// Der negative Eingang des Analogkomparators ist
// verbunden mit dem AIN1-Pin
ACSR=(1<SFIOR=(0<

//ADC-Initialisierung
//ADC deaktiviert
ADCSRA=(0<

// SPI-Initialisierung
// SPI deaktiviert
SPCR=(0<

// TWI-Initialisierung
// TWI deaktiviert
TWCR=(0<

Während (1)
{


Hier besteht kein Grund zur Sorge; das Projekt spezifiziert die Betriebsmodi von Ports, Timern, Interrupts, USART, Analogkomparator, ADC, SPI und angeschlossenen Bibliotheken. Kurz gesagt, alle Parameter, die wir im Assistenten angegeben haben, bis auf die Ports und den Chip, sind standardmäßig konfiguriert. Wir werden die Hauptprogrammschleife in while (1) (Programmtext) schreiben. Weil wir arbeiten mit PB0 (14 Bein), in der Programmschleife schreiben wir:
während (1)
{
PORTB.0=1;
Verzögerung_ms(1000);
PORTB.0=0;
Verzögerung_ms(1000);
}
Hier setzen wir PB0 auf High, warten 1 Sekunde und setzen es auf Low, dann wiederholt sich der Zyklus. Vergessen Sie nicht, die Bibliothek zu Beginn des Projekts einzubinden #include . Unser Programm ist fertig!!! Wie Sie sehen, ist alles sehr einfach. Wählen Sie nun „Projekt“ – „Alle erstellen“. Wenn keine Fehler gemacht wurden, sehen wir den Bericht des Assistenten:

Die Größe unseres Programms betrug 198 Bytes und belegte 2,4 % des Speichers des Mikrometers.
Als nächstes stellen wir das Diagramm zusammen:


Gehen Sie nun in den Ordner mit unserem Projekt, gehen Sie in den Ordner „Debug“, dann auf „Exe“, dort befindet sich eine Datei mit einer Hex-Erweiterung. In meinem Fall ist es blink.hex.
Es bleibt noch ein letzter Schritt. Kopieren Sie diese Datei in den Ordner mit AvrDude. Wir starten die Befehlszeile erneut und gehen zu unserem Ordner. Geben Sie die Zeile avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U flash:w:blink.hex ein
So sieht es auf dem Bild aus:


Wenn alles richtig eingegeben ist, drücken Sie „Enter“


Glückwunsch! Die Arbeit ist erledigt, die LED sollte fröhlich für Sie blinken :)
Abschluss.
Abschließend möchte ich auf den Nachteil des Arduino-ähnlichen Programmierers eingehen: CvAvr unterstützt ihn einfach nicht. Wenn Sie beispielsweise AVRISP mkII in der Hand haben, können Sie die Sicherungen flashen und das Programm direkt von CodeVisionAvr herunterladen. Übrigens weigerte sich der Homebrew-Programmierer auch, die grafische Oberfläche von AvrDude zu verwenden und arbeitete nur über die Befehlszeile.
Ich habe CodeVisionAvr ziemlich schnell herausgefunden; das Internet ist voll von Text- und Videolektionen. In ein paar Wochen beherrschte ich die Bedienung von Hardware-PWM, Interrupts, Timern, die Arbeit mit Tasten und den Anschluss eines Grafikdisplays. Konkret musste ich einen Teil meines Projekts erledigen: ein Hardware-16-Bit-PWM auf dem Atmega8 organisieren, zwei Tasten anschließen, um es zu steuern, und auch seine Betriebsmodi auf einem Grafikdisplay anzeigen, was mir problemlos gelungen ist :) Hier sind a ein paar Fotos:

Weitere Informationen





Ergebnisse im Vergleich mit Arduino:
+ CvArv zu verstehen ist nicht schwierig, weil es gibt einen Projekterstellungsassistenten;
+ Verfügbarkeit von Plug-in-Bibliotheken, davon gibt es genug;
+ Schnelle Zusammenstellung;
+ Die Möglichkeit, ein Projekt in Proteus zu simulieren und es mit dem integrierten Debugger zu debuggen;
+ Die Größe des Programms ist um ein Vielfaches kleiner. Standard-Blink benötigte 198 Bytes, eine ähnliche Skizze in Arduino IDE 1084 Bytes + 2 KB Bootloader;
+ Fähigkeit, Modi zu implementieren, die auf Arduino nicht möglich sind. Zum Beispiel 16-Bit-PWM (im Allgemeinen ist es auf Arduino möglich, aber nur mit „Krücken“);
+ Die Möglichkeit, ATtiny- und ATmega-Mikrocontroller für Ihre Projekte zu verwenden, bei denen Arduino überflüssig wäre;
- Dennoch ist es für einen Anfänger besser, MK mit Arduino zu beherrschen;
- Die Programmiersprache unterscheidet sich von der Arduino-Verarbeitung;
- Es gibt noch mehr Bibliotheken für Arduino;
- CodeVisionAvr ist ein kostenpflichtiges Programm, es gibt kostenlose Versionen mit Einschränkungen;
Durch die Programmierung des „nackten“ Mikrocontrollers in CodeVisionAvr habe ich viel Erfahrung gesammelt. Das Studium von Timern, Registern, Betriebsarten, Architektur und das Lesen von Datenblättern wird Ihre Fähigkeiten verbessern, Ihren Horizont erweitern und neue Aspekte der Arbeit mit Mikrocontrollern eröffnen.
Als Bonus füge ich ein paar Fotos bei, als ich das grafische LCD-Display herausgefunden und ein wenig herumgespielt habe.





P.s. Es gibt noch viel mehr, worüber ich schreiben wollte, aber dies wird keine Rezension, sondern ein umfangreicher Artikel sein. Ich bin bereit, Fragen im Rahmen meiner Kompetenz privat oder in Kommentaren zu beantworten. Auf AVR können Sie viele Lektionen ansehen.

Spitze