und:Wie wäre es stattdessen den Countdown zu vergrößern und beim Zuweisen (Countdown = Zähler) einfach ein bissl zu multiplizieren?
Countdown muss dann definitiv Word sein. Oder wie auch immer Bascom ein UInt16 nennt.
Else Countdown = Zeichen * 10
$regfile = "m8def.dat" 'Controllerdefinitionsdatei einbinden $crystal = 8000000 'Systemtakt angeben (Baudrate) $hwstack = 40 'Stacks $swstack = 16 $framesize = 32 $baud = 19200 'Baudrate UART Dim Zeichen As Byte 'UART-Empfang Dim Z As Byte Dim Fla As Byte Dim Pause As Byte Dim Pausex2 As Byte Dim Tov1cnt As Byte Dim Countdown As Word Rot Alias Portd.7 'Namen für LED-Beine Gruen Alias Portc.3 Config Rot = Output 'Ausgänge Config Gruen = Output Rot = 1 'LEDs erstmal an Gruen = 1 'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down Pwm1b = 100 'ADC aktivieren (single conversion, Prescaler Auto, AVcc (INTERN!!!) Config Adc = Single , Prescaler = Auto , Reference = Avcc Do 'Hauptschleife Begin 'erstes Teilprogramm - UART Empfang und auswerten If Ischarwaiting() = 1 Then 'Wenn Zeichen Empfangen Zeichen = Inkey() 'dann Zeichen aus Puffer lesen If Zeichen = "1" Then 'Wenn Zeichen = "1" Rot = 1 '... Print "Led An" Elseif Zeichen = "0" Then 'Wenn Zeichen = "0" Rot = 0 '... Print "Led Aus" Elseif Zeichen = "t" Then 'Wenn Zeichen = "t" Toggle Rot '... Print "Toggle Led" Elseif Zeichen = "?" Then 'Wenn Zeichen = "?" If Rot = 0 Then 'Dann wenn Led aus ist... Print "Led ist aus" Elseif Rot = 1 Then 'sonst wenn Led an ist... Print "Led ist an" End If Elseif Zeichen = 0 Then 'bei 0x00 PWM deaktivieren Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect Elseif Zeichen = 255 Then 'bei 0xFF PWM aktivieren Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down Else Countdown = Zeichen * 60 Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down End If End If 'zweites Teilprogramm - LED durch timer blinken lassen If Tifr.tov1 = 1 Then 'wenn Timer übergelaufen ist Set Tifr.tov1 'Überlaufflag zurücksetzen Incr Tov1cnt 'überlaufzähler inkrementieren If Pause = Tov1cnt Then 'entspricht dem 2ten "waitms pause" Fla = Rnd(200) Fla = Fla + 55 Pwm1a = Fla End If If Pausex2 = Tov1cnt Then 'entspricht dem ersten "waitms pause" Pwm1b = 255 - Fla Pause = Rnd(10) Pause = Pause * 6 Pausex2 = Pause Shift Pausex2 , Left 'pausex2=pause*2 Tov1cnt = 0 End If Incr Z If Z = 245 Then 'Überläufe zählen (245) Z = 0 'Zähler zurücksetzen Toggle Gruen 'LED toggeln If Countdown = 0 Then Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect Else Decr Countdown End If End If End If LoopWie geht es nun weiter?
Ich habe das schon öfters gelesen. Was ist das?Polling
Nur zu Interrupts:
Im Moment nutzt du Polling. Du hast eine Anwendungsschleife die konstant durchläuft. Darin sind Teilprogramme die nur dann ausgeführt werden wenn eine Bedienung erfüllt ist (IsCharWaiting, Tifr.tov1 = 1, ...). Wenn nichts davon erfüllt ist startet die Schleife von vorne und fragt wieder den Zustand ab (=Polling, also abfragen / ziehen des Zustandes). Sorgt aber auch für 100% CPU Last und somit hohen Stromverbrauch*.
Bei Interrupts ist es fast das Selbe, nur dass du nicht abfragst sondern Routinen hast die automatisch aufgerufen werden, von der Hardware. Deine Hauptschleife, da gibt es 2 Möglichkeiten.
Möglichkeit 1:
Du behandelst alles in der Interrupt Routine selbst, also alles was dann ausgeführt werden soll.
Das hat aber Nachteile sollte hier viel (zeitintensiver) Code laufen, wie z.B. Schreiben auf ein LCD. Es kann nur ein Interrupt gleichzeitig arbeiten (nicht ganz richtig, reicht aber erst mal). Beispiel, dein ADC hat einen neuen Wert fertig, Interrupt läuft, schreibt auf ein LCD. Aber währenddessen treten 20 Timer Events auf. Blöd, weil die verpasst du währenddessen.
Möglichkeit 2:
Du setzt in der Interrupt Routine nur ein Flag, welches in der Hauptschleife abgefragt wird. Dort, also losgelöst vom Interrupt, wird dann der Code ausgeführt. So würde der ADC Code in der Hauptroutine (unterbrechbar) ausgeführt werden und den Timer nicht beeinflussen.
Wie auch immer, wenn man mit Interrupts arbeitet nutzt man auch den Sleep Befehl. Damit wird die CPU schlafen gelegt wenn die Hauptschleife fertig ist. Geweckt wird er wieder durch Interrupts. Es wird also nach Sleep weiter gearbeitet.
Allerdings bleibt der Code selbst größtenteils gleich, er ist nur anders angeordnet.
*hoher Stromverbrauch ist bei AVR's natürlich relativ zu sehen, aber bei batteriegetriebenen Anwendungen ist das durchaus relevant.
Wie geht es nun weiter?
Die Steuerung geht immer noch über UART.
So sicher bin ich auf keinen Fall.Eigentlich solltest Du das Problem jetzt also selbst angehen können...
' Die Controller Initialisierung Main: ' Die Haupt Anwendungsschleife If Bedienung1 = 1 Then Gosub Bedienung1Erfuellt If Bedienung2 = 1 Then Gosub Bedienung2Erfuellt 'Sleep ' Controller in Sleep Mode versetzen -- machen wir später 'Reset Watchdog ' Watchdog zurücksetzen -- machen wir später Goto Main Bedienung1Erfuellt: ' Tu was Return Bedienung2Erfuellt: ' Tu was Return
Das mache ich immer, nach einem Erfolgreichen Teilabschluß, von NoEcho bis Poti und letztes Countdown.Speicher dir dein Programm erst mal ab, nicht dass es nachher vermurkst ist.
$regfile = "m8def.dat" 'Controllerdefinitionsdatei einbinden $crystal = 8000000 'Systemtakt angeben (Baudrate) $hwstack = 40 'Stacks $swstack = 16 $framesize = 32 $baud = 19200 'Baudrate UART Dim Zeichen As Byte 'UART-Empfang Dim Z As Byte Dim Fla As Byte Dim Pause As Byte Dim Pausex2 As Byte Dim Tov1cnt As Byte Dim Countdown As Word Ddrc = &B_00_0000 Portc = &B11_1111 Ddrd = &B_1111_1111 Portd = &B0000_0000 Rot Alias Portd.7 Blau Alias Portd.6 Taster Alias Pinc.3 Rot = 0 Blau = 0 Main: ' Die Haupt Anwendungsschleife If Taster = 0 Then Gosub Bedienung1erfuellt If Taster = 1 Then Gosub Bedienung2erfuellt 'Sleep ' Controller in Sleep Mode versetzen -- machen wir später 'Reset Watchdog ' Watchdog zurücksetzen -- machen wir später Goto Main Bedienung1erfuellt: Rot = 1 Blau = 0 Return Bedienung2erfuellt: Rot = 0 Blau = 1 Return