FAQs (interessante Kundenfragen)

Hier werden interessante technische Fragen der iL_BAS16xxx-Anwender beantwortet. Es können natürlich nicht alle per E-Mail eingehenden Fragen hier aufgenommen werden. In Vordergrund steht die individuelle Beratung per E-Mail. Nur wenn die Fragen und Antworten von allgemeinem Interesse sind werden sie hier aufgenommen. Aus Gründen der Anonymität ist es manchmal notwendig, die Fragen etwas umzuformulieren.
Übersicht:
Wenn PicKit2 nicht aus der iL_Edy-Umgebung nicht funktioniert
16F628, was tun wenn nichts läuft? (PDF)
Timerinterrupt ohne CLOCK-Befehl?
OSCCAL, CALVAL und OSCCON?
iL-Edy und iL-BAS16 unter Window Vista
Sichere Erfassung von Impulsen mit PULS_IN
Zugriff auf die von BINTOASC erzeugte Zeichenkette
16-Bit Variable im EEPROM abspeichern
Programmiergeräte von Fremdherstellern
PWM mittels PWM-Modul des PICs
Quadratwurzel
Ansprechen eines 24LC64 EEPROMs ( I²C )
Einlesen einer Spannung von 0V bis 5V mit dem 16F628
GP2 beim 10F20x funktioniert nicht
Bei der 32-Bit-Division durch 0 stürzt das Programm im PIC ab
Individuelle Teilebausätze für "Flash Of Inspiration I"
Einfluss der Versorgungsspannung auf die interne Oszillatorfrequenz
TIMEOUT und UART
Der PIC 12F675 funktioniert einfach nicht
Ich muss y=0.539x - 84.423 rechnen
Es wird kein INT-Interrupt ausgelöst
Umstieg vom 16F84 auf 16F819
AD-Wandler LTC1286 auslesen
I/O-Pins des 16F876 "Probleme"
Mein Programm läuft für Minuten oder Stunden ohne Probleme, bis
1 zeiliges LCD Display
Windows XP startet der Editor iL_EDy nicht
Watchdog
Befehl CLOCK mehrfach
Programmsequenz in Assembler
Der 16F628 schafft mich! Alle LEDs an Port RA...
Frage 1:
Ich muss Daten aus dem AD-Wandler LTC1286 auslesen. Dieser unterstützt aber das SPI-Protokoll, das von iL_BAS nicht unterstützt wird. Was muss ich machen?
Antwort:
Das SPI-Protokoll ist sehr einfach gehalten und kann mit wenigen BASIC Programmzeilen sehr effektiv programmiert werden. Nachfolgend ein Beispiel:

define wert = ... as word
set ad_cs 'AD-Wandler deselektieren
set ad_Clock 'Clockleitung auf High
start:
res ad_cs 'AD-Wandler einschalten
let count=15 '15 Schritte notwendig
let wert=0 'Ergebnis zuerst auf 0
rd_adc:
let wert=wert*2 'um 1 Bit nach links schieben
res ad_clock 'Clock auf Low
let wert=wert 'nur zur Zeitverzögerung
set ad_clock 'Clock wieder High
if ad_dat=1 then set wertl,0 else res wertl,0
dec count if count>0 then goto rd_adc
... das Ergebnis steht jetzt in Variable WERT
Seitenanfang
Frage 2:
Sind Ihnen bei den I/O-Pins des 16F876 "Probleme" bekannt bzw. gibt es beim RB3 etwas besonders zu beachten? Nachfolgende Befehle verwenden wir:
high RB,1 -> funktioniert
high RB,2 -> funktioniert
high RB,3 -> funktioniert nicht!
Am RB3 funktioniert kein Pegelwechsel?
Antwort:
Das Problem ergibt sich dann, wenn beim Programmieren das LVP (low voltage programming) Bit auf 1 (enable) steht. Dann wird nämlich der Programmiermodus nicht nur durch eine Vpp an MCLR-Pin aktiviert sondern auch durch Highpegel an RB3. Damit ist aber der Pin RB3 nicht mehr als I/O-Pin verfügbar. Dieser Umstand muss also bei der Programmierung des Konfigurationswortes, der Bausteine die über das LVP-Bit verfügen, beachtet werden. 
Seitenanfang
Frage 3:
Mein Programm läuft für Minuten oder Stunden ohne Probleme, bis irgend ein PIC auf dem RTCC-Pin plötzlich mit einem Low-Dauersignal den Bus "festhält" (der Kunde hat hier ein kleines Netzwerk aus mehreren PICs und den Befehlen SERIN und SEROUT realisiert). Das Programm in diesem PIC stürzt aber nicht ab, sondern läuft "normal" weiter, es können lediglich von allen PICs durch das fest anliegende L-Dauersignal keine Daten mehr gesendet werden, weil der Pullup-Widerstand die Spannung nicht meht auf High hochziehen kann. Ein Bauteildefekt schließe ich ebenso aus, wie ein Programmierfehler. Ich vermute, dass man entweder den RTCC-Pin nicht als RS-Ausgang nehmen kann, oder ein unbekannter interner Ablauf den Ausgang auf Low setzt. Können Sie mir einen Tipp geben?
Antwort:
Es ist nicht auszuschließen, dass durch iregndeine Störung von außen der Ausgang sich ändern kann. Ich würde hier folgende Schritte unternehmen:
1. Zusätzlich zum Setzen des RTCC-Pins auf "1" als Ruhepegel, das TRIS-Register für diesen Pin auf Input.
2. In regelmäßigen Abständen die Leitungen auf Dauer-Low prüfen und geg.falls die Pegel und das TRIS-Register neu setzen. Wenn der Prozessor sich nicht aufhängt, wird dieses Vorgehen funktionieren. In älteren Datenblättern von Microchip wird empfohlen das TRIS-Register regelmäßig zu erneuern, falls dies die Applikation erlaubt. In den neueren Datenblättern fehlt leider dieser Hinweis.
Seitenanfang
Frage 4:
Mein Problem ist ein 1 zeiliges LCD Display richtig zum Anzeigen zu bringen. Ich programmiere den Befehl LCDINIT rb,1,16 um bei dem PIC 16F84 den Port RB zu benutzen. Mit dem angeschlossenen Display werden aber nur 8 Stellen korrekt ausgegeben, der Rest wird auf dem LCD nicht angezeigt. Das LCD Modul ist von der Fa. C.... Ich hatte den Verdacht es läge an dem Controller des Displays (nicht Hitachi kompatibel?). Ein anderes Display von Fa. R.... (Hitachi-kompatibel) zeigt genau das gleiche Symtom, es werden nur 8 Stellen initialisiert. Auch eine Veränderung des LCDDELAYs brachte keinen Erfolg. Können Sie mir helfen wo hier das Problem liegt?
Antwort:
Leider sind manche LCD-Anzeigen die optisch wie 1 x 16 aufgebaut sind extrem billig produziert. Hier wurde nämlich ein normalerweise notwendiger Multiplexer einfach weggelassen und dafür die Multiplexleitungen für die Zeile 2 zur Ansteuerung der hinteren 8 Zeichen verwendet. Im Klartext heißt das, Sie müssen diese Anzeige programmtechnisch wie eine 2 x 8 behandeln. Probleme gibt es eigentlich nur dann, wenn eine Zahl über diese Grenze zwischen Zeichen 8 und 9 geschrieben werden soll. Das geht nicht. (Siehe auch Handbuch)
Seitenanfang
Frage 5:
Auf meinem Rechner mit Windows XP startet der Editor iL_EDy nicht (Fehlermeldung Kernel32), auch wenn ich in XP unter Eigenschaften sage, dass das Programm in W98/Me oder W2000 Mode laufen soll, kommt nur diese Fehlermeldung von XP. Die Programme iL_BAS16xxx und den Assembler jedoch kann ich per Mausklick starten. Ich habe das Programm auf einem anderen Rechner mit W2000 probiert und es läuft. Haben Sie hierzu für mich eine Lösung, da ich einen neuen Rechner besitze und das Betriebssystem XP benutze?
Antwort:
Auf Ihrem neuen Rechner ist kein Drucker installiert. Installieren Sie einen Drucker, auch wenn dieser nie verwendet werden soll. iL_EDy erwartet einen installierten Drucker.
Seitenanfang
Frage 6:
Wir setzen in Ihrem Basic-Compiler den Watchdog mit folgendem Befehl "laufend" zurück:
asm
clrwdt
endasm
Leider funktioniert dies nicht und im Handbuch finden wir keine Erklärung. Können Sie uns hierzu weiterhelfen?
Antwort:
Sie benutzen in Ihrem Programm den PRINT-Befehl. Die Datenausgabe dauert in diesem Fall länger als die Periodendauer des Watchdogs. Abhilfe schafft hier nur die manuelle Änderung des Vorteilers im OPTION-Register.
Seitenanfang
Frage 7:
Kann man den Befehl CLOCK mehrfach in einem Programm verwenden? Ist es Zufall, dass mein Programm bei folgender Eingabe nicht mehr läuft?
CLOCK zeit
CLOCK timer
CLOCK zahl
Antwort:
CLOCK darf in einem Programm nur einmal vorkommen, sonst wird eine bestimte Codesequenz mehrmals generiert und das Programm läuft nicht mehr.
Seitenanfang
Frage 8:
Um mein Programm an einer Stelle zu optimieren, habe ich eine Programmsequenz in Assembler eingefügt.
...
DECFSZ count1
LJMP weiter
...
Leider funktioniert das Programm nicht. Was mache ich falsch?
Antwort:
Sie benutzen den LJMP um über Programmseitengrenzen zu springen. Dieser Befehl wird aber vom Assembler in eine Reihe von einzelnen Assemblerbefehlen zerlegt. Der DECFZ-Befehl überspringt aber nur den nachfolgenden PIC-Befehl. Es wird sozusagen der LJMP-Befehl nur z.T. ausgeführt, was zu Fehlfunktionen führt. Schreiben Sie
.....
DEC count1
LJNZ weiter
.....
Seitenanfang
Frage 9:
Ich trete seit 5 Stunden auf der Stelle! Der 16F628 schafft mich; ich bin suizidgefährdet! Alle LEDs an Port RA bleiben eingeschaltet, der Summer funktioniert nicht.
Antwort:
Die Portleitungen von RA stehen nach dem Einschalten auf Komparatorbetrieb. Sollen Sie als normale I/O-Pins arbeiten muss in der DEFINE DEVICE Anweisung noch die Angabe CMCFG7 (CMCFGx mit x = 0...7) gemacht werden.
Hinweis: Bei PICs mit AD-Wandler muss ADCFGx verwendet werden, sonst hat man die gleichen Probleme.
Seitenanfang
Frage 10:
Umstieg vom PIC 16F84 auf PIC 16F819
Ich habe für den PIC16F84 ein Programm geschrieben mit 5 Eingängen (PORT A) und 8 Ausgängen (PORT B), die einwandfrei laufen. Ich habe das Programm an den PIC 16F819 angepasst, aber es erkennt keine Eingaben. Die Kontrolle erfolgt über ein LCD. Da die Eingaberoutine bei 16F84 einwandfrei läuft, kann ich mir nicht erklären, wieso das Programm auf dem 16F819 nicht läuft.
Antwort:
Im Gegensatz zum 16F84 hat der 16F818/16F819 am Port RA Analogeingänge, die beim Einschalten aktiv sind. Um alle auf Digital-IO umzuschalten, muss in der DEFINE DEVICE Zeile der Eintrag ADCFG7 stehen. Mit dieser Änderung sollte das Programm laufen.
Weitere Unterschiede:
Der MCLR-Pin kann ebenfalls als Digital-IO verwendet werden ( => MCLR_INT ).
Ist der interne RC-Oszillator aktiviert, läuft der PIC beim Einschalten mit 32 kHz. Um die Frequenz auf 4 MHz umzuschalten muss die Anweisung LET OSCCON=$60 ausgeführt werden.
Seitenanfang
Frage 11:
Es wird kein INT-Interrupt ausgelöst
Ich benötige für mein zukünfiges Projekt einen passenden PIC-Basic Compiler. Dabei bin ich auf Ihr Produkt gestoßen und habe mich gleich mal ans Testen gemacht. Habe einen 16F84A verwendet und Ihre DEMO (16C83). Es funktioniert alles bis auf den Interrupt-Befehl. Ich bekomme ihn zwar fehlerfrei programmiert, aber es wird kein INT ausgelöst. Ich möchte den INT an RB0/INT durch eine fallende Flanke auslösen.
Hier mein Beispiel:

$obj2hex 'generates a hex file optionally
define device 16c83
xtal 18.867
INTERRUPT intserv,hl,gied 'intserv = Name des ISR
inp rb,0 REM hl = Fallende Flanke an RB0
low ra,1
START:
high ra,0
low ra,0
GOTO start REM Springe nach START
INTPROC
INTSERV:
high ra,1
low ra,1
INTEND
Ich habe es noch mit anderen Varianten gecheckt, aber es kommt nicht zum gewünschten Ergebnis. Mache ich nun etwas falsch, oder geht das in der DEMO nicht?

Antwort:
Doch diese Funktion geht sehr wohl in der Demo-Version. Sie haben allerdings vergessen die Interrupts freizugeben. Beim Einschalten des PICs sind nämlich alle Interrupts gesperrt. Die Freigabe bzw. das Sperren erfolgt mit der Anweisung SET / RES INTE und SET / RES GIE. Dabei ist GIE die globale Interruptfreigabe und INTE die Freigabe für den RB0/INT-Interrupt. Ist die Interruptbedingung erfüllt, wird in diesem Fall das Interrupt-Flag INTF gesetzt. Sind die obengenannten Freigaben aktiv, verzweigt der Prozessor zur Interruptroutine. Hier muss unbedingt dieses INTF-Bit zurückgesetzt werden, da sonst der Prozessor laufend in diese Interruptroutine verzweigen würde.
Seitenanfang
Frage 12:
Ich muss y=0.539x - 84.423 rechnen
Ich lese einen Temperatursensor am Analogport ein und möchte die Temperatur auf einem Display anzeigen. Der Sensor ist nicht linear. Ich könnte mit zwei Tangenten hinkommen, müsste aber hierzu folgende Formel benutzen: y = 0,539x - 84,423. Ist das möglich, wenn ja wie? Oder gibt es für solche Probleme andere Lösungsansätze?
Antwort:
Der PIC-BASIC-Compiler kann gundsätzlich keine Fließkomma-Arithmetik. Dennoch kann man solche Aufgaben lösen. Angenommen Sie haben einen 10-Bit Wert vom AD-Wandler erhalten. Diesen legen Sie in einer 16-Bit Variablen ab. Wenn Sie diesen Wert mit 10 multiplizieren wird der Zahlenbereich mit Sicherheit nie überschritten. Statt der Multiplikation mit 0,539 dividieren Sie diesen Wert durch 185. Dies ist der entsprechende Kehrwert multipliziert mit 10. Dieses Zwischenergebnis multiplizieren Sie nun wieder mit 100 und subtrahieren den Wert 844. Nun dividieren Sie nomals durch 10 und erhalten So das Ergebnis. Eine Rundung der 1. Nachkommastelle können Sie dadurch erreichen, dass Sie vor dem letzen Dividieren den Wert 5 hinzuaddieren. Das Ergebnis das Sie erhalten hat einen Fehler von weniger als 1%. gegenüber der genauen Rechnung. Die Genauigkeit können Sie weiter steigern, wenn Sie statt dem Faktor 10 den Faktor 50 verwenden. Lediglich wenn Sie negative Temperaturen messen wollen, müssen Sie zusätzlich eine Nullpunktverschiebung durch die Addition einer Konstanten durchführen. 0°C ergeben in diesem Beispiel einen AD-Wert von 159.
Seitenanfang
Frage 13:
mein Problem ist, das ich leider kein einziges Programm mit dem PIC 12F675 zum Laufen bringe, bei dem der Ad-Wandler und der Comperator ausgeschalten ist und der interne Oszillator verwendet wird. Der Compiler meldet keinen Fehler. Ich programmiere den Hexcode über Picstart Plus. Könnten Sie mir ein kleines Musterprogramm machen, damit ich meinen Fehler finde.
Antwort:
Das nachfolgende Testprogramm das an GP0 und GP1 LEDs ein- und ausschaltet. Beim Programmieren des 12F675 ist es ganz wichtig, dass auf der letzten Speicherstelle im Programmspeicher der Calibrationswert steht. Dieser lautet 34xx, wobei xx ein Wert zwischen 00 und FF sein kann. Fehlt dieser Wert, läuft der Baustein nicht. Da dieser Wert beim Löschen verloren geht, sollte man vor dem Löschen den Baustein auslesen und den Wert an der Adresse 3FFH notieren. So kann dieser nachträglich wieder eingebrannt werden. Überprüfen Sie in jedem Fall vor dem Programmieren diesen Wert. Manche Programmiergeräte nehmen auf diesen Umstand keine Rücksicht, so dass man ggf. diesen Wert jedesmal manuell eingeben muss. Der Compiler iL_BAS16 bietet für diese Fälle den Befehl CALVAL xx an (für xx nur der Zahlenwert angeben, nicht den führenden Code 34). Damit wird dann allerdings jeder 12F675 mit diesem Wert programmiert, was sich in einer u.U. falschen Oszillatorfrequenz benerkbar macht. Im Beispielprogramm sind alle Pins auf IO-Betrieb umgestellt, wobei GP3 nur als Eingang funktioniert.

define device 12F675,WDT_off,PROTECT_OFF,IRC_OSC,PWRTE_ON,MCLR_INT,ADCFG0,OSC2_IO,cmcfg7
tris ra,0
loop:
set ra,0
wait 500
set ra,1
wait 500
res ra,1
wait 500
res ra,0
wait 500
goto loop
Seitenanfang
Frage 14:
Beim SERIN-Befehl gibt es einen Timeout, der allerdings nur dann funktioniert, wenn keine UART verwendet wird. Ich habe eine Applikation, wo ich sowohl die UART verwenden muss, alsauch einen Timeout benötige.

Antwort:
Das Timeout funktioniert nicht in Verbindung mit dem UART. Stattdessen müssen Sie das RCIF-Bit abfragen und falls dieses gesetzt ist zum SERIN verzweigen.
Bsp.
IF RCIF=1 then SERIN port,pin,baud,variable
Seitenanfang
Frage 15:
Hängt die interne RC-Oszillatorfrequenz sehr stark von der Versorgungsspannung ab?
Antwort:
Wir haben einmal diese Frage näher untersucht. Dabei ergibt sich folgendes Bild:
3,88V - 1,0221 MHz (=f/4)
4,00V - 1,0211 MHz
4,50V - 1,0171 MHz
5,00V - 1,0148 MHz
5,50V - 1,0167 MHz
5,84V - 1,0224 MHz
Diese Zahlen zeigen, dass der Bauteileabgleich für eine Betriebsspannung von 5 V erfolgte und es eine nichtlineare Funktion ist.
Seitenanfang
Frage 16:
Ich möchte gerne den Teilebausatz für "Flash Of Inspiration I" bei ihnen kaufen. Beim Zusammenstellen der Bestellliste ist mir aufgefallen, dass micht alle Teile bei einem Lieferanten zu beziehen sind. Da wir nicht aus Deutschland sind, benötigen wir bei den meisten Lieferanten aus Deutschland einen Mindestbestellwert von 100,- Euro. Da wir diesen Betrag aber nicht erreichen, wollte ich Sie fragen, ob Sie die Bauteile auf beiliegender Liste dem Bausatz beilegen könnten?
Antwort:
Teilebausätze nach Vorgaben der Kunden sind wegen des enormen Zeitaufwandes nicht möglich. Wir haben aber einen Komplettbausatz und das Fertiggerät neu ins Lieferprogramm aufgenommen.
Seitenanfang
Frage 17:
Bei der 32-Bit-Division durch 0 (z.B. LET WERT = MWERT / 0) stürzt das Programm im PIC ab.
Antwort:
Eine Division durch 0 ist mathematisch nicht definiert und deshalb nicht erlaubt. Leider kann der Compiler keine Laufzeitfehler ausgeben! Wohin denn auch?. Deshalb darf der Programmierer also niemals durch 0 teilen. Wird durch den Wert einer Variablen geteilt und es ist nicht auszuschließen, dass die Variable den Wert 0 annehmen kann, dann muss vor der eigentlichen Division dieser Fall abgefangen und separat behandelt werden.
Seitenanfang
Frage 18:
GP2 beim 10F20x funktioniert nicht. Ich kann beim 10F202 den GP2 nicht als Ausgang nutzen, obwohl ich TRIS entsprechend gesetzt habe. GP0 und GP1 funktionieren tadellos.
Antwort:
Laut Errata-Datasheet liegt der Fehler in der Maske. Bei neueren Silizium (A1) soll dieser Fehler behoben worden sein. Dennoch kann man das Problem dadurch umgehen, dass man den Takt für TMR0 vom internen Befehlstakt ableitet. Dazu muss in der DEFINE DEVICE Zeile noch der Parameter T0CS_INT stehen.
Seitenanfang
Frage 19:
Ich bin blutiger Anfänger im PIC programmieren und darum bitte ich Sie ein kleine Bespiel einer DEFINE DEVICE Anweisung für den Analogeingang und einer Speicherung der eingelesenen Variable. Ich habe ein FOI1 mit dem PIC 16F628 ich will eine Spannung von ca. 0-5 V aus einem Operationsverstärker bestimmen und ein PWM-Signal so danach einrichten, dass ich den Strom an einem Ausgang regeln kann.
Antwort:
Sie beginnen leider gleich mit einem schwierigen Kapitel. Das erste Problem ist das Fehlen der AD-Wandler beim 16F628. Er hat wohl Eingänge mit der Bezeichnung AN0, AN1 usw. jedoch sind diese "nur" mit Komparatoren verbunden. Eine interne Referenzerzeugung hat 16 Stufen, so dass eine Eingangsspannung von 0 bis 5V in max. 16 Schritte unterteilt werden kann. Falls dies ausreichen sollte, kann man diesen Weg gehen. Ein Beispielprogramm ist AnalogIn.BAS. Ich gehe aber davon aus, dass die Auflösung mehr als 4-Bit sein sollte, z.B. 8-Bit. In diesem Fall ist der sinnvollste Weg die Verwendung eines externen AD-Wandlers z.B. LTC1286. Dieser hat 10-Bit Auflösung und wird über ein SPI-Protokoll angesprochen. Das entsprechende Beispiel heißt LTC1286.BAS. Eine dritte Möglichkeit ist, falls am 16F628 noch 8 I/O-Pins frei sind, mittes R2R-Netzwerk einen DA-Wandler mit 8-Bit Auflösung aufzubauen um so ohne zusätzliche ICs auszukommen. Falls Sie diese Variante realisieren wollen, müssten Sie die vom R2R-Netzwerk kommende Spannung mit der Eingangsspannung vergleichen. Der Vergleich geschieht über den eingebauten Komparator. Per Software legen Sie dann unterscheidliche Werte an das R2R-Netzwerk, wobei jedesmal eine andere Spannung erzeugt wird. Zeigt der Komparator Gleichheit an, dann entspricht der angelegte Zahlenwert der Eingangsspannung. Mit einer dieser Ansätze können Sie ihre Aufgabe sicher lösen. Für die Nutzung der Hardware-PWM ist ein Beispielprogramm PWM1_HARD.BAS.
Seitenanfang
Frage 20:
Hallo, unten stehendes Programm habe ich verfasst um damit ein EEPROM zubeschreiben und auszulesen. Die Werte sollen auf das Display des FOI geschrieben werden. Leider will es mir einfach nicht gelingen die EEPROM-Daten (mit einem externen Programmer auf das EEPROM gebracht) auszulesen!. Die Adresse müsste richtig sein, nur habe ich den 24lc64 eingesetzt der aber dieselbe Adresse haben sollte wie der 24c02 der normalerweise beiliegt?!
Programmauszug:
define device 16f628,wdt_off,irc_osc,cmcfg7,MCLR_INT,OSC2_IO
tris ra,%00000001
...
lcdinit rb,2,16
define ausgabe=$20 ' Adresse der Hilfsvariablen
define eeprom=$A2 as const ' normalerweise $A0 aber durch die "A0" Leitung auf "high" =$A2
define zahl=$21 ' Adresse der Hilfsvariablen
...
i2cinit ra,1,2 'SDA=ra,1 SCL=ra,2
i2cwrite eeprom,1 <- PROBLEM
schleife:
i2cread eeprom,ausgabe
lcdwrite 1,1,zahl,$," : "
....
goto schleife

Vielleicht haben sie eine Ahnung wo der Fehler liegen kann, die FOI müsste einwandfrei funktionieren, da die Demos alle laufen!
Gibt es denn ihnen bekannte Seiten die sich mit ihrer BASIC Umgebung beschäftigen ( Foren usw)?
Antwort:
Hallo, der 24LC64 hat intern mehrere Speicherblöcke mit je 256 Byte. Deshalb reicht eine 8-Bit Adresse zur Addressierung nicht mehr aus. Die Adresse besteht aus 2 Bytes, wobei das erste Byte die Page, die zweite das Byte innerhalb der Page anspricht. Beispiel: I2CWRITE 162,0,5,wert schreibt den Inhalt von Wert an die 6. Position (0-255) der ersten Seite (Page). I2CWRITE 162,0,5 I2CREAD 162,wert liest den Wert wieder aus. Leider gibt es kein Forum. Ich habe leider viel schlechte Erfahrung mit solchen Foren gemacht, da die Informationen größtenteils sehr schlecht, manchmal auch falsch und irreführend waren. Deshalb ist es besser, wenn Sie sich per EMail direkt an mich wenden. Ich gebe ihnen mit Sicherheit gleich die richtige Antwort und dazu oftmals auch noch zusätzliche Hintergrundinformationen. Gelegentlich werde ich dann Auszüge aus solchen EMails in FAQ auf der Homepage veröffentlichen.
Seitenanfang
Frage 21:
Hallo,
ich muss aus einer Zahl die Quadratwurzel ziehen. Der Compiler bietet aber keinen solchen Befehl an. Wie kann man diesen in BASIC realisieren?
Antwort:
Hier ein Programm zur Berechnung der Quadratwurzel (8, 16 oder 32 Bit Variablen) mittels Iteration. a{n+1} = 0,5(X/a{n} + a{n}). Da das Programm stets abrundet, ist ggf. eine Rundung des Ergebnisses notwendig. Dazu wird das Ergebnis mit Ergebnis+1 multipliziert. Ist die Zahl X > dem Produkt, muss das Ergebnis um 1 erhöht werden. Das Beispielprogramm arbeitet mit DBLWORDs. Sollen nur 16-Bit Zahlen Verwendung finden, ist es entsprechend anzupassen.

define device 16F877
define ZahlX = $20 as dblword
define hilfsvar = $28 as dblword
define Wurzel = $30 as dblword
define Wurzel_alt = $38 as dblword
define ii = $3f as byte
define arith32 = $50
cold:
let ZahlX = 4294901761
'Beispielzahl
let Wurzel = ZahlX / 2
loop: let Wurzel_alt = Wurzel
let Hilfsvar=ZahlX / Wurzel
let Wurzel = Wurzel + Hilfsvar
let Wurzel = Wurzel / 2
if Wurzel_alt Wurzel then goto loop
runden:
let Hilfsvar = Wurzel + 1
let Hilfsvar = Hilfsvar * Wurzel
if ZahlX > Hilfsvar then inc Wurzel
'fertig
Seitenanfang
Frage 22:
Der PWM-Befehl von iL_BAS16 erzeugt das Signal mittels Software. Wie kann ich aber die Module für die Hardware-PWM ansprechen?
Antwort:
Dieses Programm zeigt die Anwendung des PWM-Moduls im PIC 16F628, kann auch für andere Bausteine übernommen werden. Da es keinen BASIC-Befehl für das Ansperechen der Hardware-PWM gibt, muss der Anwender das Modul Schritt für Schritt initialisieren. Dass dies sehr einfach ist, zeigt das nachfolgende Programm. Dieser PIC hat nur ein PWM-Modul an Pin RB3. Daher kann weder die LCD noch die Matrixtastatur gleichzeitig verwendet werden. In diesem Programm wird das Tastverhältnis der PWM vom Minimum zum Maximum und wieder zurück gefahren. Die Auflösung der PWM ist eine Funktion der verwendeten Quarzfrequenz, des Vorteilers und des Timers. In diesem Programm ergibt sich bei einer Quarzfrequenz von 4.194394 MHz eine PWM-Frequenz von ca. 670 Hz.
xtal 4.194304
define device 16F628, hs_osc, cmcfg7, wdt_off, mclr_int
define duty=$20 as byte
define fmax=$21 as byte
cold: goto start
'For PWM1 at pin RB1 we initialize PWM1 at RB3
init_pwm: let PR2=$60 'define PWM periode in PR2
let CCPR1L=$30 'define PWM duty cycle
outp rb,3 'this pin must be output
let CCP1CON=$0C 'set PWM mode
Let TMR2=$ff 'maximum timer value
let T2CON=7 'enable timer 2 with prescaler 16
'now we define the max. pwm duty frequency. This value depends on system clock speed (refer datasheet)
let fmax=$60
let duty=fmax 'max pwm duty frequency
return
start: gosub init_pwm 'initialize PWM module
'test program change duty cycle of PWM1
loop1: let CCPR1L=duty 'new pwm duty
dec duty 'duty cycle becomes smaller
if duty=0 then goto loop2
wait 500 'next duty cycle every half second
goto loop1
loop2: let CCPR1L=duty
inc duty 'duty cycles becomes larger
if duty=fmax then goto loop1
wait 500
goto loop2

Seitenanfang
Frage 23:
Wie benutzen erfolgreich den PIC-BASIC-Compiler iL_BAS16 zusammen mit dem Programmiergerät iL_PRG16. Wir wollen aber unser "altes" Programmiergerät ebenfalls benutzen. Es soll in der Produktion eingesetzt werden. Allerdings meldet es beim Laden der OBJ-Datei einen Fehler.
Antwort:
Das Programmiergerät iL_PRG16 nutzt das sogenannte Intel-Hex8-Format mit der Dateierweiterung OBJ. Nachfolgend eine Liste von Programmiergeräten und den notwendigen Compilerschalter, damit eine entsprechend ladbare Datei erzeugt wird:

Programmiergerät Compilerschalter Bemerkungen
Microchip PIC-Start $LIST /M_OBJ
$LIST OBJ2HEX
Bis zur Assemblerversion 5.6-09 (einschl.) darf nur ein $LIST im Programm vorkommen. Deshalb muss dort
$LIST /M_OBJ, OBJ2HEX geschrieben werden.
Vellemann $LIST OBJ2HEX
$LIST /M_OBJ
siehe oben
Seitenanfang
Frage 24:
Immer wieder tucht die Frage auf, ob und wie man eine 16-Bit-Variable im EERPOM-Speicher, der ja 8-Bit breit ist, abspeichern kann. Die Lösung ist letztendlich sehr einfach und benötigt keinerlei Rechnerei.
DEFINE   VAR16 = $20 AS WORD 'eine 16-Bitvarible wird definiert
DEFINE   VAR16L = $20 AS BYTE 'damit bekommt man Zugriff auf das Lowbyte der 16-Bit-Variablen
DEFINE   VAR16H = $21 AS BYTE 'damit bekommt man Zugriff auf das Highbyte, das an der Adresse 21H liegt
....
LET   VAR16 = VAR16 + 5 'ausführen einer 16-Bit Rechenoperation
....
WRITE   5,VAR16L 'abspeichern der 16-Bit-Variable, zuerst das Low-Byte
WRITE   6,VAR16H 'dann das High-Byte
Wenn die Variablen mit AUTO definiert werden, schreibt man analog zur obigen Schreibweise:
DEFINE    VAR16 = AUTO AS WORD
DEFINE    VAR16L = VAR16 AS BYTE
DEFINE    VAR16H  = VAR16 + 1 'AS BYTE darf man ja weglessen, da es den Defaultwert darstellt.
Seitenanfang
Frage 25:
Der Befehl BINTOASC erzeugt aus einer Binärzahl eine entsprechende ASCII-Zeichenkette mit 3 oder 5 Stellen. Wie kann ich auf die einzelen Stellen dieser Zeichenkette zugreifen?
Antwort:
DEFINE  Buffer = 32 as BYTE          'umfasst 5 Bytes
BINTOASC Zahl,Buffer
Bei der Zahl 87 steht an Adresse 31 die 7, an 32 die 8 und an 33 die 0 bzw. Blank. Zugreifen können Sie ganz einfach über einen Array-Zugriff.
LET TEMP = BUFFER(1) greift auf Adresse 32, somit auf die Zahl 8 zu.
LET TEMP = BUFFER(2) liest das Blank aus Adresse 33.
Seitenanfang
Frage 26:
Ist der Befehl PULSIN interruptorientiert? Oder misst er nur die Zeit von der Stelle wenn das Programm in der Zeile ist bis Ende Puls.
Ich will die Impulse erfassen und auf einem Display für 1 Sekunde anzeigen, dann erscheint der nächste Wert. Wie kann ich sicherstellen den Anfangsimpuls mitzubekommen, auch wenn ich in der Warteschleife hänge?
Antwort:
Der Puls_in-Befehl ist nicht interruptorientiert. Aktuell verwendet nur der CLOCK-Befehl einen Interrupt. Alle anderen Interrupts können somit individuell verwendet werden, ohne dass einem der Compiler dazwischenfunkt.
Der Pulsin wartet u.U. zuerst auf den Ruhepegel und von da an auf die geforderte Flanke.
Um in der Wartezeit keinen Impuls zu verpassen, muss man wissen, in welchem minimalen Abstand die Impulse kommen können. Danach richtet sich der Wert für WAIT. Um damit eine Sekunde zu erreichen, wird dieses WAIT in einer Schleife entsprechend oft aufgerufen.

FOR II=0 TO 100
WAIT 10
PULSIN ....
IF ....            'z.B. für Min- und Max-Erfassung
NEXT II
LCDWRITE ...

Seitenanfang
Frage 27:
Die gesamte Entwicklungsumgebung läuft normalerweise auch unter Windows Vista. Lediglich die Hilfe-Dateien werden nicht mehr unterstützt, da Microsoft die HELP-Funktionen nun nur noch in Form von CHM-, XML- oder HTML-Dateien unterstützt. Abhilfe schafft das Herunterladen von WinHlp32.EXE unter http://go.microsoft.com/fwlink/?LinkId=59782. Übrigens kann man dieses Programm auch aus der alten XP-Installation übernehmen. Sollten weiterhin Probleme auftauchen, lesen Sie hier nach: http://www.heise.de/newsticker/meldung/86460
Seitenanfang
Frage 28:
Ich komme einfach nicht hinter das Geheimnis von OSCCAL. In der Speicherstelle 03FF steht 3FFF. Mit dem Befehl CALVAL mag der PIC 12F675 auch nicht seine Arbeit aufnehmen. Dies hat zur Folge, dass der interne Oszillator nicht startet. Opfere ich zwei Pins für einen Quarz, läuft das Programm. Gibt es eine Möglichkeit den Wert für OSCCAL wieder herzustellen?
Antwort:
Das mit dem Kalibrationswert ist schon ein Kreuz! Man muss unterscheiden: Es gibt PICs mit einem OSCCAL- und manche mit einem OSCCON-Register. Bei der ersten Sorte steht der Kalibrationswert auf der letzten Speicheradresse und muss von dort gelesen und in das OSCCAL-Register geschrieben werden. Das Lesen erfolgt bei den 12-Bit-Core und den 14-Bit-Core Pics unterschiedlich. Bei der ersten Sorte muss an der letzten Stelle ein MOVLW xx stehen, bei den 14-Bitter ein RETLW xx. Entsprechend erfolgt der Aufruf um diesen Wert zu lesen. Bei der 12-Bitter springt der Prozessor bei einem RESET auf die letzte Programmstelle und beginnt dort mit der Abarbeitung. Deshalb stört es nicht, wenn dort ein 3FF steht. Bei den 14-Bitter dagegen startet die CPU an der Stelle 0000H und der Wert wird mittels CALL aus der letzten Speicherstelle gelesen. Wenn nun dort kein RETLW steht, kreist der Prozessor immer auf der Adresse 0000. Der Oszillator schwingt also trotzdem, nur das Programm kommt nicht von der Stelle und die Frequenz stimmt natürlich nicht exakt.


Den richtigen Kalibrationswert zu rekonstruieren ist möglich. Man baut sich eine Testschaltung auf, bei der mittels Tasten ein Variablenwert hoch- bzw. heruntergezählt werden kann. Defaultwert für den Kalibrationswert ist 80H, so dass man an die letzte Stelle des Programmspeichers ein RETLW 80H schreiben muss. Das geschieht mit einem CALVAL 80H. Die Oszillatorkonfiguration muss nun so eingestellt werden, dass an dem OSC2-Pin die geviertelte Oszillatorfrequenz erscheint. Diese wird mit einem Frequenzzähler überwacht. Nun tastet man man den Taster in die entsprechende Richtung, dass sich die Frequenz dem Idealwert von 1,00 MHz nähert. Hat man den optimalen Wert gefunden, muss man diesen nur noch wissen. Dazu wird aber dieser Wert einfach per Write-Befehl in das EEPROM geschrieben, das am Ende der Prozedur mittels Programmiergerät (Datenbereich) ausgelesen wird.
Seitenanfang
Frage 29:
Hallo Hr. Lehmann

ich  "Kämpfe" zur Zeit mit einem Zeitproblem. Mein Prozessor ist  ein PIC16F628  ( 4Mhz interner Takt ) und meine Software ist  iL_Bas16PRO ( Editor und Compiler ).
Ich möchte folgendes Programmieren: Alle 20ms soll ein Interrupt ausgelöst werden und in eine Interruptroutine verzweigt werden. Nur bring ich diese Funktion mit den Basic-Befehlen "Clock" und Clock1" nicht her. Kann ich dieses Problem mit dem Timer0  und der Funktion INTPROC lösen, oder muss ich diese Sache in Assembler programmieren?
Antwort:
natürlich können Sie die Interrupts auch "zu Fuß" programmieren, auch in BASIC.


Das längste Interruptintervall beim CLOCK-Befehl ist 10 ms. Intern wird die Variable TIMERX auf 100 gezählt bevor die 16-Bit Clockvariable inkrementiert wird. Wenn Sie das Ganze "zu Fuß" machen wollen, müssen Sie die entsprechenden Einstellungen ermitteln.
Mit LET OPTION_R=%00000111 wird der Vorteiler und die Vorteilerrate eingestellt. Ggf sind hier Anpassungen notwendig, falls Sie noch den RB0-Interrupt benutzen wollen.  Mit dieser Einstellung kommen die Interrupts alle 65,5 ms. Steht der Option-Wert auf %00000110 beträgt die Interruptrate 32,77 ms. Bei %00000101 sind es 16,39ms, bei %00000100 ca. 8,2ms. Sie sehen, dass es bei diesem Quarz nicht möglich ist, genau auf 20 ms zu kommen. Das Problem hat auch der Compiler. Die einzige Möglichkeit besteht darin, die Interrupts häufiger auftreten zu lassen, und diese entsprechend zu zählen. Bei Option = %00000000 ergibt sich ein Wert von 512us. Für 20 ms benötigt man etwas mehr wie 39 Interrupts. Das Problem ist aber, dass diese Interrupts nun sehr oft auftauchen und deshalb die Gesamtleitung des Programmes u.U. zu stark reduziert wird. Aber das hängt natürlich vom Einzelfall ab.
RES T0IF setzt das Timer-Interruptflag zurück (man weiß nie, wie es gerade steht).
SET T0IE gibt den Timer0-Interrupt frei
SET GIE gibt die Interrupts global frei
Nun müssen Sie in ihrer Interruptroutine, die mit INTPROC beginnt und mit INTEND abgeschlossen wird, dafür sorgen, dass bei einem Timer0-Interrupt das richtige passiert. Dazu prüfen Sie innerhalb dieser Routine das T0IF-Bit. Ist es 1, dann war es ein Interrupt vom Timer0. Sie müssen dieses Bit innerhalb dieser Routine wieder zurücksetzen. Achten Sie auch darauf, dass innerhalb der Interruptroutine keine komplexen Befehle verwendet werden. Ein INC oder DEC geht in Ordnung, bei anderen Befehlen kann es kritisch werden. Da es ein REENTRENCE-Problem gibt, müssen Sie in solchen Fällen die internen Compilervariablen mit STACK retten oder Sie unterbinden das Aufrufen von Interrupts innerhalb komplexer BASIC-Befehle durch die Option GIED beim INTERRUPT-Befehl.
Die Problematiken von oben ändern sich übrigens nicht, wenn Sie auf Assembler umsteigen würden.
Frage 30:
Ich kann mit dem PicKit2 nicht aus der iL_Edy-Umgebung programmieren. Es erscheint wohl kurz das Fenster (Konsolenprogramm), verschwindet aber sofort wieder. Starte ich aber die PicKit2-Windows-Software, kann ich programmieren. Die USB-Verbindung und das PicKit2 selbst sind somit in Ordnung.
Antwort:
Das Konsolenprogramm von PicKit2, das von iL_EDy aufgerufen wird, hat so seine Probleme mit Leerzeichen in Datei- und Verzeichnisnamen.  Dies ist bei vielen "DOS-Programmen" noch der Fall. Bitte ersetzen Sie die Leerzeichen durch Unterstriche. Damit bleiben die Namen fast genauso gut lesbar wie mit Leerzeichen.
Seitenanfang