Bascom Led matrix

gino

Neues Mitglied
06. Dez. 2013
27
0
0
Vaihingen Enz
Sprachen
  1. BascomAVR
Hallo und auch von mir ein gutes neues jahr.

Nun mal ein direkte frage, ich versuche das Thema led matrix mit multiplex zu verstehen.
Aber irgendwie hab ich es in Grundzügen verstanden aber es hat noch nicht klick gemacht.

Ich werde erst mal eine kleine matrix 8x4 versuchen am ende soll mal ne 12x12 rauskommen.

Kennt jemand eine gute erklären zu dem thema. Oder beispiele etc.

Super danke gruss.
 
Hi Gino,

Nun mal ein direkte frage, ich versuche das Thema led matrix mit multiplex zu verstehen.
Aber irgendwie hab ich es in Grundzügen verstanden aber es hat noch nicht klick gemacht.
...
Kennt jemand eine gute erklären zu dem thema. Oder beispiele etc.

sieh dir einen Fernseher an. Der ist quasi ein großes Multiplex-Display.
Es wird die erste Zeile angezeigt, dann wird die zweite Zeile angezeigt, dann die dritte, ...
Wenn man unten fertig ist, dann wird oben wieder angefangen.

Bei ner LED-Matrix macht man es beinahe genauso. Die erste LED-Zeile wird angezeigt, dann die zweite, dann die dritte.

Bei 7-Segment-Multiplex macht man es auch so. Erst die LEDs der ersten Stelle, dann die LEDs der zweiten, dann die dritte, ...

Ist eigentlich garnicht so schwer. Wenn man das schnell genug macht, dann sieht es für das Auge so aus als wenn alles gleichzeitig leuchtet.

Im Grunde hat man also ein Gitter mit Zeilen und Spaltenleitungen wo an den Kreuzungspunkten die LEDs zwischen den Zeilen und Spalten liegen. Ein Kreuzungspunkt mit einer LED. Man kann auch Kreuzungspunkte ohne LED lassen. Dann leuchtet an der Position eben nix.

Der gleiche Kram genau umgekehrt wird bei einer Matrixtastatur angewendet.

Gruß
Dino
 
Wo multiplexen

Moin, danke für die antworten.
Zum ersten ich programmiere in bascom.

Zum zweiten die idee von multiplexen ist mir klar, meine ersten tests sind auch gar net so schlecht.

Wo baue ich das eigentliche multiplexen ein, in die haupt schleife oder in einen timer interrupt.


Gruss gino.
 
Hi Gino,

Wo baue ich das eigentliche multiplexen ein, in die haupt schleife oder in einen timer interrupt.

also ohne Timer geht es zwar aber es ist dann stark abhängig von den Aktionen im Hauptprogramm. Dann sollte man schon sehr genau und gut designen damit die Helligkeit gleich bleibt und es sauber läuft. Für ests geht das aber für nen vernünftiges Programm würde ich einen Timer vorziehen.

Deine Timerroutine für das Multiplexing darf aber auch nicht ellenlang werden. Da mußt du auch sehen was da unbedingt rein muß und was man anders anordnen kann. Sonst könnte es passieren das sich deine Timerinterrupts selber überholen. Es wird dann zB ein neuer Interrupt ausgelöst wenn du noch in der ISR bist. Damit verlierst du Interrupts, es wird ungleichmäßig und du wirst in der Hauptroutine keine Zeit mehr für andere Sachen haben weil du sofort wieder rausgerissen wirst.

Gruß
Dino
 
Hmm... ich denke, die Frage war anders gemeint:
Soll das Multiplexing direkt mit in der ISR des Timers erfolgen, oder soll im Hauptprogramm auf 'ne Timerinterrupt-generierte Zeitbasis reagiert/gepollt werden.

Hmm... ich würde den Timer im PWM und CTC verwenden - also frequenzkorrektes PWM. Im Überlauf werden die Daten der einzelnen Dioden auf die Pins geschaltet, und die jeweils nächste Zeile (oder Spalte, je nachdem wierum mans betrachtet) mit Strom versorgt. In der OC-ISR werden alle Spalten (oder eben Zeilen) abgeschaltet (also die Anoden).
Dann kann die Gesamthelligkeit über den PWM nochmal gedimmt werden. Außerdem könnte man bereits in der ISR des OutputCompareMatches die Kathoden der LEDs beschalten - die Anoden liegen durch den PWM ja da auf Gnd...

Aber das kommt dann ganz auf Deine Beschaltung der Dioden an:
Anzahl der Zeilen und Spalten
treibt de Controller die Zeilen/Spalten direkt (ok, ein Transistor/FET zählt hier nicht), oder seriell über ein Schieberegister?
Wenn Schieberegister, je eines für Zeilen und Spalten, oder eins für alles?

Generell einfacher ist es, wenn Du in einer Dimension 'n (ganzes) vielfaches von 8 hast - weil Deine Pixeldaten ja in Bytes gespeichert werden.
Im SRAM legst Du Dir dann halt einen Bereich als Abbild der Pixeldaten fest - VideoRAM (VRAM) sozusagen. In Bascom einfach ein Array of Byte oder so.

Das Schalten der LEDs sollte jetzt also relativ flott in den ISRs erfolgen, die Bilddaten selbst kannst Du im Hauptprogramm an das Array füttern lassen.
 
Danke lotadac, das meinte ich das, ich bin mir unsicher wo ich was machen soll.

Wenn ich dich richtig verstehe, erstelle ich im hauptprogramm die daten, woher auch immer.
Und schalte die matrix im isr eines timers.

Pro isr alle zeilen oder immer nur eine zeile weiter.
Wir reden hier von 12x12 leds, eventuell mal duo leds.
Ich möchte eigentlich die spalten per schieberegisterr und die zeilen direkt bzw. Transistor schalten.
So glaube ich das ganze dann auch verstehen zu können.


Was das dann wird ist ja bis jetzt noch egal.

Danke für die hilfe.
 
Das meinst Du jetzt mit Duo-LEDs? Doppelleds mit 3 Beinen (und dann je common Kathode oder Anode), oder mit 2 Beinen, antiparallel geschaltet?

Zu der Sache mit den Schieberegistern:
-warum dann nicht gleich eines für die Zeilen, eines für die Spalten?
-welche Schnittstelle für die Register? mMn sollte HW-SPI am einfachsten und(!) schnellsten zu realisieren sein (TWI wäre zwar unter Bascom auch simpel, aber durch das interne Protokoll dauert es mMn länger).
-ggf müssen natürlich mehrere Register für eine Dimension kaskadiert werden (12 LEDs)
Hmm... generell gibts ja für solche Zwecke spezial-ICs - der Aufwand schreit ja förmlich nach diesem Holtek(?), den Dirk mal im Shop hatte...
(Oder nach diesen RGB-LEDs mit internem Controller...)
Andererseits, gehts hier ja ums Hobbybasteln...

Wir (ich zumindest) werfen Dir hier derzeit nur Vorschläge zu, was Du davon dann verwenden willst, und inwiefern Du weitere Hilfe von uns brauchst, mußt Du sagen...
Wenn Du Dich für einen Weg entschieden hast, gib uns zum weiterdiskutieren 'n Schaltplan - und vor allen Dingen mal den verwendeten Controller.

So auf die schnelle könnte man einfach 2 Bytes pro Spalte fürs "VideoRAM" vorsehen - also ein Array of Word (gibts sowas bei Bascom?) mit 12 (Doppel-)Zellen - 24 Bytes. da werden dann allerdings 12 halbe Bytes nicht verwendet...
Bei den Dopelleds dann das doppelte - individuelles Dimmen wäre aber erstmal noch nicht drin... nur halt die "Farbe" als ganzes...

Jetzt bist Du wieder dran...

Nachtrag: Holtek... der wars...
 
hallo, danke,

also das mit den duo leds ist erstmal nur sience fiction.

wir reden also von 12x12 leds, an einem atmega8.
die spalten will ich mit 2 74hc164 (sind grad greifbar) und die zeilen direkt oder Transistor.

Ich brauche also 1 pin für die Spalten und 12 für die zeilen.

das ganze wäre dann ja auch für 16x12 LEDS zu verwenden.

das ganze soll dann ne Uhr oder ein Thermometer oder hübsche muster anzeigen, mal sehen.


mir ist grad der wichtig, wo ich was mache, das multiplexen in einen ISR vom Timer finde ich gut,
hier wird dann aber nur immer eine zeile angezeigt, oder die ganzen 12 ??

ich hab noch nicht so ein Gefühl was wie lange dauert. (bin ja noch Neuling)

Meine jetzige Idee ist im der hauptscheife die Daten zu erstellen je zeile und in ein Wordarray zu schreiben, und dieses dann im Timer isr auszugeben.

wird das schnell genug, wenn ich im ISR alle 12 zeilen ausgeben ??

Gruß gino
 
Hi,

wir reden also von 12x12 leds, an einem atmega8.
die spalten will ich mit 2 74hc164 (sind grad greifbar) und die zeilen direkt oder Transistor.
bei 12 LEDs pro Zeile solltest du schon nen Transistor verwenden. Andernfalls must du den Strom recht stark runterschrauben (20mA max pro Pin / 12 LEDs = 1,6mA pro LED :p)

Ich brauche also 1 pin für die Spalten und 12 für die zeilen.

das ganze wäre dann ja auch für 16x12 LEDS zu verwenden.
:confused: hä? :confused:
Du brauchst für die 12 Zeilen genau 12 IO-Pins und für die 12 Spalten nochmal 12 IO-Pins. Ob die nun vom Atmel oder vom Schieberegister kommen ist erstmal egal.

Wenn du zB die Spalten vom Schieberegister versorgst, dann brauchst du 12 IOs vom Atmel für die Zeilen und auch noch mindestens Clock/Daten für die Schieberegister.

Gruß
Dino
 
guten abend,

wieso brauch ich für die spalten mit den Schiebe Registern 12 IO Pins vom atmel, die Schiebe Register werden doch seriell "befüllt".
das mit dem clk ist allerdings richtig. also 2 Pins für die spalten und 12 für die zeilen.


In Summe für die Matrix 12x12 io Pins aber eben nur 14 vom atmel.



gruß




mein erster test mit der 8x4 Matrix und timer1 sieht schon gar net so schlecht aus. was das Ergebnis angeht :))
wie meint Ihr das mit PWM um die Helligkeit zu regeln ??

wo ist im IE10 der Butten für Code einfügen ???

'Meine erste matrix
'ATMEGA8 mit 8mhz int quarz

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 100
$swstack = 100
$framesize = 100

'-------------- ports init --------------------- '
Lcdport Alias Portb
Matrixsp Alias Portd
Config Matrixsp = Output
Matrixzei Alias Portc
Config Matrixzei = Output
Taster1 Alias Pinb.6
Config Taster1 = Input
Portb.6 = 1
'------------------timer init--------------------
Config Timer1 = Timer , Prescale = 1
On Timer1 Isr1
Enable Timer1
Enable Interrupts



'------------------lcd init -----------
Config Lcdpin = Pin , Db4 = Lcdport.3 , Db5 = Lcdport.2 , Db6 = Lcdport.1 , _
Db7 = Lcdport.0 , E = Lcdport.5 , Rs = Lcdport.4

Config Lcd = 16 * 1
Cursor Off , Noblink

Dim Ledmuster(4) As Byte

Ledmuster(1) = &B01101101
Ledmuster(2) = &B10101011
Ledmuster(3) = &B11000111
Ledmuster(4) = &B11101111

Dim Zeilen(4) As Byte

Zeilen(1) = &B00000001
Zeilen(2) = &B00000010
Zeilen(3) = &B00000100
Zeilen(4) = &B00001000

Dim Sz As Byte
Dim Zz As Byte

Sz = 1
Zz = 1

'---------------------------------------------------

Cls
Lcd "hallo duda" ' nur um zu sehen ob sich was tut


Do




Loop

End




Isr1:

Matrixzei = Zeilen(zz)
Matrixsp = Ledmuster(sz)
Incr Zz
Incr Sz
If Zz = 5 Then Zz = 1
If Sz = 5 Then Sz = 1
Timer1 = 20000





Return
 
Hi,

wieso brauch ich für die spalten mit den Schiebe Registern 12 IO Pins vom atmel, die Schiebe Register werden doch seriell "befüllt".
das mit dem clk ist allerdings richtig. also 2 Pins für die spalten und 12 für die zeilen.

In Summe für die Matrix 12x12 io Pins aber eben nur 14 vom atmel.
Also ob man nun die Spalten vom Atmel und die Zeilen vom Schieberegister ansteuern läßt oder andersrum (Zeilen vom Atmel und Spalten vom Schieberegister) ist eigentlich Jacke wie Hose ;) Es kommt immer auf mindestens 14 IOs am Atmel raus.

Theoretisch könnte man sich noch einen Pin fürs Schieberegister sparen (hab grade so eine Idee) aber das ist dann ... etwas komplizierter :rolleyes:

Man könnte auch für Zeilen und Spalten Schieberegister einsetzen. Das spart dann noch mehr Pins :D Es gibt da viele Möglichkeiten für eine Umsetzung.

Gruß
Dino
 
Irgendwie habt ihr dasselbe gemeint, aber trotzdem etwas aneinander vorbei diskutiert...
soweit sieht das doch schon mal ganz gut aus...

Dino, Deine Idee hat nicht zufällig was damit zu tun, 'ne irgendwie(?) einmal ins Schieberegister gelangte 1 von vorn bis hinten durchzuclocken? Und den 12ten Ausgang dann auf den Eingang zu legen?

Zu Ginos Programm:
Du verwendest den Timer ja im normal Mode (der Timer läuft von 0 bis 65535, danach auf 0 über. Dabei erfolgt ein IRQ. In der ISR setzt Du den Timer dann jedesmal auf 20000 vor - effektiv läuft der Timer also in etwa von 20000 bis zum Überlauf.)
Du kannst den Timer aber auch automatisch bei Timerwert = Registerwert überlaufen lassen. Dieser Mode heißt CTC. Clear Timer on Compare Match. Allerdings erfolgt hier nicht der Überlauf-Interrupt (stattdessen der Interrupt des Matches).
Als Vergleichsregister stehen Dir das InputCaptureRegister und das OutputCompareregisterA zur Verfügung.

Ähnlich dem CTC kannst Du auch einen (frequenzkorrekten) fastPWM-Mode verwenden. Schau Dir das mal im Datenblatt des Controllers an (Timer1-Modes of Operation).
Dann könntest Du bei jedem Überlauf (eines der Register legt den Überlauf fest) eine Zeile anzeigen lassen (Zeilen und Spalten wie gehabt mit Werten aus den Arrays beschreiben). In der ISR des CompareMatches des anderen Registers setzt Du die Zeilen alle auf 0 (Matrixzei=0). Das inkrementieren und rücksetzen der Indizees kannst Du sinnig auf beide ISRs verteilen. Effekt ist, daß nach dem erreichen des Matches alle LEDs aus gehen, also gedimmt wird.

Kommst Du noch mit?


Nachtrag: den code-Button hast Du nur im erweiterten Editor (# oben rechts)
Beim bearbeiten von vorhandenen Beiträgen wird erstmal nur der einfache Editor verwendet... Das kannst Du aber unten rechts am Rand des Eingabefensters (Frames?) umschalten...
 
Hi,

Dino, Deine Idee hat nicht zufällig was damit zu tun, 'ne irgendwie(?) einmal ins Schieberegister gelangte 1 von vorn bis hinten durchzuclocken? Und den 12ten Ausgang dann auf den Eingang zu legen?

Mist! :rolleyes: erwischt :p

Ich hätte den Dateneingang des Schieberegisters auf eine sowieso benötigte Spaltenleitung vom Atmel gelegt. Dann muß man beim 1-durchtakten nur auf den richtigen Pegel dieser Leitung achten. Sollte aber kein Problem sein :D

Gruß
Dino
 
Ähnlich dem CTC kannst Du auch einen (frequenzkorrekten) fastPWM-Mode verwenden. Schau Dir das mal im Datenblatt des Controllers an (Timer1-Modes of Operation).
Dann könntest Du bei jedem Überlauf (eines der Register legt den Überlauf fest) eine Zeile anzeigen lassen (Zeilen und Spalten wie gehabt mit Werten aus den Arrays beschreiben). In der ISR des CompareMatches des anderen Registers setzt Du die Zeilen alle auf 0 (Matrixzei=0). Das inkrementieren und rücksetzen der Indizees kannst Du sinnig auf beide ISRs verteilen. Effekt ist, daß nach dem erreichen des Matches alle LEDs aus gehen, also gedimmt wird.

Hallo,

Also im pwm mode gibt es comparea und b.
Den bascom code werd ich schon finden.
Ich arbeite also mit zwei isr bei comparea die zeile einschalten und bei b wieder aus.
Die zeit zwischen a und b bestimmt die helligkeit.

Werds mal versuchen, danke.
 
Bascom unterstützt mit diesen config xxx nicht alle Möglichkeiten, die jeder Controller bietet...
(Du kannst aber trotzdem die nötigen Werte in die Konfigurationsregister schreiben - nur eben nicht mit Config)

Mal was generelles zum Timer:
Timer1 ist ein 16 Bit-Timer
Du kannst verschiedene Modes of Operation einstellen (siehe Datenblatt)
Es existieren 3 Register, die beim Increment des Zählregisters (TCNT1 - Bascom nennt es timer1) verglichen werden (können): OCR1A, OCR1B (das sind die beiden OutputCompareRegister, die für HardwarePWM verwendet werden können) und das ICR1 (das InputCaptureRegister - eigentlich ist das sowas wie 'ne Rundenzeit bei 'ner Stopuhr - entsprechend konfiguriert (Operationsmodus) wird, wenn man den entsprechenden Pin (B0=ICP1) "betätigt" der aktuelle Zählerstand (timer1) automatisch in dieses ICR-Register kopiert, während der Timer weiterläuft. Außerdem kann ein Interrupt ausgelöst werden.

In Deinem Code hattest Du die Überlauffrequenz des Timers erhöht (bzw die Reichweite verkürzt), indem Du die ersten 20000 increments übersprungen hattest. Diese Zuweisung (timer1=20000) bei jedem Interrupt kannst Du sparen, indem Du die Reichweite des timers auf 45536 Schritte reduzierst. Du sagst ihm einfach, daß er überlaufen soll, wenn der Timer gleich dem entsprechenden Vergleichsregister ist. im Vergleichsregister steht dann die 45535 (ja, eins weniger - nimms erstmal hin).
Quizfrage1: was passiert, wenn Du im laufenden Betrieb jetzt im Hauptprogramm den Inhalt des Vergleichsregisters (Timerreichweite) änderst?
Als Vergleichregister kannst Du hier nur das OutputCompareRegister1A oder das InputCaptureRegister1 verwenden lassen.

Wenn das soweit umgesetzt wird, ändert sich an Deinem Programm erstmal nicht viel - die Manipulation des Zählers fliegt aus der ISR, weil das ja automatisch geschieht, dafür mußt Du bei der Konfiguration einen anderen Modus wählen, und einmalig den Vergleichswert setzen.

ABER: mit dem Config Timer1=xxx hast Du da keinen Zugriff drauf - Schau Dir mal im Datenblatt des Mega8 das Kapitel für den Timer1 an - insbesondere die Modes of Operation, und die Registererklärung hinterher...
Um das Mysterium mit dem Config Timer1 mal rauszunehmen:
Das Verhalten des Timers wird durch 8 Register manipuliert. 4 davon sind 8-Bit Register, 4 sind 16-Bit-Register (da 16-Bit-Timer). Bascom setzt durch Config blablub halt die entsprechenden Werte in die Register - kennt nur nicht alle Möglichkeiten. Das kannst Du selbst mit dem Datenblatt auch...
Und: keine Panik - Du mußt nicht an alle Register ran - erst recht nicht an alle Bits aller Register...

Wenn Du Dir selbst 'n Überblick verschafft hast, helf ich Dir gern, die Register mal gedanklich auseinanderzunehmen...

Achso, Du kannst natürlich jederzeit sagen "Stopp - interessiert mich alles nicht! Ich bleib bei dem, was Bascom mir mit Config trallala erlaubt!".
Mich hingegen hat es immer interessiert, was im Controller selbst abgeht, was mir die Hardware bietet... Was eigentlich wirklich passiert, wenn man in Bascom irgendwas konfiguriert und/oder startet... Allerdings schweift es damit etwas vom eigentlichen Multiplexing ab - dafür erhältst Du aber auch mehr Möglichkeiten...
Dein Projekt, Deine Zeit, Deine Wahl...
 
guten abend,

danke hat mich schon mal weitergebracht.
mich interressesiert schon was wirklich abgeht, irgendwie habe ich es jetzt sogar hinbekommen, ich kann die Helligkeit mit ocr1b einstellen.

eigentlich wollte ich es aber anderst herum lösen, zuerst die LEDS an, dann aus.
Jetzt bin ich der Meinung, das ich quasi zuerst aus und dann ein schalte.

Ist das egal oder hab ich nen Denkfehler. (siehe Code)

jetzt bin ich grad am überlegen, wie ich die Daten des Arrays elegant auslese bzw. ändere.
z.b. um per taser von römisch I bis römisch 10 zu zählen.
die Daten für das muster lege ich im datenbereich ab:

data Daten für römisch I
data Daten für römisch II
..
..
date Daten für Römisch X

wie hole ich dann die Daten passend aus dem speicher. und wieviel platz für diese Datenmuster habe ich im mega8 eigenltich.

gruß


Code:
'Meine erste matrix
'ATMEGA8 mit 8mhz int quarz

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 100
$swstack = 100
$framesize = 100

'--------------  ports init ---------------------                                  '
Lcdport Alias Portb
Matrixsp Alias Portd
Config Matrixsp = Output
Matrixzei Alias Portc
Config Matrixzei = Output
Taster1 Alias Pinb.6
Config Taster1 = Input
Portb.6 = 1
'------------------timer init--------------------


Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1
On Compare1a Isr1
On Compare1b Isr2
Enable Compare1a
Enable Compare1b
Ocr1a = 600
Ocr1b = 200
Enable Interrupts

'------------------lcd init -----------
Config Lcdpin = Pin , Db4 = Lcdport.3 , Db5 = Lcdport.2 , Db6 = Lcdport.1 , _
   Db7 = Lcdport.0 , E = Lcdport.5 , Rs = Lcdport.4

Config Lcd = 16 * 1
Cursor Off , Noblink


Dim I As Byte
Dim Offset As Byte
Dim Ledmuster(4) As Byte

For I = 1 To 4
Offset = I - 1
Ledmuster(i) = Lookup(offset , Spalten)
Next

Dim Zeilen(4) As Byte

Zeilen(1) = &B00000001
Zeilen(2) = &B00000010
Zeilen(3) = &B00000100
Zeilen(4) = &B00001000

Dim Sz As Byte
Dim Zz As Byte

Sz = 1
Zz = 1

'---------------------------------------------------

  Cls
  Lcd "hallo duda"                                          ' nur um zu sehen ob sich was tut


Do


Loop

End

Isr1:

   Matrixzei = Zeilen(zz)
   Matrixsp = Ledmuster(sz)
   Incr Zz
   Incr Sz
   If Zz = 5 Then Zz = 1
   If Sz = 5 Then Sz = 1


    Return


Isr2:


   Matrixzei = 0


   Return





$data

Spalten:
Data &B01101101 , &B10101011 , &B11000111 , &B11101111
 
Ok, das mit "clear Timer = 1" wird in der Online-Hilfe nur kurz angedeutet, aber nirgends richtig erklärt. Was bewirkt "clear Timer = 0" dann?
Und 'ne Option, die das ICR1 statt des OCR1A verwendet (um beide PWM-Kanäle frei zu haben) finde ich so auch nicht. Egal, ICH kann das ja stattdessene direkt über die I/O-Register machen - und ich weiß dann auch, was wirklich in diesen Registern steht...

Wie ist das jetzt mit Deinem Timer:
  • der zählt (mit Systemtakt/64) von 0 bis 600 hoch
  • bei 200 erfolgt ein Comparematch mit OCR1B
  • bei 201 wird das korrespondierende Interrupt-Flag gesetzt (und somit der Interrupt ausgelöst)
  • in der ISR löschst Du jetzt alle LEDs, und kehrst zum (leeren) Hauptprogramm zurück, währenddessen läuft der Timer weiter
  • bei 600 erfolgt ein Comparematch mit OCR1B
  • bei 601 wird das korrespondierende Interrupt-Flag gesetzt, was hier einerseits den Timer sofort auf 0 setzt (also 601=0), andererseits den entsprechenden Interrupt auslöst
  • in der ISR läßt Du jetzt ein paar LEDs leuchten, und kehrst ins (leere) Hauptprogramm zurück - währenddessen läuft der Timer weiter...

Die LEDs leuchten also solange, wie sich der Timer zwischen dem Überlauf und OCR1B befindet (erst an) - von ORC1B bis Überlauf (OCR1A) sind sie aus (dann aus).
Ein größerer wert im OCR1B hat eine höhere Helligkeit (Leuchtdauer) zur Folge, oder?

Quizfrage2: Wie kehrst Du das um? (also erst aus, dann an)

Dabei fällt mir ein, daß Du Frage 1 noch nicht beantwortet hast: Was geschieht, wenn Du im Programm irgendwann mal den Inhalt von OCR1A veränderst?

Der Mega8 hat (oh welch Überraschung):
aus dem Datenblatt schrieb:
8Kbytes of In-System Self-programmable Flash program memory
Das sind erstmal nur Words. Wenn das Programm also in irgendeiner Speicherzelle landet, wird das dortige Word als Befehl interpretiert, und ausgeführt. Speicherzellen, die vom Programm nie erreicht werden, werden logischerweise nie als Befehl ausgeführt. In diesen Zellen können natürlich irgendwelche Daten stehen (Strenggenommen steht ja immer irgendwas drin - und wenns 'ne 0 ist). Der Controller besitzt einen Befehl, mit das Byte einer beliebigen Flash-Adresse (aus dem program-flash) geladen werden kann. In Deinem Programm nutzt Du das zB bei lookup usw. Dort wird der Inhalt dann aber auch gleich an eine Variable weitergereicht - effektiv werden also Daten aus dem Flash ins SRAM kopiert (Variablen sind ja quasi Zeiger auf Adressen im SRAM).
Mit Zuweisungen wie Varname=Wert hast Du was ähnliches. Mit dem Dim-Befehl sagst Du Bascom ja nur, wieviel Platz die Variable im SRAM verwendet, und hast im Programm 'n Namen für den eigentlichen Speicherplatz. Erst die Zuweisung erzeugt dann den Code, im Flash erscheint dann eine Befehlsfolge, die den Wert (als Konstante) in's SRAM kopiert. Der Wert steht mitsamt der Befehlsfolge im Flash. Allerdings in ... ähm ... gepackter Form. Wenn ich das jetzt auch noch ausführen soll, kannst Du auch bald auf Assembler umsteigen, gelt TommyB?!
 
...
danke hat mich schon mal weitergebracht.
mich interressesiert schon was wirklich abgeht
...
Das interpretiere ich jetzt mal als Aufforderung, was zum Timer (speziell zum Timer1 Deines Mega8) zu schreiben.
Wie gesagt wird das Verhalten des Timers über 8 I/O-Register gesteuert und ausgewertet. diese sind:
  • TCNT1 - Timer/Counter 1 Register
    Das ist der eigentliche Zähler, und da es sich im einen 16bit Timer handelt, also bis 216 gezählt werden können muß, handelt es sich um ein 16bit-Register (ein Word, 2 Byte-Register)
    Du hast auf dieses Register bereits über "Timer1=..." zugegriffen, eigentlich müßte auch TCNT1 gehen (wäre logischer). Du kannst Lesen und Schreiben.
  • OCR1A - Timer/Counter 1 Output Compare Register A
    Mit dem Wert in diesem Register wird TCNT1 bei jedem Timerschritt verglichen. Bei Gleichheit wird ein Compare Match Event ausgelöst (Flag im TIFR weiter unten), was zur Anforderung eines Interruptes verwendet werden kann, außerdem kann der Output Compare A - Pin durch die Hardware manipuliert werden (Compare Output Modes im TCCR1A weiter unten). Kann den Maximalwert des Timers/Counters festlegen. In einem Operationsmodus (WGM im TCCR1A/B) mit singleSlope entspricht das dem zurücksetzen des TCNT1 ("clear Timer" - der läuft hier auf 0 über), was effektiv die Reichweite des Timers reduziert (->Quizfrage1).
    In einem dualSlope-Modus kehrt der Timer aber an dieser Stelle um - Clear paßt hier also nicht. Die Reichweite wird hier natürlich auch begrenzt (wat ja der Sinn von'nt janze ist)
    Da der gesamte TCNT1-Bereich abgedeckt werden können soll, handelt es sich auch hier um ein 16bit-Register. Du greifst bereits mit OCR1A darauf zu. Kann gelesen und beschrieben werden
  • OCR1B - Timer/Counter 1 Output Compare Register B
    Ist eigentlich dasselbe wie beim A-Kanal, außer daß dieses Register NICHT zur Festlegung des maximalen Zählerwertes (Überlauf-/Umkehrpunkt) verwendet werden kann.
  • ICR1 - Timer/Counter 1 Input Capture Register
    Normalerweise nimmt dieses Register eine Kopie des derzeitigen TCNT1-Registers auf, sobald ein InputCaptureEvent am InputCapturePin1 (ICP1) erfolgt (siehe auch ICES1 in TCCR1B) Der AnalogComperator kann da zwar auch noch ein Wörtchen mitreden, aber das nur am Rande. Dieses ImputCaptureEvent kann natürlich auch einen Interrupt anfordern (-> TIFR)
    Alternativ kann das Register aber auch verwendet werden, den Maximalwert von TCNT1 zu begrenzen (Überlauf-/Umkehrpunkt) - dann löst die Gleichheit mit dem TCNT1 das CaptureEvent aus, und kann (zusätzlich) zur Interruptanforderung verwendet werden. In diesen Operationsmodi ist das ganze allerdings nicht mehr an den ICP1 gekoppelt. Alternativ halt.
    Logischerweise ist auch ICR1 ein 16bit-Register, welches gelesen und beschrieben werden kann.
  • TCCR1A - Timer/Counter 1 Control Register A
    Wie man dem Namen bereits entnehmen kann, steuern die Bits dieses Registers das Verhalten des Timers. die Bits sind:
    • COM1A1|COM1A0 - Compare Output Mode for Channel A
      Diese 2 Bits legen das Verhalten des OC1A-Pins beim CompareMatch (TCNT1=OCR1A) fest. Das ganze ist auch abhängig vom Operationsmodus. Mit 2 Bits sind das 22=4 Möglichkeiten. Salopp (vereinfacht, aber stimmt nicht ganz) gesagt kannst du den Pin in Nicht-PWM-Modi als normalen Pin belassen (TimerUnit hat keinen Einfluß drauf), ihn bei jedem Match toggeln lassen, ihn setzen lassen oder löschen. In SingleSlope-PWM-Modi wird im Überlauf dann die je komplementäre Aktion ausgeführt, beim setzen/löschen. PWM halt. Bei den DualSlope-Modi erfolgt die komplementäre Aktion dann, wenn TCNT beim zurückkommen wieder durch OCR1A läuft.
    • COM1B1|COM1B0 - Compare Output Mode for Channel B
      Im wesentlichen dasselbe, nur eben für den OC1B-Pin, ausgelöst durch das OCR1B=TCNT1 Match
    • FOC1A - Force Output Compare for Channel A
      Wird eine 1 in dieses Bit geschrieben, während der Timer in einem Nicht-PWM-Modus ist, reagiert der OC1A-Pin, als wenn gerade ein CompareMatch erfolgt. Dabei wird aber nicht der eventuell aktivierte Compare-Interrupt ausgelöst (klar TCNT1 ist ja ungleich OCR1A) - ich habs noch nie gebraucht. Liest man dieses Bit, erhält man immer eine 0 (writeOnly)
    • FOC1B - Force Output Compare for Channel B
      Dasselbe für den OC1B-Pin
    • WGM11|WGM10 - Waveform Generation Mode
      Diese beiden Bits legen mit 2 weiteren Bits aus TCCR1B fest, wie der Timer überhaupt zählt (Überlauf (single Slope), oder hin und zurück (dual Slope), wo er Überläuft, was die COM-Bits (oben) konkret bewirken usw...)
      Das sind die "Operationsmodi".
      Timer1 des Mega8 kann 15 verschiedene (weswegen 4 Bits zur Auswahl nötig sind) - ich erspare mir (und Euch) hier mal, die Alle aufzuführen - reiche das gerne aber in 'ner weiteren Antwort nach. Nachtrag: hier
  • TCCR1B - Timer/Counter 1 Control Register B
    Das zweite Steuerregister, hier befinden sich die Bits:
    • ICNC1 - Input Capture 1 Noise Canceller
      Eine 1 in diesem Bit aktiviert einen Filter (digitaler Hardware-Tiefpaß?) zwischen dem ICP1-Pin und dem Input Capture Unit, um Rauschen zu unterdrücken
    • ICES1 - Input Capture 1 Edge Select
      Legt fest, bei welcher Flanke am ICP1 ein InputCaptureEvent getriggert wird (0=fallend, 1=steigend) - natürlich nur wenn das nicht durch einen Operationsmodus ausgehebelt wird, wo ICR den maximalen Timerwert begrenzt.
    • ungenutzt
    • WGM13|WGM12 - Waveform Generation Mode
      Wurde bereits bei TCCR1A angedeutet - hier die anderen beiden Bits
    • CS12|CS11|CS10 - Clock Source
      Legt die Taktquelle für den Timer fest. 3 Bits erlauben 8 diskrete Vorgaben:
      • 0 - Timer steht
      • 1 - Systemtakt/1 (Prescaler=1)
      • 2 - Systemtakt/8 (Prescaler=8)
      • 3 - Systemtakt/64 (Prescaler=64)
      • 4 - Systemtakt/256 (Prescaler=256)
      • 5 - Systemtakt/1024 (Prescaler=1024)
      • 6 - fallende Flanke am T1-Pin
      • 7 - steigende Flanke am T1-Pin
    • 6 und 7 sind quasi Counter Modi.
  • Was in den beiden TCCR1 stehen soll, hattest Du Bascom im Prinzip mit "Config Timer1=..." gesagt. Start Timer1 bzw Stop Timer1 manipulieren die CS1x-Bits in TCCR1B, soweit klar?
  • TIMSK - Timer/Counter Interrupt Mask Register
    In Register können alle Interrupts aller Timer (des Mega8) freigegeben werden (ist bei anderen Controllern aber auch anders). Für Timer1 relevant sind:
    • Bit5 = TICIE1 - Timer 1 Input Capture Interrupt Enable
      Interrupt beim Input Capture Event
    • Bit4 = OCIE1A - Output Capture 1 A Interrupt Enable
      Interrupt beim Output Capture Event von Kanal A
    • Bit3 = OCIE1B - Output Capture 1 B Interrupt Enable
      dasselbe für Kanal B
    • Bit2 = TOIE1 - Timer 1 Overflow Interrupt Enable
      Interrupt beim Überlauf
  • Macht den jeweiligen Interrupt scharf (natürlich nur mit dem globalen Interruptbefähigungsbit im SREG (enable interrupts)).
    Diese Bits werden von Bascom durch "enable ..." gesetzt, "disable... sollte sie wieder löschen, um den Interrupt zu entschärfen.
  • TIFR - Timer/Counter Interrupt Flag Register
    Die Bits dieser Register werden durch die Hardware gesetzt wenn das korrespondierende Event eingetreten ist. Die Bitpositionen und Namen sind entsprechend denen im TIMSK für die Bits 5, 4, 3 und 2 ICF1 (Input Capture Flag1), OCF1A (Timer 1 Output Compare Flag for Channel A), OCF1B (dito Kanal B) und TOV1 (Timer/Counter 1 Overflow Flag).
    Die entsprechende Controllerhardware beschreibt die Bits beim entsprechenden Event mit einer 1. Ist der Interrupt befähigt (und auch global), wird er (bzw die ISR) ausgeführt. dabei wird automatisch das Flag zurückgesetzt. Wird der Interrupt nicht verwendet, kann man das Flag trotzdem lesen, um auf das Event reagieren zu können. Um das Flag löschen zu können, muß eine 1 in das Bit geschrieben werden
So, das wars erstmal - wenn hier irgendwo was nicht stimmt, bin ich für Korrekturen gerne offen...
(Dino von der Hardware her, und Cassio was Bascom betrifft, denk ich mal)
 
Zuletzt bearbeitet:
wow, also danke für die Ausführung, ich behaupte mal du hast das wirklich verstanden und nicht nur auswendig gelernt, liest sich zumindest so.
(die meisten menschen die ich kenne machen das übrigens umgekehrt)

also ich habs bis jetzt weder ganz verstanden noch kann ich's auswendig, aber wird ja noch kommen.

ich versuch mal das zusammenzufassen, was ich verstanden habe.

clear timer 1 setzt den timer bei ocr1a wieder auf null, ist mir bereits aufgefallen, wenn ich dieses auf 0 stelle waren mir die isr zu langsam.
ist mir nun auch klar, ich habe in summe bei timer1 3 isr Möglichkeiten, das wird mir nun klar.

1. compare1b (timer läuft aber weiter)
2. compare1a (timer kann weiterlaufen ,tuts bei mir aber grad net)
3. timer1 Overflow.

da mir nun die Reihenfolge der timer viel klarer ist werde ich es bestimmt hinbekommen, die Matrix zu drehen, also zuerst an dann aus, wäre mir ja auch irgendwie lieber.

meine hauptschleife ist noch leer, weil ich ja noch net weiß was ich dann tun will, vermutlich ne worduhr, also muss ich noch dcf auswerten und die Uhrzeit in ein led muster umsetzten.
ich poste den code wenn ich meine isr angepasst habe.

gruss
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)