Wenn Sie den folgenden Code in eine AVR-C-Quelle einfügen, können Sie die Sicherungen anscheinend direkt programmieren, ohne dass ein zusätzlicher Befehl oder eine .hex-Datei erforderlich ist:
#include <avr/io.h>
FUSES = {
.low = LFUSE_DEFAULT ,
.high = HFUSE_DEFAULT ,
.extended = EFUSE_DEFAULT ,
};
Gibt es einen ähnlichen Trick, um Werte im EEPROM zu programmieren?
Ich habe überprüft, /usr/lib/avr/include/avr/fuse.h
wo ich einige Kommentare zu einem Makro finden kann, aber ich kann keinen ähnlichen Kommentar in finden, /usr/lib/avr/include/avr/eeprom.h
und die Interpretation des Präprozessor-Zeugs ist ein bisschen außerhalb meiner Liga.
Es wäre wirklich praktisch, wenn ich Standard-EEPROM-Werte in den C-Quellcode aufnehmen könnte. Weiß jemand, wie man das bewerkstelligt?
Dieser FUSES-Trick wird nur zur ISP-Zeit ausgeführt, nicht zur RUN-Zeit. Es werden also keine Sicherungen im resultierenden Assembler-Code in der Steuerung programmiert. Stattdessen durchläuft der Programmierer automatisch einen zusätzlichen SICHERUNGS-Programmierzyklus.
Ich verwende die avr-gcc- und avrdude-Toolchain unter Linux.
Mit avr-gcc EEMEM
kann das Makro für die Definition einer Variablen verwendet werden, siehe die libc
Dokumentation und ein Beispiel hier :
#include <avr/eeprom.h>
char myEepromString[] EEMEM = "Hello World!";
deklariert, dass sich das Array von Zeichen in einem Abschnitt namens ".eeprom" befindet, der nach der Kompilierung dem Programmierer mitteilt, dass diese Daten in das EEPROM zu programmieren sind. Abhängig von Ihrer Programmiersoftware müssen Sie dem Programmierer den Namen der ".eep"-Datei, die während des Build-Prozesses erstellt wurde, möglicherweise explizit mitteilen, oder er findet ihn implizit von selbst.
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 ihex $(src).elf $(src).eeprom.hex
avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U eeprom:w:$(src).eeprom.hex
Ja, Sie können Standarddaten im Quellcode manuell in das EEPROM schreiben. Schauen Sie sich zuerst diese großartige Anleitung zum EEPROM mit AVR an: Dean's AVR EEPROM Tutorial. Außerdem sollte ich hinzufügen, dass es eine bessere Idee ist, eine .eep-Datei zu erstellen, die die EEPROM-Daten enthält, indem das Makefile verwendet wird, das zusammen mit dem Quellcode auf das Gerät programmiert wird. Wenn Sie jedoch mit verschiedenen Makefile- und Linker-Operationen nicht vertraut sind, können Sie dies immer noch aus Ihrer Quellcodedatei heraus tun - es geschieht einfach, sobald die Schaltung mit Strom versorgt wird, wodurch die anfängliche Programmoperation blockiert wird.
Am Anfang des Programms (vor jeder Art von Hauptschleife) könnten Sie so etwas tun:
#include <avr/eeprom.h>
#define ADDRESS_1 46 // This could be anything from 0 to the highest EEPROM address
#define ADDRESS_2 52 // This could be anything from 0 to the highest EEPROM address
#define ADDRESS_3 68 // This could be anything from 0 to the highest EEPROM address
uint8_t dataByte1 = 0x7F; // Data for address 1
uint8_t dataByte2 = 0x33; // Data for address 2
uint8_t dataByte3 = 0xCE; // Data for address 3
eeprom_update_byte((uint8_t*)ADDRESS_1, dataByte1);
eeprom_update_byte((uint8_t*)ADDRESS_2, dataByte2);
eeprom_update_byte((uint8_t*)ADDRESS_3, dataByte3);
Die „Update“-Funktion prüft zuerst, ob dieser Wert bereits vorhanden ist, um unnötige Schreibvorgänge zu vermeiden und die EEPROM-Lebensdauer zu erhalten. Dies kann jedoch für sehr viele Standorte einige Zeit in Anspruch nehmen. Es könnte besser sein, einen einzelnen Standort zu überprüfen. Ist es der gewünschte Wert, dann können die restlichen Updates komplett übersprungen werden. Zum Beispiel:
if(eeprom_read_byte((uint8_t*)SOME_LOCATION) != DESIRED_VALUE){
eeprom_write_byte((uint8_t*)SOME_LOCATION, DESIRED_VALUE);
eeprom_update_byte((uint8_t*)ADDRESS_1, dataByte1);
eeprom_update_byte((uint8_t*)ADDRESS_2, dataByte2);
eeprom_update_byte((uint8_t*)ADDRESS_3, dataByte3);
}
Wenn Sie große Datenmengen aktualisieren möchten, versuchen Sie es mit anderen Funktionen wie eeprom_update_block(...)
. Und lesen Sie auf jeden Fall dieses Tutorial. es ist gut geschrieben.
Sie könnten alle EEPROM-Aktualisierungsanweisungen in eine einzige Bedingungsanweisung des Präprozessors packen. Das geht ganz einfach:
#if defined _UPDATE_EEPROM_
#define ADDRESS_1 46 // This could be anything from 0 to the highest EEPROM address
uint8_t dataByte = 0x7F; // Data for address 1
eeprom_update_byte((uint8_t*)ADDRESS_1, dataByte1);
#endif // _UPDATE_EEPROM_
Dieses Stück Code wird nicht einmal kompiliert, es sei denn, Sie tun Folgendes:
#define _UPDATE_EEPROM_
Sie können dies dort als Kommentar hinterlassen und dann auskommentieren, wenn Sie die Standard-EEPROM-Werte ändern müssen. Weitere Informationen zum C-Präprozessor finden Sie in diesem Online-Handbuch . Ich denke, Sie interessieren sich am meisten für die Abschnitte über Makros und bedingte Anweisungen.
Ch. 7 Setting Initial Values
.EEMEM
Variablen kümmert sich der Compiler darum, welche Variable sich wo im EEPROM befindet. Auf diese Weise operieren Sie beim Zugriff auf die Daten nur mit (konstanten, vom Compiler generierten) Zeigern auf Variablen. Wenn Sie andererseits die Adresse, an der sich jede Variable befindet, explizit definieren, müssen Sie sich selbst um diese Adressen kümmern, einschließlich des Sicherstellens, dass keine Variablen versehentlich dieselbe Adresse belegen und sich gegenseitig überschreiben; oder alle Adressen neu berechnen, falls sich die Speichergröße einer Variablen in Zukunft ändert usw.
Engelgroß
PeterJ
Jippie
Chris Stratton