ich habe es eben geschaft mein erstes Programm für den PIC10F202
zu debuggen (ich bitte um Applaus :-)
Dabei ist mir aufgefallen, dass das Setzen von einzelnen Bits in einem
bitfield nicht so funktioniert, wie ich mir das dachte.
Hier mal (eine sicher bekannte) Definition eines structs, das die 4 Pins des GPIO des PIC10F202 definiert.
1
// bitfield definitions
2
typedefunion{
3
struct{
4
unsignedGP0:1;
5
unsignedGP1:1;
6
unsignedGP2:1;
7
unsignedGP3:1;
8
};
9
}GPIObits_t;
10
externvolatileGPIObits_tGPIObits__at(0x006);
Also dachte ich - naiv wie ich bin - dass folgender Code
1
GPIO&=0b001000;// set each "output" low
2
OPTION=0b10111111;
3
4
GPIObits.GP2=1;
5
GPIObits.GP1=1;
6
GPIObits.GP0=1;
folgendes Ergebnis ergibt:
GPIO = 0b00001111
Aber, es kommt folgendes heraus:
GPIO = 0b00001001
Kann mir das jemand erklären ?
Ich könnte natürlich auch einzelne Bits mit OR/XOR/AND-Operationen auf GPIO selbst setzen, aber die struct-Varante ist irgendwie schöner (wenn sie funktionieren würde).
Viele Grüße
Harry
PS.: Siehe auch den Screenshot aus der MPLAB X IDE
Bitte beachten, dass diese PICs nicht jenen Zustand lesen, den du reingeschrieben hast, sondern stets den Zustand des Pins selbst. Wenn du in einen Pin mit schwachem Pullup eine 1 reinschreibst, der Pin aber extern runter gezogen wird, liest du eine 0 zurück. TRIS mischt auch noch mit.
Dieses Verhalten kann zu recht überraschenden Effekten führen und ist der Grund, weshalb neuere Architekturen zwischen den Registern für Output und für Input unterscheiden.
Ich würde mir einfach mal den aus der C-Datei erzeugten Assemblercode
ansehen, da sieht man dann, ob und wie so ein Bit gesetzt wird.
1
!GPIObits.GP2 = 1;
2
0x174: BSF GPIO, 0x2
3
!GPIObits.GP1 = 1;
4
0x175: BSF GPIO, 0x1
5
!GPIObits.GP0 = 1;
6
0x176: BSF GPIO, 0x0
Hmmm Assemblertechnisch bin ich nicht so bewandert,
aber, wenn BSF VARIABLE, X bedeutet, dass das X-te Bit (gezählt ab 0) auf 1 gesetzt wird, dann ist mein Code okay.
Ich würde das mehrfache R-M-W aus dem Prozess entfernen und die Variante mit dem Schattenregister wählen: schreib alle deine Änderungen in ein lokales Register und schreibe dieses Register am Ende der gesammelten Portzugriffe auf das Portregister.
Dazu brauchst du natürlich einen Programmablauf, bei dem die Hauptschleife dauernd durchlaufen, an ihrem Anfang die Eingänge gelesen, diese Information bearbeitet und das Ergebnis am Ende rausgeschrieben wird. Und das dann hunterte bis zigtausendmal pro Sekunde.
Du olltest A.K. Vorschlag folgen.
Wenn ich mich recht entsinne, wird selbt im Datenblatt davor gewarnt,
an den GPIO-Bits einzeln herumzuspielen.
Richtig benutzt man entweder den Ausgabelatch, wenn der verwendete
PIC den hat, oder ein Schattenregister das man dann nach der
Bitkippelei komplett(!) ins GPIO schreibt.
Du olltest A.K. Vorschlag folgen.
Wenn ich mich recht entsinne, wird selbt im Datenblatt davor gewarnt,
an den GPIO-Bits einzeln herumzuspielen.
Richtig benutzt man entweder den Ausgabelatch, wenn der verwendete
PIC den hat, oder ein Schattenregister das man dann nach der
Bitkippelei komplett(!) ins GPIO schreibt.
Wenn ich wüsste, was ein Schattenregister ist,
würde ich das natürlich testen ;-)
Wenn ich wüsste, was ein Schattenregister ist,
würde ich das natürlich testen ;-)
Du setzt in einem (freien) Register des Prozessor die entsprechenden Bits und kopierst dann den Inhalt dieses Registers "in einem Rutsch" in den jeweiligen GPIO.
Da jeder Befehl in PICs 4 Takte braucht und das Lesen am Anfang, das Schreiben jedoch erst am Ende passiert, schreibt dein 1. BSF gerade das Bit, wenn der letzte BSF die Eingänge liest.
Dieser setzt dann das gelesene Muster.
Du musst einfach ein paar NOPs einbauen (oder was anderes sinnvolles tun) und es wird gehen, wenn die Hardware nicht allzu stark an den Pins zieht.
Wenn sie es doch tut und/oder du keinen Bock hast auf solche Sachen zu achten, nutze ein Schattenregister.
Wat is'n dette? hör ich da...
Entweder hat die Hardware eins (also ein Register, das rein und ausschließlich schreibend auf die Hardware wirkt, auch wenn man es selbst lesen kann) oder ein Stück RAM, in dem du so tust als würdest du dich über leuchtende LEDs freuen, und immer wenn du meinst jetzt wäre ein guter Zeitpunkt die ganzen Änderungen mal nachzutragen machst du MOVF x,W und MOVWF GPIO.
Das ist schon deswegen eine schlechte Idee, weil der C-Standard nicht definiert, wie die Bits in einem Bitfield angeordnet sind. Sie sind ausschließlich zum Speichersparen gedacht, aber nicht für Register-Mapping.
Du olltest A.K. Vorschlag folgen.
Wenn ich mich recht entsinne, wird selbt im Datenblatt davor gewarnt,
an den GPIO-Bits einzeln herumzuspielen.
Das hast du nur flüchtig gelesen. Wenn man alle PortPins als Ausgang konfiguriert hat, dann ist das einzelne Setzen völlig OK, aber wenn man Eingänge am Port dabei hat, dann kommt in das eigentlich abgeschaltete Pin-Flipflop eben der Zustand, den das Pin grad hat. Das ist eigentlich völlig ungefährlich, da der Pin ja ein Eingang ist. Aber wenn man glaubt, in dem zwar zugänglichen aber abgeschalteten FF sich irgend etwas merken zu wollen, dann geht das schief.
Das ist schon deswegen eine schlechte Idee, weil der C-Standard nicht
definiert, wie die Bits in einem Bitfield angeordnet sind.
Naja, so ein kleiner PIC hat zum einen nur einen recht kleinen Platz für Code aber zum anderen nette Maschinenbefehle, mit denen man ein einzelnes Bit setzen und testen kann. Sowas kann man jedoch nur in Assembler richtig ausnutzen. Sowas wie C ist dafür nicht eingerichtet. Das ist eben das Problem, wenn man Programmiersprachen erfinden will, die hardwareunabhängig sein sollen. Die können dann naturgemäß nicht auf einzelne Details irgendeiner Plattform eingehen.
Naja, so ein kleiner PIC hat zum einen nur einen recht kleinen Platz für
Code aber zum anderen nette Maschinenbefehle, mit denen man ein
einzelnes Bit setzen und testen kann.
Nein, die hat er auch in Asm-Code nicht wirklich, auf Portbits bezogen. Befehle wie BSF manipulieren kein einzelnes Portbit, sondern lesen den ganzen Port, ändern ein Bit, und schreiben zurück. Und genau das ist das Problem. Siehe Datasheet Abschnitt 5.4. "I/O Programming Considerations".
8051 Pins arbeiten von Haus aus als O.D. mit Pullup, aber während deren Port-Read Befehle den Zustand der Pins lesen, lesen Read-Modify-Write Befehle das Latch, was Bitoperationen absichert. Ersetzt man "Port |= Maske" durch "Port = Port | Maske" (ohne entsprechende Optimierung), hat man bei 8051 das gleiche Problem, was eigentlich inkompatibel zur Definition von C ist.
Da bislang alle verbauten PICs, und das sind eine ganze Menge,
das tun was sie sollen, habe ich wohl doch genau genug gelesen.
Das war auch mehr der Wink mit dem Zaunpfahl an den TO,
sich den Abschnitee genau durchzulesen.
Im uebrigen habe ich ja auch noch auf DS33023 verwiesen.
Man muss auch immer bedenken, dass eine Schaltung/Geraet in
jeder Umgebung funktionieren sollte. Und das dann kapazitive
Lasten wenn geschludert wurde, sonderbare :) Effekte ausloesen
koennen...
zum anderen nette Maschinenbefehle, mit denen man ein
einzelnes Bit setzen und testen kann.
Insbesondere die kleinen PICs erfreuen sich bei mir zumeist
an einem Mix aus XC-8 C und XC-8 Assembler.
Wenn man alle PortPins als Ausgang
konfiguriert hat, dann ist das einzelne Setzen völlig OK
Schliess mal an die Ausgaenge Kondensatoren von 1 uF an.
Nicht das ich das tun wuerde. Aber Kunden machen sowas...
Dann wirst du sehen wie wunderbar das schief geht :).
Dabei ist mir aufgefallen, dass das Setzen von einzelnen Bits in einem
bitfield nicht so funktioniert, wie ich mir das dachte.
Wenn es nur so ein kapazitiver Effekt ist, der den Fehler auslöst, dann hast du hast du gute Chancen, dass dein Programm "funktioniert", wenn du in Einzelschritten von Hand durch die drei Zeilen durchgehst...
Danke erst mal für die Erläuterungen der technischen Hintergründe.
Was mich ein wenig stutzig macht, ich teste das Ganze ja vorerst in einer Simulation, da kann ja im Grunde kein Input-Pin in die Quere kommen, denn das kann ich ja selbst beeinflussen (und triggere eben gerade keinen Input).
Eine kurze Frage zur Initialisierung des PIC10F202 und die Implementierung in meinem Progrämmchen..
1
2
TRIS=0b110111;// configure GP3 (only) as an input
3
GPIO&=0b001000;// set each out low
4
5
// bit 6 GPPU: Enable Weak Pull-ups bit (GP0, GP1, GP3)
6
// 1 = Disabled
7
//0 = Enabled
8
OPTION=0b10111111;
Stimmt das so ?
Für GP2 gibt es keinen konfigurierbaren Pullup ?
Wenn ich lieber einen Pulldown hätte, müsste ich einen Masse-Widerstand am entsprechenden Pin anbringen, welchen Wert würde man da nehmen, wenn man
bereits intern einen Pullup konfiguriert hat (man kann das ja leider nur für alle 3 Pins konfigurieren) ?
Die beste Lösung wäre wohl dann, die internen Pullups nicht zu konfigurieren
und die Pullup/Pulldown mit je einem externe Widerstand (? Ohm) zu realisieren ?
Wenn man Pins nicht als Eingang benutzen will, definiert man
sie als Ausgang. Was man an das MCLR Pin anschliesst,
sollte im Datenblatt mit Schaltung und Erklaerung dazu stehen.
Ansonsten kann man deine Fragen nur mit der Universalantwort:
"Es haengt davon ab." beantworten.
Datenblaetter sind dazu da, solche Einfachstfragen allumfassend
zu beantworten. Wenn man sie liest. Und versteht.
Schliess mal an die Ausgaenge Kondensatoren von 1 uF an.
Scherzbold! Ich habe oft genug dagegen gewettert, daß z.B. FET's direkt mittels Portpins geschaltet werden, was man hier in diesem Forum fast jeden Tag findet. Zumal es genug Gatetreiber gibt, die so etwas zuverlässig erledigen.
Nein, die hat er auch in Asm-Code nicht wirklich, auf Portbits bezogen.
Er hat diese Maschinenbefehle. Das Gegenteil kann man bei Chips mit Load-Modify-Store Architekturen sehen, da braucht es 3 Maschinenbefehle dafür. Und da im betreffenden Befehl bei den PIC sowohl Adresse als auch Bitnummer enthalten ist, kann man bei sinnvoller Implementierung einer Bit-Vereinbarung auch sicherstellen, daß man nicht versehentlich eine Bitnummer zusammen mit einer falschen Adresse anwendet. In Assembler geht das, in maschinenunabhängigen Sprachen eben leider nicht. Allerdings hat selbst Microchip das noch nicht richtig gemerkt. Es ist doch einfacher und leserlicher, wenn man schreibt:
CE_LCD: BIT PortB, 0
...
BSF CE_LCD
anstelle
BSF PortB, CE_LCD
Und wie ein Maschinenbefehl physisch funktioniert, ist ein anderes Thema als daß es Maschinenbefehle zum Hantieren mit einzelnen Bits gibt.
ich habe es eben geschaft mein erstes Programm für den PIC10F202
zu debuggen (ich bitte um Applaus :-)
Bittesehr: Du bist ein Held!
Dabei ist mir aufgefallen, dass das Setzen von einzelnen Bits in einem
bitfield nicht so funktioniert, wie ich mir das dachte.
Ich kannte zwar mal jemanden, der da meinte "ich sehe keinen Grund, so einen PICNICHT in C zu programmieren" - aber ich teile solche Ansicht nicht. Der von dir genannte PIC hat (wimre) noch nicht einmal 1 K an Programmspeicher, also kann dessen Flash wohl nur maximal 512 Maschinenbefehle speichern. Und der Umfang an Maschinenbefehlen ist gering, es sind nur 33 verschiedene Befehle (oder waren es nur 32 ?). Bei so kleinen Plattformen sehe ich als Programmiersprache nur Assembler, denn alles andere ist etwa so wie mit dem SUV mal eben zum Bäcker um die Ecke zum Brötchen holen zu fahren. Der braucht zum Anlassen und aus der Parklücke zu rangieren doppelt so viel Sprit wie für die eigentliche Strecke.
Ich hoffe nur, daß du nicht auch auf die Idee kommst, auf diesem PIC sowas wie printf benutzen zu wollen. Versuche dich lieber mal in Assembler, das erscheint mir leichter, als auf so einer Nußschale deine gewünschte Funktionalität in C formulieren zu wollen.
Versuche dich lieber mal in Assembler, das erscheint mir leichter,
als auf so einer Nußschale deine gewünschte Funktionalität in C
formulieren zu wollen.
Als ich das las kam mir spontan der Gedanke, dass du wahrscheinlich total übertreibst, aber ...
... das ist ja wirklich eine Nußschale. Aber Hallo! Ich wusste gar nicht, dass es so kleine Mikrocontroller gibt.
... das ist ja wirklich eine Nußschale. Aber Hallo! Ich wusste gar
nicht, dass es so kleine Mikrocontroller gibt.
Diese PIC10 sind im Grunde lebende Fossilien. Sie stammen wenig verändert vom allerersten PIC ab, dem PIC1650 von 1976. Aber es gibt eben Aufgaben, wo das ausreicht.
Der Befehlssatz war schon damals auf diese 512 Worte à 12 Bits optimiert, von denen sogar nur 256 Worte universell ansprechbar sind. Mehr als diese, und mehr als die 32 Bytes Datenadressraum für RAM und I/O-Registern, sind nicht ohne Bank-Switching machbar. Der '200 hat sogar nur 256 Worte und 16 statt 24 Bytes RAM freigegeben.
Warum man sich allerdings ausgerechnet sowas als Lernplattform aussucht... Und da muss ich W.S. ausnahmsweise Recht geben: ASM bevorzugt.
Es ist zwar nur eine Bequemlichkeitsfrage, aber was mich an
6 Pinnern stoert, ist das man den ICSP-Adapter entweder
abziehen oder "eindesignen" muss.
Wieso man sich als Anfaenger diese Zwerge antut? Keine Ahnung.
Selbst die aeltesten und sparsam ausgestatteten 12F675 und
12F683 sind da um Groessenordnungen komfortabler und vermutlich
wegen groesserer Stueckzahlen obendrein billiger.
... das ist ja wirklich eine Nußschale. Aber Hallo! Ich wusste gar
nicht, dass es so kleine Mikrocontroller gibt.
Der Punkt ist aber eigentlich ein anderer, nämlich:
Es wird bei der ganz kleinen Hardware nur besonders deutlich, dass Assembler rules, weil es dort über geht oder geht nicht für eine konkrete Anwendung entscheiden kann.
Aber: auch bei den größeren Maschinen ist ein liebevoll handoptimiertes Assemblerprogramm immer schneller als das, was Compiler hervorbringen können.
Das Problem ist eigentlich nur, dass man erheblichen Zeitaufwand in so ein Assemlerprogramm versenken muss. Zeit ist Geld. Und da wird es dann schnell sehr attraktiv, Asm Asm sein zu lassen und einfach auf fettere Hardware umzuschwenken, die halt schnell genug ist, um auch die suboptimalen Compilate hinreichend schnell ausführen zu können...
Die (noch nicht ganz überstandene) Lieferkrise bei der Hardware hat hier allerdings einiges in Bewegung gebracht. Extreme Preissteigerungen bei der Hardware und teilweise Nicht-Verfügbarkeit haben es wieder finanziell attraktiver gemacht, bei der Software nicht mehr nach der "was kost' die Welt"-Methode vorzugehen, sondern mal wieder ernsthaft über die Effizienz des Codes nachzudenken. Muss ja nicht immer zu Asm führen...
Als ich das erste Mal so einen Winzling in C programmiert habe,
war ich ehrlich gesagt ziemlich erstaunt, wir gut das Ergebnis
trotz fehlender Optimierung usw. beim xc8 war.
Da das Programm für einen 10F wirklich nicht sehr umfangreich sein kann, kann man meiner Meinung durchaus mal testen es in C zu schreiben, wenn man in der Lage ist den Maschinencode der dabei heraus kommt zu bewerten. Ist meiner Meinung nach auf jeden Fall erheblich lesbarer als Assembler.
Zugegebenermaßen war es bei mir ein 10F3xx der schon zu den Midrangetypen zählt und ein LATCH Register hat, das man auch lesen kann...
Die (noch nicht ganz überstandene) Lieferkrise bei der Hardware hat hier
allerdings einiges in Bewegung gebracht.
Aber eher nicht mit mehr Assembler, weil das nicht portabel ist. Eine Anwendung mit brauchbarer Schichten-Architektur kann man portieren, wenngleich man die Lowlevel-Schicht neu machen muß - aber erstens nur die, und zweitens geht auch das in C schneller als in Assembler.
Drittens hat man spätestens danach die Beschaffungsoption mit "second source" und hat damit eine andere Verhandlungsbasis, falls man groß ist, und die Möglichkeit, jederzeit auf Marktpreise zu reagieren, falls man klein ist.
Extreme Preissteigerungen bei der Hardware
Jo, und wenn man eine Anwendung hat, die auf diese CPU festgenagelt ist, weil in Assembler geschrieben, wird man so ziemlich jeden Preis zahlen. Preis-unelastische Nachfrage ist ja in einer Marktwirtschaft der Grund für extreme Preissteigerungen bei Knappheit.
Immer dieses Rumgereite auf der Portabilität von C-Code.
Die Geräte bestehen zu etwa einem Prozent aus CPU, auch wenn ein großer Teil der Funktionalität mittlerweile auf der Software basiert, so ist doch wesentlich mehr an Chips beteiligt die ebenfalls knapp sind und kaum ersetzbar.
Die zahlreichen Geräte aus allen möglichen Teilen der Industrie die ich kenne sind jedenfalls deutlichst teurer geworden, weil ein Softwareport auf einen anderen Prozessor genau gar nichts bringt, wenn man die anderen ICs nicht mehr bekommt.
Also muss man eh neu designen, und da lässt man dann die Software laufen, denn 10€ pro CPU mehr oder 10€ pro Gerät für den Port mehr ist wurscht.
Ich kenne jedenfalls kein einziges Produkt wo die ach so gelobte Portabilität genutzt wurde.
Aber eher nicht mit mehr Assembler, weil das nicht portabel ist. Eine
Anwendung mit brauchbarer Schichten-Architektur kann man portieren,
Wobei so ein PIC10 nicht wirklich zu komplexer Software-Architektur einläd. Da sitzt ein C-Programm genauso unabstrakt auf der Hardware wie ein Assembler-Programm und das grösste Problem der Portierung liegt bei Asm in der armen Sau, die sich nach Abgang des einzigen PIC-Experten mit einem Befehlssatz rumärgern darf, in dem alles anders heisst, als sonst üblich.
Schätze, dass so mancher PIC10 nicht viel mehr ist, als ein digitaler stromsparender Ersatz eines NE555. Ein paar Zeilen Initialisierung, vielleicht völlig ohne Hauptprogramm.
Und die ganze Software komplett neu schreibt, oder wie? Naja, wenn's nicht mehr als ein LED-Blinky ist, mag das noch angehen.
Ansinsten habe ich in realen Projekten schon Hardware-Abstraktion braucbar implementiert gesehen von dem Level, wo mit Evalboard und Steckerleiste die SW parallel zum eigentlichen HW-Design gemacht wurde (mit sehr unterschiedlicher Pinbelegung) bis dahin, daß die SW im Mockup am PC laufen kann - einfach, indem in der Build-Konfig das unterste Layer getauscht wird.
Letzteres bedeutet hatürlich eine tatsächliche Hardware Abstraction Layer und nicht bloß die Umbenennung von Registern in Structs, wie das bei STs Möchtegern-HAL der Fall ist.
Schätze, dass so mancher PIC10 nicht viel mehr ist, als ein digitaler
stromsparender Ersatz eines NE555. Ein paar Zeilen Initialisierung,
vielleicht völlig ohne Hauptprogramm.
Lach dich tot, genau dazu isser gemacht. Kleinste einfachste Aufgaben die sich gerade eben nicht mehr mit einem NE555 erledigen lassen und oder mehr Bauteile bräuchten kann man hier mit wenigen Zeilen, Teilen und Moneten erledigen.
Und die ganze Software komplett neu schreibt, oder wie?
Bei den Projekten die ich zu bearbeiten die Ehre hatte in den letzten 25 Jahren: ja. "Ist eh alt, machen wir komplett neu, muss eh neu zugelassen werden".
Da wurden höchstens die grundsätzlichen Ideen des alten Codes übernommen.
Ansinsten habe ich in realen Projekten schon Hardware-Abstraktion
braucbar implementiert gesehen
Das ist fuer kleine 8 bit PICs voellig ueberzogen.
Es reicht da voellig, Teilfunktionen zu kapseln.
Aber eher nicht mit mehr Assembler
Genau du bist wahrscheinlich nicht in der Zielgruppe.
Wenn man die besonderen Eigenschaften der Architektur nutzen will,
fuehrt an Assembler zumindest in Teilfunktionen kein Weg vorbei.
Das kann man entweder mit Inlineassembler oder wenn es mehr wird,
mit separatten Assemblerquellen tun.
wenn man eine Anwendung hat, die auf diese CPU festgenagelt ist
Wenn der eindesignte Wunsch-PIC nicht verfuegbar sein sollte,
wird man mit einiger Sicherheit einen alternativen Typ finden,
der die benoetigte Peripherie enthaelt.
Aber z.B. einen groesseren Flash hat.
Die Standardperipherie ist ueber alle Typen sehr uniform,
was einen Wechsel erleichtert.
es in C zu schreiben
Ja.
Die strukturierenden Elemente koennen natuerlich in C geschrieben sein,
was die Uebersicht und die Lesbarkeit verbessert.
Der XC8-Compiler hat aber architekturbedingt seine Eigenarten
die man kennen sollte.
Ein
liebevoll handoptimiertes Assemblerprogramm
tut man sich auch nur an, um bestimmte Timingvorgaben bei der
Erzeugung von Signalablaeufen in Software zu erfuellen.
Eine kurze Frage zur Initialisierung des PIC10F202 und die
Implementierung in meinem Progrämmchen..
1
2 TRIS = 0b110111; // configure GP3 (only) as an input
3 GPIO &= 0b001000; // set each out low
45 // bit 6 GPPU: Enable Weak Pull-ups bit (GP0, GP1, GP3)
6 // 1 = Disabled
7 //0 = Enabled
8 OPTION = 0b10111111;
Stimmt das so ?
Eine „1“ im TRIS-Register definiert den entsprechenden Pin als Eingang, und bei „0“ ist der Pin als Ausgang konfiguriert.
Es wird bei der ganz kleinen Hardware nur besonders deutlich,
dass Assembler rules
War klar dass du das so aufgreifst. Man könnte aber auch sagen, dass Assembler eben nicht mehr "rules" weil diese extrem schwachen Mikrocontroller kaum noch relevant sind.
Aber: auch bei den größeren Maschinen ist ein liebevoll handoptimiertes
Assemblerprogramm immer schneller als das, was Compiler hervorbringen
können.
Premature optimization führt dort wo ich arbeite zur Kündigung. Solange der Computer schnell genug funktioniert, verschwendet man damit unnötig Zeit und macht das Programm unnötig kompliziert.
Das Problem ist eigentlich nur, dass man erheblichen Zeitaufwand
in so ein Assemlerprogramm versenken muss. Zeit ist Geld.
So ist es. Bei Hobbyprojekten kann man sich den Aufwand eher leisten, wenn man will.
weil diese extrem schwachen
Mikrocontroller kaum noch relevant sind.
Atmel brachte recht spät mit den ATtiny4..10 eine direkte Konkurrenz zu den PIC10. Ganz so irrelevant schien diese Klasse für Atmel folglich nicht zu sein.
ich habe jetzt alle Dokumentationen und Datenbätter zum PIC10F202 gelesen und hoffentlich verstanden.
Wenn ich es richtig verstanden habe ist ein Schatten-Register nichts weiter als eine (temp.) Variable, in die ich einen Wert aus einem Reister (hier GPIO) kopiere, dort "bearbeite" und dann in das Register zurückkopiere !?
(Schatten-Register ist also nur ein Synonym für ene temp. Variable).
Ich habe jetzt ein kleines Testprogramm geschrieben, das nichts weiter machen soll, als in GPIO0-GPIO2 eine 1 bzw eine 0 zu schreiben (bzw, vom PIN aus gesehen, High- bzw Low-Level setzen).
Wie der Teufel so will, funktioniert das Ganze bis auf eine Winzige Kleinigkeit, das Schreiben einer 1 in GPIO2 funktioniert einfach nicht.
Ob es mit dem Wert 0 funktioniert weiß ich nicht, da GPIO2 ja immer 0 ist (egal, was ich mache)
Ich zeige hier mal meine C-Source, die sicher nicht optimal ist (weil ich inzwischen auch alles ausprobiert habe um GPIO2 willig zu machen, hat aber bisher nicht funktioniert). Rahmenbedingung des Programms ist dass GPIO0-GPIO2 outputs sind GPIO3 ist (natürlich) ein Input.
#include<stdbool.h> /* For true/false definition */
10
11
12
// no ext reset, no code protect, no watchdog
13
#pragma config MCLRE = OFF, CP = OFF, WDTE = OFF
14
#define _XTAL_FREQ 4000000 // oscillator frequency for _delay()
15
16
#define GPIO0BIT 1
17
#define GPIO1BIT 2
18
#define GPIO2BIT 4
19
20
uint8_tsGPIO;
21
22
voidsetGPIOOUT(uint8_tbitval)
23
{
24
sGPIO|=bitval;// toggle shadow bit corresponding to GP1
25
GPIO=sGPIO;// write to GPI
26
NOP();
27
NOP();
28
NOP();
29
}
30
31
voidunsetGPIOOUT(uint8_tbitval)
32
{
33
sGPIO&=~bitval;// toggle shadow bit corresponding to GP1
34
GPIO=sGPIO;// write to GPI
35
NOP();
36
NOP();
37
NOP();
38
}
39
40
voidmain(void)
41
{
42
sGPIO=0;// shadow copy of GPIO
43
TRIS=0b11111000;
44
45
while(1)
46
{
47
setGPIOOUT(GPIO2BIT);
48
setGPIOOUT(GPIO0BIT);
49
setGPIOOUT(GPIO1BIT);
50
51
unsetGPIOOUT(GPIO0BIT);
52
unsetGPIOOUT(GPIO1BIT);
53
unsetGPIOOUT(GPIO2BIT);
54
}
55
56
}
Ich verwende MPLAB X IDE v6.05 mit xcu (2.40) unter Windows10 UND Ubuntu 22.04 LTS (was bzgl. des Problems keinen Unterschied macht, aber ich probiere gerne alles aus, wenn es zielführend ist).
Bin mal gespannt, ob ich da ein Brett vorm Kopf habe oder was das Problem auch immer verursacht.
Atmel brachte recht spät mit den ATtiny4..10 eine direkte Konkurrenz zu
den PIC10. Ganz so irrelevant schien diese Klasse für Atmel folglich
nicht zu sein.
Ja, wohl auch deshalb, weil die AVRs für C optimiert sind.
Die ATtiny4..10 haben einen echten Stack im SRAM, Interrupts, Timer, ADC. Nur der EEPROM fehlt, kann aber im Flash emuliert werden.
in die ich einen Wert aus einem Reister (hier GPIO) kopiere, dort
"bearbeite" und dann in das Register zurückkopiere !?
Fast richtig. In deinem Fall ist es aber ein Register, wo du das gewünschte Bitmuster für die Ausgänge erzeugst und das dann von diesem "Schattenregister" ohne Read-Modify-Write direkt geradeaus auf den Ausgang schreibst.
Worauf basieren diese "Angst-NOPs"? Genau die brauchst du nicht mehr, wenn du nur schreibst und keine Read-Modify-Write-Zugriffe machst.
Oder andersrum: dich interessiert in deinem Fall überhaupt nicht, welchen Pegel der Ausgangspin gerade hat, deshalb musst du ihn auch niemals lesen.
das Schreiben einer 1 in GPIO2 funktioniert einfach nicht.
Nur im Simulator? Oder auch in echt?
unset
Wieder ein überraschender neuer Name für "reset" oder "clear".
Wie schon gesagt: ich würde das Rausschreiben pro Mainloop-Durchlauf nur 1x machen. Eben nicht gleich jedesmal, wenn sich irgendein Bit geändert hat. Aber keine Sorge: auf diesen Programmierstil mit der schnellstmöglich durchlaufenden Mainloop und den Zustandsautomaten wirst du im späteren Verlauf der Programmierkarriere auch noch kommen ;-)
Das Problem ist eigentlich nur, dass man erheblichen Zeitaufwand in so
ein Assemlerprogramm versenken muss. Zeit ist Geld. Und da wird es dann
schnell sehr attraktiv, Asm Asm sein zu lassen und einfach auf fettere
Hardware umzuschwenken
Die Hardware muß nichtmal riesig fett sein für C. Schon ein ATtiny10 läßt die Vorteile von C benutzen und damit schneller und deutlich weniger fehleranfällig programmieren.
Das Problem mit den RMW-Zugriffen auf die Portpins haben die AVRs auch elegant gelöst. Ich würde das Fehlverhalten der PIC als Bug einstufen. Es ist nämlich vom CPU-Takt abhängig, ob der Bug auftritt oder nicht.
Das Problem mit den RMW-Zugriffen auf die Portpins haben die AVRs auch
elegant gelöst. Ich würde das Fehlverhalten der PIC als Bug einstufen.
Eine Art Altererscheinung. Als man die PIC10 Architektur in den 1970ern konzipierte, war dieser Denkfehler bei I/O-Ports weit verbreitet. Die AVRs kamen zu einem Zeitpunkt raus, zu dem dieses Problem bereits bekannt war.
PICs mit neuerer Architektur haben ein LATx Register für den Ausgangszustand, vgl AVR. Aber den PIC10 hat Microchip das nicht angedeihen lassen. Vielleicht auch, weil der Adressraum für RAM und I/O-Ports mit 32 Bytes ziemlich knapp bemessen ist.
in die ich einen Wert aus einem Register (hier GPIO) kopiere, dort
"bearbeite" und dann in das Register zurückkopiere !?
Fast richtig. In deinem Fall ist es aber ein Register, wo du das
gewünschte Bitmuster für die Ausgänge erzeugst und das dann von diesem
"Schattenregister" ohne Read-Modify-Write direkt geradeaus auf den
Ausgang schreibst.
Ohne nerven zu wollen (ich will es einfach nur verstehen),
ich definiere mit
1
uint8_tsGPIO;
im Sinne von "C" eine Variable. C läßt mich im unklaren, wo sich diese Variable befindet. Warum ist diese Variable denn jetzt ein (Schatten)Register ?
Worauf basieren diese "Angst-NOPs"? Genau die brauchst du nicht mehr,
wenn du nur schreibst und keine Read-Modify-Write-Zugriffe machst.
Angst NOPs , da hast du recht und sie sind sicher unnötig, aber
was macht man nicht alles um zum Ziel zu kommen :-)
Oder andersrum: dich interessiert in deinem Fall überhaupt nicht,
welchen Pegel der Ausgangspin gerade hat, deshalb musst du ihn auch
niemals lesen.
Ja, stimmt, aber ich möchte in der Simulation ja schon wissen, ob das was ich beabsichtige auch passiert.
das Schreiben einer 1 in GPIO2 funktioniert einfach nicht.
Nur im Simulator? Oder auch in echt?
Nur im Simulator oder besser Debugging !
Es kann ja auch ein Fehler in der Entwicklungsumgebung sein.
Ich möchte gerne wissen, ob jemand einen Fehler im Code sieht
oder ob jemand, der/die den Code in seiner IDE ausprobiert genau das gleiche sieht wie ich.
unset
Wieder ein überraschender neuer Name für "reset" oder "clear".
set/unset, für mich ist das eine seit langem gängige Bezeichnung für zb boolsche oder Bit- oder Zustands-"Dinge" :-)
Wie schon gesagt: ich würde das Rausschreiben pro Mainloop-Durchlauf nur
1x machen. Eben nicht gleich jedesmal, wenn sich irgendein Bit geändert
hat.
In echt wäre nach jedem "set" erst mal ein delay, das jede Menge Rechnenzeit verbraucht (im ms-Bereich)
Aber keine Sorge: auf diesen Programmierstil mit der
schnellstmöglich durchlaufenden Mainloop und den Zustandsautomaten wirst
du im späteren Verlauf der Programmierkarriere auch noch kommen ;-)
Keine Angst, ich programmiere seit Jahrzehnten, aber bei µC gilt es für mich erst mal die "Hello World"-Ebene erfolgreich zu verlassen.
Im Grunde ist das, was passiert ja "nur" Zustände zu lesen oder zu schreiben und das MUSS rocksolid sein, oder ?
Rechenzeit interessiert mich nicht, ich möchte gute Lösungen für einfach Probleme finden.
Mir ist schon klar, dass ich auf dem PIC10F202 keine Tabellenkalkulation hinbekomme :-)
Das Problem mit den RMW-Zugriffen auf die Portpins haben die AVRs auch
elegant gelöst. Ich würde das Fehlverhalten der PIC als Bug einstufen.
Eine Art Altererscheinung. Als man die PIC10 Architektur in den 1970ern
konzipierte, war dieser Denkfehler bei I/O-Ports weit verbreitet. Die
AVRs kamen zu einem Zeitpunkt raus, zu dem dieses Problem bereits
bekannt war.
PICs mit neuerer Architektur haben ein LATx Register für den
Ausgangszustand, vgl AVR. Aber den PIC10 hat Microchip das nicht
angedeihen lassen. Vielleicht auch, weil der Adressraum für RAM und
I/O-Ports mit 32 Bytes ziemlich knapp bemessen ist.
Das alles beantworte leider meine Frage nicht, selbst wenn ich den Aufruf
1
setGPIOOUT(GPIO2BIT);
nur jede Minute mache geht es nicht (in der Simulation mit Step over zb
passiert ja alles höchstens in 10Sec-Schritten).
Dass die PIC alt sind und es bessere Hardware gibt hat ja nichts damit zu tun, dass eine "einfache" Aufgabe wie das Setzen von GPIO2 nicht funktioniert (wie geschrieben in Der Simulation/Debugging). Da es den PIC1F202 schon seit Jahrzehnten gibt, wird auch das Beschreiben von GPIO2 seit Jahrzehnten funktionieren , oder ?
C läßt mich im unklaren, wo sich diese Variable befindet.
Sie ist irgendwo im Speicher.
Warum ist diese Variable denn jetzt ein (Schatten)Register ?
Weil es in deinem Programmkonzept und Willen liegt, diese Variable als "Schatten" des GPIO-Registers zu verwenden. Nur deshalb ist das ein "Schattenregister".
Ich möchte gerne wissen, ob jemand einen Fehler im Code sieht
Dein C-Code hat keinen Fehler. Kannst du deine Änderung an dem Schattenregister erkennen? Gibt es im Assemblerfile einen Startup-Code, der vor deiner main() ausgeführt wird? Falls ja: was passiert dort?
Dass die PIC alt sind und es bessere Hardware gibt hat ja nichts damit
zu tun, dass eine "einfache" Aufgabe wie das Setzen von GPIO2 nicht
funktioniert (wie geschrieben in Der Simulation/Debugging).
Dann probier das doch einfach mal im echten Leben mit einem richtigen µC.
BTW und nur weil mir noch keiner eine Antwort gegeben hat:
wo lernt man denn das Plenken?
C läßt mich im unklaren, wo sich diese Variable befindet.
Sie ist irgendwo im Speicher.
Warum ist diese Variable denn jetzt ein (Schatten)Register ?
Weil es in deinem Programmkonzept und Willen liegt, diese Variable als
"Schatten" des GPIO-Registers zu verwenden. Nur deshalb ist das ein
"Schattenregister".
Also ist es eine Variable, die als Wert die Kopie des Wertes eines Registers bekommt, "Schattenregister" ist wohl so etwas wie µC-Gebabbel.
Ich möchte gerne wissen, ob jemand einen Fehler im Code sieht
Dein C-Code hat keinen Fehler. Kannst du deine Änderung an dem
Schattenregister erkennen? Gibt es im Assemblerfile einen Startup-Code,
der vor deiner main() ausgeführt wird? Falls ja: was passiert dort?
Dass die PIC alt sind und es bessere Hardware gibt hat ja nichts damit
zu tun, dass eine "einfache" Aufgabe wie das Setzen von GPIO2 nicht
funktioniert (wie geschrieben in Der Simulation/Debugging).
Dann probier das doch einfach mal im echten Leben mit einem richtigen
µC.
Schlaumeier, im echten Leben komme ich noch ohne µC aus und das wird auch so bleiben,
du bist wohl eine Art Borg, wenn ein µC zu deinem echten Leben gehört :-)
BTW und nur weil mir noch keiner eine Antwort gegeben hat:
wo lernt man denn das Plenken?
Keine Ahnung, wen interessiert das und worauf beziehst du dich ?
Also ist es eine Variable, die als Wert die Kopie des Wertes eines
Registers bekommt, "Schattenregister" ist wohl so etwas wie µC-Gebabbel.
Ja, tatsächlich ist das ein üblicher Begriff in der Hardware. Und wenn man mit µC und konsequenterweise mit hardwarenaher Programmierung herummacht, dann sollte man dieses "Gebabbel" als "Sprache" beherrschen. Immerhin findet Google dazu 380000000 Treffer: https://www.google.com/search?q=shadow+register
Wenn ich lieber einen Pulldown hätte, müsste ich einen Masse-Widerstand
am entsprechenden Pin anbringen, welchen Wert würde man da nehmen, wenn
man bereits intern einen Pullup konfiguriert hat (man kann das ja leider
nur für alle 3 Pins konfigurieren) ?
Der interne Pullup hat irgendwas im Bereich ab 15kOhm aufwärts. Und die Schaltschwelle für LOW liegt bei 0,2*Vdd. Ergo muss der Pulldown merklich kleiner sein als ein viertel des Pullups. Du müsstest bei aktiviertem Pullup also für sicheres Erkennen des LOW-Pegels einen Pulldown im Bereich unter 3kOhm nehmen.
Aber der Witz liegt eigentlich in den 6 Worten am Anfang dieses Satzes:
Wenn ich lieber einen Pulldown hätte
Im Grunde ist es völlig egal, was du lieber hättest. Sondern du solltest deine Schaltung so auslegen, wie es der µC gerne hätte.
du bist wohl eine Art Borg, wenn ein µC zu deinem echten Leben gehört
Nein, ich habe Strom und Internet und verwende täglich viele µC, um mein echtes Leben angenehm zu machen. Nur wer irgendwo fernab als Selbstversorger in einer Einsiedelei ohne Strom und Internet lebt, könnte von sich behaupten, dass kein µC in seinem echten Leben auftaucht.
Auf die fehlerhaften Leerzeichen vor manchen Satzzeichen:
https://de.wikipedia.org/wiki/Plenk
Und meine Frage ist: warum machst du die? Wo hast du das gelernt?
Ich frage das nur, weil wirklich viele das machen und mir wie gesagt noch keiner eine Antwort gegeben hat.
Ein Grund kann sein: ich wohne in Frankreich! Das gilt als Argument, dort lernt man das so. Allerdings als nichttrennbares Leerzeichen, das fest mit dem vorhergehenden Wort verbunden ist und deshalb niemals eine eigene Zeile bekommt. Es wird immer zusammen mit dem vorhergehenden Wort umgebrochen:
https://de.babbel.com/de/magazine/franzoesische-satzzeichen
Und meine Frage ist: warum machst du die? Wo hast du das gelernt?
Ich frage das nur, weil wirklich viele das machen und mir wie gesagt
noch keiner eine Antwort gegeben hat.
Wir (DE) haben doch keine Computer in den Schulen und für Handschrift ist das kein Theme. Also wird da, neu an der Tastatur, nach Gefühl eine eigene Regel aufgestellt. ... So meine These.
Sollte als ein Phänomen der pre millenniums Kids sein. ... Hoffe ich.
Scheinbar reicht deine Aufmerksamkeitsspanne nicht dazu aus,
etwas vollstaendig zu erledigen. Dafuer muss man sich nicht
auch noch auf die Schulter klopfen.
Das hier wird fuer einen nichtsimulierten PIC nicht reichen:
In mein allererstes (PIC-)Prograemmelchen habe ich mir die
Belegung des OPTION-Words als Kommentar hineinkopiert.
Da konnte man dann schon im Code sehen, was Sache ist.
Das Ergebnes war dann auch straightforward auf Anhieb richtig.
Wie willst du eigentlich komplexere Probleme angehen?
Mit unbekuemmerten Herumprobieren?
Also ist es eine Variable, die als Wert die Kopie des Wertes eines
Registers bekommt, "Schattenregister" ist wohl so etwas wie µC-Gebabbel.
Ja, tatsächlich ist das ein üblicher Begriff in der Hardware. Und wenn
man mit µC und konsequenterweise mit hardwarenaher Programmierung
herummacht, dann sollte man dieses "Gebabbel" als "Sprache" beherrschen.
Immerhin findet Google dazu 380000000 Treffer:
https://www.google.com/search?q=shadow+register
Das kannst du so sehen, ich finde es ist ein unnötiger Begriff für eine einfache Sache: temporäre Variable das passt - generalistisch - für jede Art Programmierung. Mir hat "Schattenregister" den Eindruck vermittelt, dass das eine andere Art von Registern im µC ist und das genau ist es nicht.
Wenn ich lieber einen Pulldown hätte, müsste ich einen Masse-Widerstand
am entsprechenden Pin anbringen, welchen Wert würde man da nehmen, wenn
man bereits intern einen Pullup konfiguriert hat (man kann das ja leider
nur für alle 3 Pins konfigurieren) ?
Der interne Pullup hat irgendwas im Bereich ab 15kOhm aufwärts. Und die
Schaltschwelle für LOW liegt bei 0,2*Vdd. Ergo muss der Pulldown
merklich kleiner sein als ein viertel des Pullups. Du müsstest bei
aktiviertem Pullup also für sicheres Erkennen des LOW-Pegels einen
Pulldown im Bereich unter 3kOhm nehmen.
Aber der Witz liegt eigentlich in den 6 Worten am Anfang dieses Satzes:
Wenn ich lieber einen Pulldown hätte
Was du alles witzig findest.
Jetzt geht es in diesem Thread also um Begrifflichkeiten, Fakt ist, dass ich die Lösung des Problems selbst gefunden habe und die meisten hier lieber Vorschläge gemacht haben, die mich nicht weiter gebracht haben.
Im Grunde ist es völlig egal, was du lieber hättest. Sondern du
solltest deine Schaltung so auslegen, wie es der µC gerne hätte.
Sprachakrobatik, scheint wohl dein Fachgebiet zu sein.
du bist wohl eine Art Borg, wenn ein µC zu deinem echten Leben gehört
Nein, ich habe Strom und Internet und verwende täglich viele µC, um mein
echtes Leben angenehm zu machen. Nur wer irgendwo fernab als
Selbstversorger in einer Einsiedelei ohne Strom und Internet lebt,
könnte von sich behaupten, dass kein µC in seinem echten Leben
auftaucht.
Auf die fehlerhaften Leerzeichen vor manchen Satzzeichen:
https://de.wikipedia.org/wiki/Plenk
Und meine Frage ist: warum machst du die? Wo hast du das gelernt?
Ich mache das, weil ich es als richtig empfinde.
Ich frage das nur, weil wirklich viele das machen und mir wie gesagt
noch keiner eine Antwort gegeben hat.
Ein Grund kann sein: ich wohne in Frankreich! Das gilt als Argument,
dort lernt man das so. Allerdings als nichttrennbares Leerzeichen, das
fest mit dem vorhergehenden Wort verbunden ist und deshalb niemals eine
eigene Zeile bekommt. Es wird immer zusammen mit dem vorhergehenden Wort
umgebrochen:
https://de.babbel.com/de/magazine/franzoesische-satzzeichen
Ist mir egal, ich rede/schreibe deutsch und denke dass man versteht, was ich will. Wenn das deine einzige Sorge ist, geht es dir wohl sehr gut.
So lieber Lothar, zum Schluss eine Bitte. Wenn du dich in Threads, die ich angefangen habe oder anfangen werde zukünftig mehr um das Thema als die sprachliche Form kümmerst wäre mir das recht, vielen Dank im voraus.
Scheinbar reicht deine Aufmerksamkeitsspanne nicht dazu aus,
etwas vollstaendig zu erledigen. Dafuer muss man sich nicht
auch noch auf die Schulter klopfen.
Du kannst mich mal !
Das hier wird fuer einen nichtsimulierten PIC nicht reichen:
In mein allererstes (PIC-)Prograemmelchen habe ich mir die
Belegung des OPTION-Words als Kommentar hineinkopiert.
Da konnte man dann schon im Code sehen, was Sache ist.
Das Ergebnes war dann auch straightforward auf Anhieb richtig.
Deine Aufmerksamkeitsspanne erlaubt es dir aber dir jetzt selbst auf die Schultern zu klopfen du Held du großer !
Wie willst du eigentlich komplexere Probleme angehen?
Indem ich kleine wie dich einfach ignoriere :-)
Mit unbekuemmerten Herumprobieren?
Um es offen zu sagen, deine Art zu kommunizieren gefällt mir nicht,
ich bitte dich Threads, die ich zukünftig beginnen werde, zu ignorieren
Unterhalte dich mit Lothar über Satzzeichen, Umlaute und Rechtschreibung.
Dann ist allen geholfen.
Danke im Voraus
und die meisten hier lieber Vorschläge gemacht haben, die mich nicht
weiter gebracht haben.
Aber wenigstens hast du was gelernt wie z.B. "Schattenregister" und "Plenk" und dass man im Debugger am fett geschriebenen Wort bei "Owner or Mapping" ganz leicht eine unerwünschte Konfiguration des Pins erkennt.
temporäre Variable
Warum verwendest du selbst dann mit sGPIO eine globale Variable? Und nicht eine temporäre Variable, die nur in einer Unterroutine bekannt ist und dort bei jedem Funktionsauf neu initialisiert wird.
Jetzt geht es in diesem Thread also um Begrifflichkeiten
Wenn du nicht weißt, was der im Internet 390 Millionen mal verwendete Begriff "Schattenregister" ist und jemand erklärt es dir, dann würde hinterher ein schlichtes "Danke, das wusste ich bisher nicht!" auch schon reichen.
Plenk
Ich mache das, weil ich es als richtig empfinde.
Ok, vermerkt.
So lieber Lothar, zum Schluss eine Bitte. Wenn du dich in Threads, die
ich angefangen habe oder anfangen werde zukünftig mehr um das Thema als
die sprachliche Form kümmerst wäre mir das recht
Liebster Harry, erinnere mich bitte daran, falls ich nochmal ungewollt irgendwas in einem deiner Threads schreibe.
Jetzt geht es in diesem Thread also um Begrifflichkeiten
Ja, so ist das nun bei Sprache und Informationsaustausch.
Die Verständigung zwischen den Teilnehmern funktioniert halt nur, wenn man verständliche und richtige Begriffe verwendet. Sonst redet man oft aneinander vorbei...
Hinweis: Wenn man nicht helfen kann, oder auch nicht will: Einfach mal
die Pfoten von der Tastatur lassen!
Manchen Threads wäre besser geholfen, wenn die Ersteller die zulässigen Antworten gleich in der Frage mit auflisten. Und man nur noch ankreuzen darf. Fehlt darin "nichts von alledem, und zwar...", erspart es solche Diskussionen wie hier.
Jetzt geht es in diesem Thread also um Begrifflichkeiten
Ja, so ist das nun bei Sprache und Informationsaustausch.
Die Verständigung zwischen den Teilnehmern funktioniert halt nur, wenn
man verständliche und richtige Begriffe verwendet. Sonst redet man oft
aneinander vorbei...
Endlich mal wieder ein sinnvoller Beitrag, danke dafür :-)
Als ich das las kam mir spontan der Gedanke, dass du wahrscheinlich
total übertreibst, aber ...
... das ist ja wirklich eine Nußschale. Aber Hallo! Ich wusste gar
nicht, dass es so kleine Mikrocontroller gibt.
Tja, wenn ich mal übertreibe, dann schreibe ich das dazu. Damit das jeder sogleich sehen kann.
Und die bodenlose Angst vor jeglicher Assembler-Programmierung scheint mir nur ein Ausdruck mangelnder Fähigkeiten zu sein. Gerades bei kleineren PIC's mit nur wenig Flash und ebenso wenig RAM ist das (zumindest für mich) deutlich einfacher, schneller und platzsparender als das Verwenden einer maschinenunabhängigen Sprache wie z.B. C.
Allerdings räume ich ein, daß ich gerade die PIC16 seit ganz vielen Jahren und in Assembler programmiere. Das ist etwas anderes als bei jemandem, der mit Mühe gerade mal C erlernt und die zu programmierende Plattform nur so ungefähr mal gesehen hat.
Oft werden Argumente für C angebracht, die bei näherer Betrachtung albern oder gar auf falschen Randbedingungen fußen.
Portabilität: So etwas greift bei Algorithmen, die im Grunde hardwareunabhängig sind. Beispiele: Software-I2C-Treiber, um serielle EEPROM's zu benutzen oder Kreisberechnung für Displayzwecke. Aber für das, was man mit einem 6 pinnigen µC und bis zu 512 Maschinenbefehlen überhaupt machen kann, ist das Argument albern.
Entwicklungszeit und -Aufwand und Fehlervermeidung: So etwas greift ebenfalls nur bei größeren Projekten. Bei kleineren Projekten sind es eher die mangelnden Fähigkeiten des Programmierers. Man sieht es hier am Thema dieses Threads bereits: Da hat jemand zwar von Bitfeldern in C gehört/gelesen, aber er verstrickt sich dabei in einem Dickicht aus Wenn und Abers, das zum Teil von C her kommt und nur zum anderen Teil aus der Unkenntnis/Nichtbeachtung der PIC-Architektur.
Lesbarkeit: Das ist ein Problem der Umsetzung von dem, was man in der Plattform bewirken will hin zu dem, was man in C überhaupt formulieren kann. Bisweilen kommt dann in C ein Schwulst dabei heraus, wo man erstmal grübeln muß, was der Autor da überhaupt mit bezwecken will.
Soviel zur Kritik an Argumenten zu C.
Ein anderes Thema tritt hier in diesem Thread ebenfalls deutlich in Erscheinung: Die Ansichten der Leute, die sich auf bestimmte Architekturen konzentriert haben über andere Architekturen, die sie nur vom Hörensagen kennen, aber an der ihnen vertrauten Arcitektur messen wollen. Einen typischen Satz darüber gebe ich hier nochzum Besten: "Die PIC16 haben ja nur 1 Register in der CPU, wie erbärmlich." Gemeint ist das W-Register und eben nicht bekannt ist, daß ein Großteil der Operationen ohne CPU-Register direkt im RAM bzw. Hardwareregistern stattfindet.
Als ich das las kam mir spontan der Gedanke, dass du wahrscheinlich
total übertreibst, aber ...
... das ist ja wirklich eine Nußschale. Aber Hallo! Ich wusste gar
nicht, dass es so kleine Mikrocontroller gibt.
Tja, wenn ich mal übertreibe, dann schreibe ich das dazu. Damit das
jeder sogleich sehen kann.
Und die bodenlose Angst vor jeglicher Assembler-Programmierung scheint
mir nur ein Ausdruck mangelnder Fähigkeiten zu sein. Gerades bei
kleineren PIC's mit nur wenig Flash und ebenso wenig RAM ist das
(zumindest für mich) deutlich einfacher, schneller und platzsparender
als das Verwenden einer maschinenunabhängigen Sprache wie z.B. C.
Ich habe keine Angst, habe bereits Ende der 1980er eifrig assembliert, x86 damals.
Allerdings räume ich ein, daß ich gerade die PIC16 seit ganz vielen
Jahren und in Assembler programmiere. Das ist etwas anderes als bei
jemandem, der mit Mühe gerade mal C erlernt und die zu programmierende
Plattform nur so ungefähr mal gesehen hat.
Da stimme ich dir teilweise zu.
Ich habe im Laufe meines Lebens (historisch sortiert):
meinen Taschenrechner programmiert
Basic gekernt und es schnell wieder sein gelassen.
Turbo Pascal geliebt, leider braucht das heute niemand mehr (+ Asm im TC-Code)
Assembler x86
Im Studium : Modula-2
C - eine Sprache, die man überall brauchen kann (PC, Arduino, Raspi, µC)
C++ - einfach klasse
Im Berufsleben
Java - meine derzeitige Hauptsprache
Perl - aber das brauche ich gottseidank nicht mehr
Ruby - jobbedingt musste ich diese Kröte schlucken
HTML (naja, eiegntlich keine Programmiersprache)
sämtliche Scriptsprachen in Linux und Windoof
python - überschätzt aber leider viel verwendet
diverse Sprachen, die ich bereits vergessen habe
Vielleicht sollte ich noch erwähnen, dass ich im Studium Programmierkurse für andere Fachbereiche gemacht habe.Daher tangieren mich die abfälligen Bemerkungen bzgl. meiner Kenntnisse nur bedingt :-)
Oft werden Argumente für C angebracht, die bei näherer Betrachtung
albern oder gar auf falschen Randbedingungen fußen.
Portabilität: So etwas greift bei Algorithmen, die im Grunde
hardwareunabhängig sind. Beispiele: Software-I2C-Treiber, um serielle
EEPROM's zu benutzen oder Kreisberechnung für Displayzwecke. Aber für
das, was man mit einem 6 pinnigen µC und bis zu 512 Maschinenbefehlen
überhaupt machen kann, ist das Argument albern.
Nein, das Argument ist valide. C ist prinzipiell harwareunabhängig. Dass man ein beliebiges C-Programm nicht auf jede Hardware anwenden kann ist einfach ein Fakt, aber kein Argument gegen C.
Entwicklungszeit und -Aufwand und Fehlervermeidung: So etwas greift
ebenfalls nur bei größeren Projekten. Bei kleineren Projekten sind es
eher die mangelnden Fähigkeiten des Programmierers. Man sieht es hier am
Thema dieses Threads bereits: Da hat jemand zwar von Bitfeldern in C
gehört/gelesen, aber er verstrickt sich dabei in einem Dickicht aus Wenn
und Abers, das zum Teil von C her kommt und nur zum anderen Teil aus der
Unkenntnis/Nichtbeachtung der PIC-Architektur.
Ich war auf der Suche des "GP2 lässt sich nicht beschreiben"-Problems
und habe dabei alles probiert, was mir sinnvoll erschien.
Um es mal so zu sagen: Nach der Veröffentlichung meines Quelltextes hies es, dass er fehlerfrei ist. Also habe ich einfach Dinge ausprobiert.
Niemand hat bemerkt, dass "OPTION" noch nicht korrekt gesetzt war.
Einer hat sich damit gebrüstet, dass er selbst das schon von Anfang an alles richtig gemacht hat, das ist ihm aber erst eingefallen, nachdem er meine Lösung gelesen hat. Solche Kommentare nach dem Motto - hab' ich's doch gewussst, bin aber selbst nicht drauf gekommen finde ich nicht sehr hilfreich.
Lesbarkeit: Das ist ein Problem der Umsetzung von dem, was man in der
Plattform bewirken will hin zu dem, was man in C überhaupt formulieren
kann. Bisweilen kommt dann in C ein Schwulst dabei heraus, wo man
erstmal grübeln muß, was der Autor da überhaupt mit bezwecken will.
Soviel zur Kritik an Argumenten zu C.
C reicht für mein Projekt, also nehme ich es. Wer Textverarbeitungen in Assembler schreibt möge das tun :-)
Wer in C Schwulst schreibt wird es bei Assembler auch tun.
Ein anderes Thema tritt hier in diesem Thread ebenfalls deutlich in
Erscheinung: Die Ansichten der Leute, die sich auf bestimmte
Architekturen konzentriert haben über andere Architekturen, die sie nur
vom Hörensagen kennen, aber an der ihnen vertrauten Arcitektur messen
wollen. Einen typischen Satz darüber gebe ich hier nochzum Besten: "Die
PIC16 haben ja nur 1 Register in der CPU, wie erbärmlich." Gemeint ist
das W-Register und eben nicht bekannt ist, daß ein Großteil der
Operationen ohne CPU-Register direkt im RAM bzw. Hardwareregistern
stattfindet.
W.S.
Da hast du recht, Antworten die darauf hinauslaufen, dass ich den falschen Prozessor verwende waren nicht im mindesten hilfreich. Das sind halt Zeitgenossen, die sich nicht mit dem eigentlichem (meinem) Problem befassen, sondern lieber rumquasseln, weil sie eine Art Langeweile erfasst hat, die wohl nur mit wenig hilfreichen Posts kompensiert werden kann.
Ich hoffe dass in diesem Thread jetzt endgültig alles Wichtige und Unwichtige besprochen wurde. Ich habe meine Lösung und werde nun das implementieren, was ich vorhabe, es wird funktionieren und meine Welt ein wenig schöner machen :-)
So etwas greift
ebenfalls nur bei größeren Projekten.
Programme haben aber die Angewohnheit zu wachsen. Es fallen einem viele schöne Dinge ein, die der MC noch nebenbei machen könnte.
Dann ist es schön, wenn man einfach nur von dem 6-Pinner auf einen 14-Pinner wechseln kann, ohne alles nochmal neu schreiben zu müssen. Und haste nicht gesehen, ist man beim 64-Pinner gelandet.
Ich möchte nicht extra eine Babysprache lernen müssen, nur weil das Projekt gerade mit einem 6-Pinner auskommt.
Bitfelder für IO-Pins benutze ich sehr gerne, es macht den Code viel übersichtlicher. Man muß dann je Pin nur ein Symbol definieren und nicht immer Bitmaske und Byteadresse getrennt mitschleifen. Bitfelder findet man daher auch oft in den professionellen Headern des MCs.
Auch kann es oft passieren, daß man die Pinzuordnung ändern muß, z.B. für ein besseres Layout oder weil alternative Funktionen einen Pin belegen.
Programme haben aber die Angewohnheit zu wachsen. Es fallen einem viele
schöne Dinge ein, die der MC noch nebenbei machen könnte.
Bleib mal beim Thema. Ich sehe überhaupt keine Wahrscheinlichkeit, daß jemand auf die Idee kommt, da einen 6-Pinner durch einen 14-Pinner oder gar 64-Pinner zu ersetzen. Allenfalls die umgekehrte Richtung: ihn wegzurationalisieren aus Kostengründen.
C reicht für mein Projekt, also nehme ich es. Wer Textverarbeitungen in
Assembler schreibt möge das tun :-)
Wer in C Schwulst schreibt wird es bei Assembler auch tun.
Da bist du auf dem falschen Dampfer. Mir ging es dabei darum, daß man mit einer maschinenunabhängigen Sprache nicht die Spezialitäten einer bestimmten Plattform für den Programmierer verfügbar machen kann. Also ist es immer ein Umschreiben dessen, was man machen will mit den Ausdrucksmitteln der verwendeten Sprache. Also quasi eine Art Workaround. Und da kommt eigentlich fast immer ein Schwulst in C bei heraus. Schau dir doch dein eigenes Beispiel an: Da definierst du einen Struct, um dem Nichtvorhandensein von echt einbittigen Booleans zu entgegnen. Ist nicht dein Fehler, aber an sowas siehst du, was du in C (oder einer anderen maschinenunabhängigen Sprache) an Workarounds machen mußt. Dabei ist das nur ein ganz harmloses keines Beispiel (die Sinnhaftigkeit von typedef will ich hier nicht diskutieren).
Die Maschinenunabhängigkeit einer Programmiersprache erkauft man sich durch die Beschränkung auf eine Art kleinsten gemeinsamen Nenners. Und die nachträgliche teilweise Wiederanpassung ist dann Obliegenheit des nachfolgenden Optimierers, der mehr oder weniger gut sein kann. Irgend eine Kröte liegt eben immer auf dem Teller.
Meine Bitte : den ganzen Thread löschen, er gefällt mir nicht.
Du hast eine eher seltsame Ansicht über Foren, speziell DIESES Forum. Wenn du nur lesen willst, was dir gefällt, dann ist ein Diskussionsforum nicht die richtige Stelle.
ich habe es eben geschaft mein erstes Programm für den PIC10F202
zu debuggen (ich bitte um Applaus :-)
Dabei ist mir aufgefallen, dass das Setzen von einzelnen Bits in einem
bitfield nicht so funktioniert, wie ich mir das dachte.
Tja, das Setzen des einzelnen Bits hat wohl funktioniert, allein es hatte nicht die erwünschte Wirkung auf den betreffenden Chip. Das sieht da eher danach aus, als ob du von Anfang an nicht an der richtigen Stelle gesucht hattest. Kann jedem mal passieren, allerdings hätte es dir bereits vor dem Eröffnen dieses Treads zu denken geben können. Da ist es kein Wunder, daß aus einem solchen Thread auch mal eine dezente Zurechtweisung werden kann: "du Dussel, du hast da was ganz anderes vergessen!". Man sollte bei sowas nicht die beleidigte Leberwurst spielen.
Wenn du mich meinst: du bellst den falschen Baum an. Und wenn du mich nicht meinst, dann hast du aber schon einen unflätigen Ton am Leib.
du löschst wohl gerade das, was dir nicht gefällt.
Meine Zeit ist mir sogar zu schade, zu schauen, was denn da gelöscht wurde.
Meine Bitte : den ganzen Thread löschen, er gefällt mir nicht.
Lies die Nutzungsbedingungen: du hast nach dem Absenden eines Posts die Nutzungsrechte an den Besitzer der HP abgegeben und bezüglich irgendwelcher Löschungen kein Mitspracherecht.
Wenn du mich meinst: du bellst den falschen Baum an. Und wenn du mich
nicht meinst, dann hast du aber schon einen unflätigen Ton am Leib.
du löschst wohl gerade das, was dir nicht gefällt.
Meine Zeit ist mir sogar zu schade, zu schauen, was denn da gelöscht
wurde.
Meine Bitte : den ganzen Thread löschen, er gefällt mir nicht.
Lies die Nutzungsbedingungen: du hast nach dem Absenden eines Posts
die Nutzungsrechte an den Besitzer der HP abgegeben und bezüglich
irgendwelcher Löschungen kein Mitspracherecht.
Ich habe zwei Mails bekommen, dass Beiträge von mir gelöscht wurden.
Eine Begründung gab es nicht.
Ich habe die Nutzungsbedingungen gelesen.
Ich habe gegen keine der Nutzungsbedingungen verstoßen, falls doch, kann man mir das ja mitteilen. Wenn du mir einen unflätigen Ton vorwirfst bist, hast du das Wort unflätig wohl nicht ganz verstanden. Wenn du nicht der "Löscher" bist und dich angesprochen fühlst, misch dich nicht ein.
Dass einige Poster hier einen Ton drauf haben, der mir nicht gefällt, ist mein Problem, dass man aber meine Beiträge löscht, obwohl sie in keinster Weise irgendwie zu beanstanden wären, finde ich schon recht merkwürdig.
Komm' mal von deinem hohen Roß runter !