Hallo Leute, ich habe ein Programm für einen Mega8 in Assembler geschrieben, das mir zyklisch den Akku-Ladezustand eines Handys abfragt. Ist der Akku unter 40%, dann wird er geladen bis er voll ist. Ich habe das so gelöst: ldi ZL, LOW(cbc100) ; Startadresse im EEPROM für den ldi ZH, HIGH(cbc100) ; Vergleich laden rcall Num_Check ; Vergleichsroutine aufrufen sbrc FlagReg, Match ; wenn AKKU voll geladen rjmp ladung_aus ; Sprung nach Ladung_aus ldi ZL, LOW(cbc90) ; Startadresse im EEPROM für den ldi ZH, HIGH(cbc90) ; Vergleich laden rcall Num_Check ; Vergleichsroutine aufrufen sbrc FlagReg, Match ; wemm AKKU zu 90% geladen rjmp ladung_aus ; Sprung nach Ladung_aus ...... Immer Text aus dem EEPROM laden, vergleichen, Flag auswerten (Match wird bei Gleichheit SRAM und EEPROM gesetzt) und springen. Das mach ich solange bis ich alle möglichen Meldungen vom Handy abgeklappert hab. Ab 40% springe ich dann nach "ladung_ein". Erscheint mir etwas uneffektiv. Gibts da noch eine elegantere Möglichkeit? Für Vorschläge bin ich dankbar. Gruß Marcus
> Erscheint mir etwas uneffektiv > Das mach ich solange bis ich alle möglichen Meldungen Das Problem ist aber, dass dein Program a priori weiss, wiviele das sind. Besser wäre es, wenn du diese Anzahl auch noch ins EEPROM legst und über die Vergleiche noch eine Schleife legst, die auf dieser Anzahl basiert. NrWerte = vom EEProm lesen for i = 0 to NrWerte - 1 do Grenzwert = i-ten Vergleichswert vom EEprom holen vergleichen und gegebenenfalls springen next
Ich hab 10 mögliche Werte im EEPROM stehen: 1,90 ; 0,90 ; 0,80 ; .... ; 0,10 Hab ich dich richtig verstanden das ich in einer Schleife, in meinem Fall 10 mal, die Daten vom EEPROM hole und vergleiche? Ist die 10 (bzw 9) voll, gehts im Programm normal weiter. Da muß ich die Anzahl ja nicht im EEPROM ablegen, kann ich ja gleich mit LDI den entsprechenden Wert in ein Register laden, dieses mit INC erhöhen und mit CPI vergleichen? Das würde mir zumindest mal Schreibarbeit ersparen und evtl. die Lesbarkeit vom Code verbessern, vom Rechenaufwand für den µC ist es aber kein Unterschied. Mich stört halt das da der AVR recht lange in der Schleife hängt, wobei das für meine Anwendung sicherlich keine Rolle spielt. Gruß Marcus
> Da muß ich die Anzahl ja nicht im EEPROM ablegen, kann ich ja > gleich mit LDI den entsprechenden Wert in ein Register laden Genau das würde ich nicht tun. Bei einer Änderung musst du dann an 2 Stellen ändern: im Programm und in der Datentabelle. > Mich stört halt das da der AVR recht lange in > der Schleife hängt, wobei das für meine Anwendung sicherlich keine > Rolle spielt. Der Löwenanteil der Zeit wird wohl für das Lesen aus dem EEprom draufgehen. Die 10 Schleifeniterationen hat der µC in ein paar µSek durch. Also: Bei Programmstart die Daten aus dem EEprom ins RAM umkopieren und von dort weg arbeiten. Stell dir mal eine andere Frage: musst du die Tabelle eigentlich abgrasen, oder kannst du dir nicht einfach ausrechnen, welcher Tabelleneintrag der richtige ist. So wie ich das sehe hat deine Tabelle lauter 10-er Abstufungen. d.h. wenn du deine Prozentzahl durch 10 dividierst, hast du die Nummer des zuständigen Eintrags. Ich werde allerdings aus deiner ganzen Beschreibung nicht ganz schlau, was du eigentlich machen willst. Daher schlag ich das jetzt einfach mal so vor, ohne zu wissen ob dich das wohin führt. (Anstatt 10 Einträge würde ich aber dann 8 oder 16 nehmen. Die Division wird dann einfacher).
Die Sache mit dem Tabelleneintrag ausrechnen hört sich doch recht gut an. Hab nur leider keine Ahnung wie ich das bewerkstelligen soll. Kannst du mir hierzu einen Denkanstoss geben? Das Programm das ich geschrieben hab funktioniert, so wie es ist, tadellos. Mich stört halt nur die Art wie ich es gelöst habe.
Wie gesagt: Ich bin mir nicht sicher überhaupt zu verstehen, was du da überhaupt machst. Ich denke (und rate) mal: * Du holst dir vom Handy einen String. * In diesem String ist die Prozentzahl in irgendeiner Form codiert. * Du weist wie die Strings aussehen muessen, und hast alle vom Handy benutzten Strings im EEprom abgelegt. * Die Aufgabe ist es jetzt aus dem String abzuleiten ob du die Ladung anstossen musst oder nicht. Nein. Ich verstehs immer noch nicht. Warum musst du alle möglichen Strings abklappern um zu entscheiden ob du jetzt laden musst oder nicht. Die Prozentzahl wird doch an immer der gleichen Stelle im String stehen. Wenn du dir von dort den Teilstring mit der Zahl rausholst und in eine Zahl umwandelst, dann musst du doch nur noch vergleichen ob diese Zahl grösser als 40 ist oder nicht. Oder versteh ich da was grundsätzlich falsch.
Liegst mit deiner Vermutung absolut richtig: die Schaltung macht nichts anderes als auf einen Anruf warten. Bei einem Anruf wird die Rufnummer mit einer zuvor gespeicherten verglichen und bei Gleichheit ein Ausgang geschaltet. Alle 60 Sekunden schicke ich über den UART den Befehl at+cbc zum Handy und frage damit den Ladezustand ab. Als Antwort erhalte ich vom Handy mehrere Linefeeds und Zeilenumbrüche gefolgt von +cbc= 0,xx und wieder einigen Linefeeds und Zeilenumbrüchen. Wobei xx für den Ladezustand steht. Wenn Zeichen auf dem UART empfangen werden, speichere ich diese ab dem Leerzeichen im SRAM ab, bis ich ein Linefeed erhalte. Danach vergleiche ich den String im SRAM mit dem im EEPROM. Da ich die berechtigte Rufnummer mit einem Jumper und einem Anruf programmiere, ist es nötig ab dem Leerzeichen zu speichern. Ich denke, das es die beste Lösung ist, wenn ich den hinteren Teil des Strings auswerte. Vorne ist es eigentlich immer gleich, ausser wenn geladen wird, dann steht eine 1,xx. Mir ist nur noch nicht ganz klar wie ich aus dem eingelesenen String einen Teil rausfischen kann. Darüber werde ich mir Morgen Gedanken machen. Hab heute keinen Kopf mehr dazu. Dir vielen Dank für die Denkanstösse und die Mühe.
Ist doch einfach: Du hast den String. Dann gehst du den Zeichen für Zeichen durch, bis ein ',' auftaucht. Jetzt weist du das danach die dich interessierende Zahl kommt. Die Zahl ist abgeschlossen mit einem LineFeed. Jetzt setzt du die Zahl aus den einzelnen Zeichen zusammen: In PseudoCode: Zahl = 0 while( ZifferCharacter ungleich LineFeed ) Zahl = Zahl * 10 + ( ZifferCharacter - '0' ) ZifferCharacter auf das nächste Zeichen im String Angenommen der Ziffern-String lautet "56" + LineFeed Zahl startet mit 0 ZifferCharacter ist '5', also unglich LineFeed -> ein Durchlauf durch die while Schleife ZifferCharacter, also '5' minus '0' (also die ASCII Codes voneinander abziehen) ergibt 5. Zahl, also 0, mal 10 ergibt wieder 0 plus die 5 macht 5 while Schleife wieder von vorne beginnen: ZifferCharcter ist um ein Zeichen weiter nach rechts gegangen und ist jetzt 6. 6 ist nicht gleich LineFeed, also noch ein Durchgang durch die Schleife: wieder: von '6' die '0' abziehen. Ergibt 6 Zahl, also 5, mal 10 ergibt 50 plus die 6 macht 56. Das nächste Zeichen ist ein LineFeed, damit ist die Bedingung für die while-Schleife nicht mehr erfüllt, sie wird nicht mehr ausgeführt und Zahl enthält das Ergebnis: 56 Aber diesmal als echte Zahl und nicht als String. Eine Multiplikation mit 10 ist einfach zu machen: 2 mal nach links schieben = * 4 die Originalzahl noch mal dazuaddieren = * 5 und nachmal nach links schieben = * 10 Bsp: dezimal 4 binär 00000010 einmal schieben 00000100 zweites mal schieben 00001000 die 4 addieren 00001010 und nochmal schieben 00010100 binär 0010100 ist dezimal ( 8 + 32 ) also 40
Ich seh schon, da gibts für mich noch einiges zu lernen. Meine jetzige Lösung von heute Vormittag sieht so aus: im SRAM steht nach der Abfrage " 0,x0" gefolgt von LineFeed. Da sich nur die erste Stelle nach dem Komma ändert, speichere ich diese mit dem Befehl STS und direkter Adressierung (Speicheradresse +3) in ein Register und ziehe anschliessend $30 ab um den ASCII zu wandeln. Jetzt vergleiche ich ob >= 4 und entscheide dann, ob ich laden muß oder nicht. Ich seh grad das ich mir die 30 abziehen eingentlich sparen kann und gleich auf >= $34 vegleichen kann.
Geht auch. Du hast halt 2 Annahmen getroffen: * Das dich interessierende Zeichen steht immer an Position 3 * Dein Schwellwert ist immer eine 'Zehner-Zahl'. In deinem Fall halt 40 Wenn du mit diesen beiden Annahmen leben kannst, dann lass es so. Annahme 1 ist dabei der dicke Hund, denn du kannst das Format nicht beeinflussen sondern das wird dir vom Handyhersteller aufgedrückt. Zumindest den Teil würde ich durch eine aktive Suche nach dem vorhergehenden ',' ersetzen. So eine Schleife die dir das Zeichen sucht, ist doch kein Problem: 1) Startadresse ins X-Register. 2) Zeichen über das X-Register holen. 3) War es ','? Wenn nein: X Register erhöhen und weiter bei 2 4) X-Register nochmal erhöhen, um an das Zeichen nach dem ',' zu kommen 5) Zeichen über das X-Register holen. 6) Mit $34 vergleichen 7) kleiner? Wenn ja: Ladung einleiten
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.