GLCD und I2C (TWI) am Atmega32

Salami

Neues Mitglied
16. Feb. 2012
22
0
0
Sprachen
Hallo und Guten Abend,

meine Frage bezieht sich auf den Atmega32-16. Ich habe ein GLCD (64x128) am Controller hängen. An den Pins 14...21 (Port D) liegen die 8 Datenleitungen, an den Pins 22...27 (Port C) die Control-Leitungen. Nun möchte ich über I2C eine DS1307 anschließen. Ich habe die Control-Leitungen um 2 verschoben, so dass PortC.0 (SCL) und PortC.1 (SDA) frei werden. Dann habe ich meine RTC-Routine ins Programm implementiert, und nun geht das GLCD nicht mehr. Einzeln funktioniert alles: die RTC-Routine liest den Dallas DS1307 korrekt aus, mein "normales" Programm mit dem GLCD funktioniert auch prima ohne die RTC-Zeilen.

Gibt es da einen Konflikt, wenn ich den PortC mit dem I2C UND den GLCD-Contol-Leitungen belege? Ich frage deshalb, weil ich nicht erst alles umbauen will, nur um festzustellen, dass es doch "nur" ein Codefehler war. Wenn allerdings etwas gegen die aktuelle Verdrahtung spricht, muss ich wohl oder übel eine neue Platine erstellen.


Vielen Dank, DW
 
Hallo Salami!

Willkommen im AVR-Praxis Forum! :ciao:

Also generell spricht nichts dagegen, dass du die Steuerpins des GLCD`s am AVR zwei Pins "weiter schiebst".
Die JTAG Schnittstelle sollte wohl schon deaktiviert sein, sonst hätte es vorher bestimmt auch nicht funktioniert.

Einen Uhrenquarz hast du aber nicht auch noch an den Pins C6 und C7?
Oder hast du ggf. die Softclock aktiviert und das Programm erwartet einen Uhrenquarz an den Pins...... und bekommt dafür das GLCD? :wink:

Kannst du vielleicht mal einen Anschlussplan und deinen derzeitigen Programmcode hier einstellen?
Das hilft meistens bei der Fehlersuche ungemein. :cool:

In welcher Sprache programmierst du denn eigentlich? BASCOM oder C ?

Grüße,
Cassio
 
Hi,

Gibt es da einen Konflikt, wenn ich den PortC mit dem I2C UND den GLCD-Contol-Leitungen belege? Ich frage deshalb, weil ich nicht erst alles umbauen will, nur um festzustellen, dass es doch "nur" ein Codefehler war. Wenn allerdings etwas gegen die aktuelle Verdrahtung spricht, muss ich wohl oder übel eine neue Platine erstellen.
Ähhhh ... jaaaaahhhh ... Keine Ahnung :confused:

Ohne den kleinsten Fetzen Code oder einer Info mit was du für einer Sprache programmierst und nem Schaltplan oder nem Foto vom Aufbau oder was auch immer kann man da eigentlich nur in die Glaskugel schauen oder im Kaffesatz rühren.

Dieser erste Beitrag war für die Lösungsfindung leider nicht wirklich gewinnbringend.

Gruß
Dino
 
Hallo,

ich danke Euch erstmal für die schnellen Antworten und ja, ich verstehe Eure Reaktion. Ich werde heute noch eine Anschlusstabelle und den Code einstellen und auch die beabsichtigte Funktion erläutern. Ich dachte, dass es auf die Frage >I2C am PortC, darf da noch was anderes höherwertiges am selben Port liegen< eine einfache Antwort gibt. Da dem nicht so ist, stehe ich nun in der Pflicht, etwas Material zu liefern.

Mfg, DW
 
Hi,

Ich dachte, dass es auf die Frage >I2C am PortC, darf da noch was anderes höherwertiges am selben Port liegen< eine einfache Antwort gibt.
das einzige was beim Mega32 am PortC sonst noch draufliegt ist der JTAG-Anschluß (PC2-5). Du mußt also bei den Fuses JTAG abschalten um die entsprechenden Pins frei zu bekommen. Aber ohne Schaltplan weiß ich ja noch nichtmal ob du die Pins überhaupt benutzt hast.

Du mußt immer davon ausgehen das wir dir ja nicht über die Schulter geschaut haben. Und je weniger Infos du rausgibst desto länger dauert die Fehlersuche weil wir ja nicht wissen könne was du da so getrieben hast.

Gruß
Dino
 
Hallo Cassio und Dino03,

gestern war meine Zeit zu knapp. Aber jetzt...

Ein paar Worte zur Funktion: ich baue eine Warmwassersteuerung für einen Boiler mit Zirkulation und Durchlauferhitzer. Der Boiler hat eine eigene elektrische Heizung und soll möglichst gleichmäßig durchgewärmt sein. Wenn er warm genug ist und ein Zeitprogramm die Freigabe gibt, soll die Zirkulationspumpe das Wasser zur Küche fördern. Im Falle einer hohen Entnahme (baden) soll zusätzlich der elektrische Durchlaufheizer mit 7kW zuschalten.

Der sitzt mit im Kreis der Zirkulationspumpe und wird über elektrische Kugelventile zusätzlich in die Hydraulik gebracht. Er soll möglicht wenig laufen und ist vielleicht mal für eine spätere Ergänzung um einen Nachtstrom-Tarifzähler noch sinnvoller einsetzbar. Zur Temperaturmessung benutze ich den Typ AD22100 von Analog Devices. Die Ausgänge schalten über SSD´s von Sharp (S216S02) die Verbraucher wie Heizung, Pumpe, Ventile.

Ich programmiere in Bascom. Zur Frage von Cassio: ohne Quarz und ohne Softclock. Am Atmega32 ist ein 128x64 GLCD angeschlossen, welches symbolisch das Warmwasserschema zeigt und die wichigsten Messwerte bzw. Schaltzustände. Über 3 Tasten ist ein Menü bedienbar, in welchem der eigentliche Sollwert sowie einige Werte (Min-, Max-, Grenzwerte,...) einstellbar sind. Sie werden im EEPROM des Atmega32 abgelegt und bleiben auch bei Stromunterbrechung erhalten.

Die externe RTC (die natürlich einen Quarz hat) soll zur Realisierung des Zeitprogrammes für die Zirkulation dienen.

Zuerst mal ein Bild von der Anlage:
WWB_Schema_V10.PNG

Hier die Anschlussbelegung des Atmega32:
Atmega 32-16 Pinout WWB-Steuerung_V23.PNG

Und hier ist eine Art Programmplan, mit dem ich mich im Bascom-Code gut orientieren kann:
Seite 1
WWB_Programm_V21_01.jpg

Seite 2
WWB_Programm_V21_02.jpg

Vielleicht hilft sowas ja auch jemandem, um sein eigenes Programm zu sortieren, indem er sich den Ablauf per Grafik verdeutlicht. So einen Plan habe ich auch noch für das Menü, in dem ich später direkt am Gerät Werte ändern und wieder abspeichern kann. Das nur nebenbei.

Ich habe durch meine Blödheit einen Teil meines Codes zerstört; den muss ich erst wieder über meinen Programmplan anpassen.

Hier ist nun erstmal der Code der RTC, welcher funktioniert und mir auf dem Display Datum und Uhrzeit ausgibt:

PHP:
$regfile = "m32def.dat"
$framesize = 80
$swstack = 80
$hwstack = 80
$crystal = 8000000

$lib "glcdKS108.lbx"

Config Sda = Portc.1
Config Scl = Portc.0
I2cinit

 Config Graphlcd = 128 * 64sed , Dataport = Portd , Controlport = Portc , Ce = 3 , Ce2 = 2 , Cd = 7 , Rd = 5 , Reset = 4 , Enable = 6


 Setfont Font6x8


Waitms 100
Cls

Dim _weekday As Byte
Dim _day As Byte
Dim _month As Byte
Dim _year As Byte
Dim _sec As Byte
Dim _min As Byte
Dim _hour As Byte

Dim Ds1307w As Byte
Dim Ds1307r As Byte

Ds1307w = &B11010000
Ds1307r = &B11010001

_day = 31
_month = 12
_year = 09
_sec = 50
_min = 59
_hour = 23


_sec = Makebcd(_sec)
_min = Makebcd(_min)
_hour = Makebcd(_hour)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 0
'I2cwbyte _sec
'I2cwbyte _min
'I2cwbyte _hour
I2cstop


_day = Makebcd(_day)
_month = Makebcd(_month)
_year = Makebcd(_year)
'I2cstart
'I2cwbyte Ds1307w
'I2cwbyte 3
'I2cwbyte _weekday
'I2cwbyte _day
'I2cwbyte _month
'I2cwbyte _year
'I2cstop

'--Hauptschleife----------------------------------------------------------------

Do
   I2cstart
   I2cwbyte Ds1307w
   I2cwbyte 0
   I2cstart
   I2cwbyte Ds1307r
   I2crbyte _sec , Ack
   I2crbyte _min , Ack
   I2crbyte _hour , Ack
   I2crbyte _weekday , Ack
   I2crbyte _day , Ack
   I2crbyte _month , Ack
   I2crbyte _year , Nack
   I2cstop

 '--Datum-----------------------------------------------------------------------

   _day = Makedec(_day)
   _month = Makedec(_month)
   _year = Makedec(_year)

      If _day < 10 Then
         Lcdat 1 , 1 , ; " " ; _day ; "." , 0
      Else
         Lcdat 1 , 1 , _day ; "." , 0
      End If

      If _month < 10 Then
         Lcdat 1 , 19 , ; " " ; _month ; "." , 0
      Else
         Lcdat 1 , 19 , _month ; "." , 0
      End If

      If _year < 10 Then
         Lcdat 1 , 37 , ; "200" ; _year , 0
      Else
         Lcdat 1 , 37 , ; "20" ; _year , 0
      End If

'--Uhrzeit----------------------------------------------------------------------

   _sec = Makedec(_sec)
   _min = Makedec(_min)
   _hour = Makedec(_hour)

      If _hour < 10 Then
         Lcdat 2 , 1 , ; " " ; _hour ; ":", 0
      Else
         Lcdat 2 , 1 , ; _hour ; ":" , 0
      End If

      If _min < 10 Then
         Lcdat 2 , 19 , ; "0" ; _min ; ":", 0
      Else
         Lcdat 2 , 19 , ; _min ; ":" , 0
      End If

      If _sec < 10 Then
         Lcdat 2 , 37 , ; "0" ; _sec , 0
      Else
         Lcdat 2 , 37 , _sec , 0
      End If

   Waitms 50
Loop

'--Ende-------------------------------------------------------------------------




 End

 $include "font6x8.font"


Und hier der Code des Hauptprogrammes. Allein die Zeilen im Abschnitt "Uhrzeit-Variablen" (ab Zeile 144 bei aktivierter Zeilennummerierung) bewirken , dass mein Programm nach dem Aufbau des Bildes stehen bleibt. Keine Temperaturanzeige, keine Darstellung der Schaltzustände, kein Zugriff aufs Menü. Wegen der überschrittenen Zeichenanzahl musste ich ihn als Angang dazugeben.


So. Der Code ist sicher nicht optimal. Wie gesagt, was mich stört ist, dass das Programm nicht mehr läuft, sobald ich den Abschnitt der Uhrzeit-Variablen aktiviere.


Na toll..... Jetzt merke ich gerade, dass das irgendwie nicht sein kann. Denn die RTC-Routine läuft ja mit dem GLCD. Also scheint DAS nicht das Problem zu sein. Nun wirds doch kompliziert. Naja, ich setz´ das jetzt trotzdem mal ins Forum und suche nebenbei den Fehler.


Erstmal viele Grüße und vielen Dank, DW
 

Anhänge

  • ATmega16-16_Steuerung_WWB_23.bas
    38,3 KB · Aufrufe: 18
Hallo DW!

Also ich habe jetzt einige Zeit über deinen Programmcode geschaut und mir auch den Anschlussplan des Mega32 virtuell daneben gelegt.
Mir will sich zur Zeit aber einfach nicht erschließen, warum das GLCD und die RTC nicht zusammen arbeiten sollten.

Wie du aber geschrieben hast, funktioniert es aber letztlich doch.....

Das Einziege was ich mal erhöhren würde, sind SWSTACK, HWSTACK und FRAMESIZE.
Diese scheinen mit jeweils 80 doch relativ gering zu sein.
OK, du verwendest für Uhrzeit und Datum in BCD und binär immer die "selben" Variablen, aber trotzdem.....

Setzt doch schon mal alles auf 128!
Gerade weil du etwas vom Laden eines Bildes schreibst, nachdem der AVR dann einfach "stehen" bleibt.

Außerdem kann das ja auch nicht der vollständige Code sein, denn du schreibst ja etwas vom Anzeigen der Schaltzustände, Temperaturanzeige und so weiter.

Fazit....
Programmstückchen sollte laufen....
JTAG muss deaktiviert sein....
Speicher für die Stacks und Framesize auf 128 erhöhen....
Schleifendurchlauf (DO- LOOP) künstlich verlängern (nicht nur die Waitms 50)...

Grüße,
Cassio
 
N´abend Cassio,

ich habe die Speicherwerte auf 128 erhöht, nichts.

Ich habe mir eine Art Startbildschirm generiert, der mir beim Neustart anzeigt, welche Version ich geladen habe. Wenn meine *.bas-Datei z.B. xyz_V23.bas heißt, so sehe ich eine "23" auf dem Startbildschirm. Ich dachte, sowas ist nützlich, wenn das Teil mal 2 Wochen in der Ecke liegt. Wenn ich es dann wieder einschalte, weiß ich zumindest, woran ich bin. Natürlich muss ich die "23" vorher von Hand im Programm pflegen; das sind die paar Zeilen ziemlich weit vorn im Code, kurz vor der "Initialisierung:".

Naja, schon beim Aufbau dieses Startbildschirmes bleibt er hängen und verkackelt ihn noch zum Teil. Und das nur, wenn ich die 20 Zeilen Code hinter "Uhrzeit-Variablen" aktiviere.
Wenn es hilft, mache ich mal ein paar Fotos vom Display.

Ich such´ auch weiter, danke erstmal und tschüß. DW



Ergänzung:
JTAG war schon deaktiviert. Und Du schreibst, der Code wäre nicht vollständig? Ich hatte den "großen" Code in den Anhang packen müssen, weil mir der Editor die 45000 Zeichen nicht abnahm. Ja, da sind noch Eier drin, aber ich bin am Ball. Und das mit den "selben Uhrzeit-Datums-Variablen" musst Du mir bitte noch erklären.
 
Hallo,

nachdem ich gestern das gute Wetter für Freilandübungen genutzt habe, bin ich nun wieder am Thema. Ich habe mal 3 Fotos erstellt und kommentiere sie ein wenig.

Auf diesem Bild sieht man meinen sog. Startbildschirm. Der wird nach jeder Spannungsunterbrechung und später auch nach dem Verlassen des Menüs (mein Sollwerte-Menü zur Einstellung und Abspeicherung von Variablen im EEPROM) gezeigt. Die hier gezeigte "23" trage ich zum einen von Hand ins Programm als Text ein und zum Anderen ist sie Teil des Dateinamens:
01_Startbild_ok.jpg



Das zeigt den Startbildschirm, wenn ich die 20 Zeilen Code der Uhrzeit-Variablen mit im Programm habe:
03_Startbild_Fehler.jpg



Und so sieht normalerweise das Display aus, wenn die Anlage läuft. Dass jetzt überall die gleiche Temperatur angezeigt wird liegt daran, dass ich derzeit zum Test nur einen Fühler angeschlossen und ihn auf alle ADC´s zugewiesen habe:
02_Schema_ok.jpg



Was mir gerade noch auffällt ist, dass der fehlerhafte Startbildschirm auch dann angezeigt wird, wenn ich gerade das Programm in den Controller lade. Eigentlich genau dann, wenn der Upload durch ist und BASCOM den ROM zum Vergleich liest (gut, zwischen dem Upload und dem Vergleich zeigt mein Display immer irgendwelchen Mist an, aber hier fällt´s auf). Aber hinterher, nach dem Reset, ist´s ok. Bleibt mein Controller mit dem fehlerhaften Programm irgendwo vor oder nach dem internen Reset hängen?



Viele Grüße, DW
 
Hallo DW!

Den angehängten Programmcode habe ich natürlich wieder mal übersehen....... :cool:

OK, dann schaue ich mal in den kompletten Code, vielleicht fällt mir da etwas auf.
Melde mich dann im laufe des Tages noch mal.

Grüße,
Cassio
 
Ja, ich schon wieder,

bin eben durchs Programm gegangen. Sobald ich den Befehl "I2cstart" im großen Programm benutze, streikt alles. Im kleinen Programm, das nur die RTC ausliest und auf´s Display schreibt, geht er. Darum 2 Ideen:

- beißt sich der Befehl "I2cstart" mit irgendwas in meinem Programm?

- kann der Fehler daran liegen, dass ich sozusagen zum EEPROM im Atmega auch noch den RAM der RTC auslese. Muss da irgendwas beachtet werden?


Viele Grüße, DW
 
Hallo DW !

Ich habe eben nur mal auf die Schnelle einen Blick ins Programm geworfen, weil ich gleich noch weg muss....

Irgendwie weiß ich jetzt gar nicht wo ich anfangen soll.... :hmmmm:

Grundsätzlich sind diese ganzen GOTO leider nicht die gute Lösung, in dem großen Programm.
Das solltest du unbedingt umstellen!
Ja ich weiß, damit musst du das ganze Programm neu aufbauen. :wink:
Es kann aber jetzt gut sein, dass sich dein Programm speichertechnisch voll läuft.
Das lässt sich aber nur schwer ermitteln..... weil man das ganze Programm dann Stück für Stück prüfen muss.

Was ich im Programmcode aber seltsam fand ist das hier:
Code:
 [COLOR="#FF0000"]Taster_4[/COLOR]:
   Waitms 50
   If Ta_mehr = 0 Then
      [COLOR="#FF0000"]Goto Taster_4[/COLOR]
   End If
   If Ta_weniger = 0 Then
      [COLOR="#FF0000"]Goto Taster_4[/COLOR]
   End If
   Cursor_weiter = Not Cursor_weiter
   Goto Taster_2


Tja, wie schon geschrieben....
Dein Programm solltest/musst du leider noch mal komplett überarbeiten.
Auf diese Weise können immer wieder Probleme auftreten, die später nur schlecht zu erklären und zu lokalisieren sind.

Grüße,
Cassio
 
Hallo,

also das was einem am meißten den Erfolg verhagelt sind Interrupts die irgendwo dazwischenfunken. Bei mir waren es zB gestern die Interrupts des Touchscreens die in die Steuerroutinen des Displays geschlagen haben und damit den Ablauf gestört haben. Endergebnis war ein hängendes oder ab und zu mal hakendes Display. Ich hab dann zB mit "disable int6" am Start der Displaysteuerung und mit "Enable int6" am Ende den Interrupt während der Sequenz den Interrupt ausgeschaltet weil er ja für die Abfrage der Touchdaden/Eventregister die selben Steuersequenzen und Pins verwendet.

Sieh also mal nach ob durch Interrupts irgendwas in der Ansteuerung des Displays durcheinander kommen kann. Zum Beispiel durch Displayausgaben in der Interruptroutine. Dann hättest du zwei ineinandergeschachtelte Steuersequenzen für das Display.

EDIT:
Was ich im Programmcode aber seltsam fand ist das hier:
Code:
 [COLOR="#FF0000"]Taster_4[/COLOR]:
   Waitms 50
   If Ta_mehr = 0 Then
      [COLOR="#FF0000"]Goto Taster_4[/COLOR]
   End If
   If Ta_weniger = 0 Then
      [COLOR="#FF0000"]Goto Taster_4[/COLOR]
   End If
   Cursor_weiter = Not Cursor_weiter
   Goto Taster_2
Das würde ich auch so sehen. Damit hast du die Gefahr von Endlosschleifen aus denen du nicht rauskommst. Eine Abfrage sollte kurz sein und dann im Programm verarbeitet werden. Versuch nicht auf Ereignisse wie zB Tastaturabfragen zu warten. Dann tut dein Programm nichts anderes mehr als zu warten. Immer nur Abfragen und dann auf den aktuellen Status reagieren.

EDIT2: Du hast etwas zu wenig Bemerkungen drin ...
Code:
 Config Pinb.0 = Output
 Sb_zipu Alias Portb.0

 Config Pinb.1 = Output
 Sb_v_dlh Alias Portb.1

 Config Pinb.2 = Output
 Sb2_v_dlh Alias Portb.2

 Config Pinb.3 = Output
 Sb_v_zi Alias Portb.3

 Config Pinb.4 = Output
 Sb2_v_zipu Alias Portb.4

 Config Pinb.5 = Input
 Ta_weniger Alias Pinb.5

 Config Pinb.6 = Input
 Ta_mehr Alias Pinb.6

 Config Pinb.7 = Input
 Ta_enter Alias Pinb.7
man weiß eigentlich nicht wirklich was sich hinter den Pins verbirgt. Ich mache das zB so ...
Code:
' PB0,/SS ---->---- /CS (XV60D)
' PB1,SCK ---->---- SPI-Clock -- (XV60D , W5100)
' PB2,MOSI --->---- to Slaves -- (XV60D , W5100)
' PB3,MISO ---<---- to Master -- (XV60D , W5100)
' PB4 -------->---- /SCS (W5100) SPI-ChipSelect
' PB5 -------->---- /Reset (W5100)
' PB6 -------->---- /Busy (XV60D)
' PB7 -------------
Ddrb = &B0011_0111
Portb = &B1111_1111

Tft_cs Alias Portb.0
Lan_cs Alias Portb.4
Lan_reset Alias Portb.5
Tft_busy Alias Pinb.6
....
' PK7 ------------- Led -- GND
Man sieht also was an den Pins hängt und ob die LED nach GND oder Vcc geschaltet ist. Bei Tastern wäre das zB auch wichtig.

EDIT3: Also in den ISRs ist nichts mit LCD-Ausgabe und sie sind soweit kurz. Sehr schön. Aber das ganze Programm ist absolut unübersichtlich und so eigentlich nicht zu warten. Wegen dem wilden hin und hergespringe mit den ganzen Gotos müßte man das Programm eigentlich ausdrucken und auf dem Tisch ausbreiten um den Ablauf verfolgen zu können. Das sind erst etwas über 1100 Zeilen. Das ist noch recht kurz. Du wirst schnell über die 2000-3000 Zeilen kommen. Versuch dann mal das hin und hergespringe zu verfolgen. Du wirst an deine Grenzen stoßen. Spätestens wenn du nach nem Monat wieder reinsiehst brauchst du mit zunehmender Programmgröße bei den vielen GOTOs und den wenigen Kommentaren immer länger für die Einarbeitung. Schließlich wirst du dann wohl aus Frust weil du garnicht mehr durchblickst das ganze Programm in die Tonne kloppen. So sieht im Moment meine Prognose aus. Versuch es auf Unterprogramme umzuschreiben und arbeite mit Gosubs oder Calls oder ähnlichem. Damit landest du bei einem Aufruf einer Subroutine wieder bei der nächsten Zeile nach dem Subroutinenaufruf. GOTOs nur für den absoluten Notfall verwenden. Sorry aber so steige ich auch nicht mehr durch das Programm durch. Es ist wie ein Gordischer Knoten der jetzt reif ist für den Schwerthieb.

Gruß
Dino
 
Hi,

und weiter gehts ...

Bei dir im Programm ..
Code:
 Config Pinb.5 = Input
 Ta_weniger Alias Pinb.5
Bascom Referenz zu Config Port/Pin ...
INPUT will set the data direction register to input for port X.
OUTPUT will set the data direction to output for port X.
est steht dort nichts davon das der interne PullUp eingeschaltet wird. Hast du einen externen PullUp oder PullDown ? Schaltet der Taster nach GND oder Vcc ?

Zum I2C-Bus ... ich hab nirgends die Konfiguration gefunden. Benutzt du Hardware oder Software-TWI ? Für Hardware-TWI würde auch die Bindung der Bibliothek fehlen.

Aber das ist alles Nebenschauplatz wenn ich mir das hier ansehe .....
Code:
$regfile = "m32def.dat"
$framesize = 80
$swstack = 80
$hwstack = 80
$crystal = 8000000

'toDo
'alles aus bei Sensorfehler

 $lib "glcdKS108.lbx"

 Config Pina.5 = Output
 Sb2_dlh Alias Porta.5
.....
.....
 Config Pinb.7 = Input
 Ta_enter Alias Pinb.7

 Config Graphlcd = 128 * 64sed , Dataport = Portd , Controlport = Portc , Ce = 3 , Ce2 = 2 , Cd = 7 , Rd = 5 , Reset = 4 , Enable = 6

 Config Timer0 = Timer , Prescale = 1024                    'Faktor 32 entspricht etwa 1:10min., 128 ~ 4:40min., 256 ~ 9:30min. und 1024 ~ 37min.
 Enable Timer0                                              'Rückkehrzeit aus dem Menü
 Enable Interrupts
 On Ovf0 Timer0_interrupt

 Config Timer2 = Timer , Prescale = 256                     'Faktor 32 entspricht etwa 1:10min., 128 ~ 4:40min., 256 ~ 9:30min. und 1024 ~ 37min.
 Enable Timer2                                              'Rückkehrzeit aus dem Menü
 Enable Interrupts
 On Ovf2 Timer2_interrupt

 'Stop Timer2

 Config Adc = Single , Prescaler = Auto , Reference = Avcc
 Start Adc

 ' Variablen für die Temperaturmessung
 Dim Temp_o_mw As Word                                      ' Boilertemperatur oben Messwert
.....
.....
 Dim Blinky2 As Byte
 Dim Blinky3 As Byte

 Blinky2 = 40
 Blinky3 = 26
'------------------------
'(
' Uhrzeit-Variablen
 Dim _weekday As Byte
 Dim _day As Byte
.....
.....
 _day = Makebcd(_day)
 _month = Makebcd(_month)
 _year = Makebcd(_year)

')
'------------------------

 Setfont Font6x8

   Cls
   Lcdat 2 , 1 , "Atmega 32-16" , 0                         ' Anzeige des Microcontrollers
   Lcdat 4 , 1 , "Steuerung_WWB" , 0                        ' Anzeige der Datei
   Lcdat 6 , 1 , "Version: 23" , 0                          ' Anzeige der Dateiversion
   Wait 10
   Cls

 Do                                                         ' <== ##### ANFANG MAINLOOP ###################################

 Initialisierung:                                           ' Hier die Defaultwerte für das Hauptprogramm ablegen
    ' ###### In der Mainloop dauernd CLS machen ist Mist ###########################################################
      Cls                                                   ' ist notwendig, weil diese Routine auch nach dem Menü aufgerufen wird
      Sb_hzg = Merker_hzg
      Sb_dlh = Merker_dlh
      Timer2_wert_b = 0
      Stop Timer2
.....
.....
 Ende_initialisierung:

   Gosub Schema_wwb                                         ' ########## Springt in Mainloop nach hinten ######### ==>

 Hauptprogramm:
'   Lcdat 1 , 1 , M1_uebertemp_dlh ; M2_uebertemp_boiler ; M3_anf_dlh ; M6_anf_hzg ; M8_auskuehlschutz_zirku , 0

   Lcdat 2 , 1 , "Soll:" ; Sw_wwb ; "°C" , 0
.....
.....
 Schema_wwb:                                                ' <==#### Aufruf ueber GOSUB #############

 Line(86 , 2) -(124 , 2) , 1                                'Boiler Innenlinie oben quer
 Line(86 , 43) -(124 , 43) , 1                              'Boiler Innenlinie unten quer
.....
.....
 Line(70 , 23) -(70 , 32) , 1                               'Linie Temperatur DLH
 Line(51 , 32) -(51 , 40) , 1                               'Linie Temperatur DLH

 Return                                                     ' ##### Ruecksprung aus Schema_wwb ??? ######### ==>
 ' ########## Warum ist die Subroutine Schema_wwb Teil der Mainloop ?????  #################

 Loop                                                       ' ###### ENDE MAINLOOP ############# ==> ab nach vorne

' ###########################################################

 Timer0_interrupt:
   If Timer0_wert_a = 255 Then
      Timer0_wert_b = Timer0_wert_b + 1
   End If
   Timer0_wert_a = Timer0_wert_a + 1
   If Timer0_wert_b = 20 Then
      M22_vlz_dlh = 1
   End If
  Return

' ###########################################################

 Timer2_interrupt:
   If Timer2_wert_a = 255 Then
      Timer2_wert_b = Timer2_wert_b + 1
   End If
   Timer2_wert_a = Timer2_wert_a + 1
   If Timer2_wert_b = 255 Then
      Auto_return_hauptprogramm = 1
   End If
   Return

' ###########################################################

 End

 $include "font6x8.font"

im Ganzen würde ich sagen das du eine Subroutine in deine Mainloop gebaut hast. Außerdem ist deine Mainloop eigentlich das komplette Programm in dem du wild mit GOTO und GOSUB hin und herspringst und ein RETURN drin hast das evtl auch mal ohne einen GOSUB einfach was vom Stack holt oder wo das GOSUB mal dauernd was auf den Stack packt was nicht abgeholt wird. Wenn du da noch Interrupts zwischen hast die mit dem Stack arbeiten dann ist das Ergebnis kein Wunder. Je mehr auf dem Stack gearbeitet wird desto eher fliegt dir das Programm um die Ohren. Durch einen größeren Stack wirst du das Dilemma nur herauszögern.

Ergebnis: Dein Stack fliegt dir durch dein wildes Hin und Hergespringe um die Ohren (läuft über) und im Endeffekt scheinst du jetzt bereit durch die ganzen GOTOs den Überblick komplett verloren zu haben.

Lösung: Bau dein Programm KOMPLETT auf eine saubere Struktur mit einzelnen Unterprogrammen um die du über GOSUB oder CALL aufrufst und aus denen du sauber mit RETURN zurückkommst. Schmeiß die ganzen GOTOs komplett raus.

Gruß
Dino
 
Hallo zusammen!

Also ich gebs auf.....
Da bekommt man ja einen Knoten ins Gehirn, wenn man sich nicht zig Stunden mit dem Programm befassen möchte. :)
Das ganze Hin und Her mit den GOTO`s macht mich ganz schwindelig. :wink:

Sorry, aber ich habe momentan einfach nicht die Zeit um mich da reinzuarbeiten.
Ich gehe auch mal davon aus, dass es kein "richtiger" Fehler ist....
sondern durch das permanente Verlassen und wieder Einspringen in Befehlen und Routinen irgendwann speichertechnisch alles durcheinander kommt.


Grüße,
Cassio
 
Hi Cassio,

Sorry, aber ich habe momentan einfach nicht die Zeit um mich da reinzuarbeiten.
ich hab da auch nicht stundenlang dran rum gebrütet. Ich hab mir (aus Erfahrung mit anderen Fehlern) eigentlich nur die ISRs und dann Anfang/Ende der Mainloop angesehen um überhaupt erstmal die aller unterste Grundstruktur zu erkennen. Dabei ist mir dann auch dieses GOSUB und das RETURN aufgefallen. Beim Rest dazwischen wären mir auch die Gehirnwindungen geschmolzen :rolleyes:

Gruß
Dino
 
Hallo,


entschuldigt, dass ich erstmal gelacht habe. Aber zum Aufgeben wollte ich Euch nun wirklich nicht verleiten....


Also gut, da ist noch ´ne Menge zu tun. Ich werde mir Eure Anmerkungen ansehen und dann sicher noch mal zurück in die Anfänger-Ecke gehen. Und ich dachte gerade, dass es (für mich jedenfalls) durchschaubar ist. Aber ich will mir auch nicht erst eine falsche Vorgehensweise aneignen.

Ich will mal schnell auf einige Eurer Punkte reagieren:
Dass ich nun den Code neu erzeugen muss, scheint mir nicht dass Schlimmste, so wie Cassio befürchtet. Die Interrupts dienen mir dazu, eine längere Bedienpause im Sollwerte-Menü zu erkennen und dieses automatisch wieder zu verlassen. Die Gefahr vom Verweilen in Endlosschleifen bei Tasterabfragen umgehe ich in Zukunft besser mit einem Interrupt, oder? Meine Taster haben externe Pullups, demzufolge zieht der Taster den Eingang auf GND. Ist das eigentlich unüblich, einen Zustand "Taster EIN" im Programm mit einer "0" auszuwerten oder ist das egal? Den I2C lasse ich am PortC.0 und PortC.1 laufen, also am Hardware-I2C. Ach ja...


Ich werde mich ranhalten, aber ein wenig Hilfe werde ich schon noch brauchen. Ihr seid Spitze, auch wenn ich noch nicht jedes Eurer Argumente verstehe, zumindest nicht ohne nachzuschlagen.




Wäre es übertrieben, Euch nach einem Vorbild-Programm zu fragen oder wisst Ihr, wo ich eines finden kann. Als Orientierungshilfe, um den richtigen Ablauf zu studieren.



DW
 
Hallo,

Und ich dachte gerade, dass es (für mich jedenfalls) durchschaubar ist. Aber ich will mir auch nicht erst eine falsche Vorgehensweise aneignen.
Die Vorgehensweise mag bis zu einer gewissen Größe des Programmns noch ganz gut funktionieren. Aber glaub mir das du damit sehr schnell die Übersicht verlierst. Du hast bis jetzt grade mal die Grundstruktur des Programmes zusammen. Das wird sich schnell auf das vierfache aufblähen und dann stehst du nur noch im Wald. Wenn man mal Pascal programmiert hat dann wird man sozusagen in eine Struktur hineingezwungen. Das erzieht zur sauberen modularen Programmierung bei der man einzelne Teile des Programmes schnell in neuen Projekten wiederverwenden kann. Das geht mit deinen ganzen GOTOs nicht. Du wirst also bei jedem neuen Projekt bei Null wieder anfangen müssen.

Die Interrupts dienen mir dazu, eine längere Bedienpause im Sollwerte-Menü zu erkennen und dieses automatisch wieder zu verlassen. Die Gefahr vom Verweilen in Endlosschleifen bei Tasterabfragen umgehe ich in Zukunft besser mit einem Interrupt, oder?
Nein, Nein, Nein. Interrupts benutzt man nicht um Programmierfehler zu verschlimmbessern. Sieh dir mal in Bascom den Befehl DEBOUNCE an. Außerdem kann man die Pins mit den Tasten direkt abfragen (so wie jetzt schon) und dann den Status irgendwann später verarbeiten. Man tut es absolut nicht das man auf eine Tastenabfrage wartet. Du hast lediglich 16MHz zur Verfügung. Was soll der Prozessor denn neben dem warten auf nen irgendwann mal stattfindenden Tastendruck noch machen ? Er könnte in einer Sekunde für dich 16 Millionen Befehle abarbeiten. Statt dessen wartet er sich nen Wolf oder auf nen erlösenden Interrupt.

Ist das eigentlich unüblich, einen Zustand "Taster EIN" im Programm mit einer "0" auszuwerten oder ist das egal?
Das kannst du halten wie die Dachkdecker. Wenn du es im Programm vermerkst damit es andere bei der Hilfestellung erkennen und du dich bei der Fehlersuche dran erinnern kannst dann paßt das schon.

Den I2C lasse ich am PortC.0 und PortC.1 laufen, also am Hardware-I2C.
dann fehlt dir noch die Einbindung der Bibliothek sonst ist es nur Software I2C.

aber ein wenig Hilfe werde ich schon noch brauchen. Ihr seid Spitze, auch wenn ich noch nicht jedes Eurer Argumente verstehe, zumindest nicht ohne nachzuschlagen.
Weiterhelfen können wir gerne. Wenn du die Tips nicht in den Wind schlägst dann wie es leider manche machen, dann wird auch recht ausdauernd geholfen ;)

Wäre es übertrieben, Euch nach einem Vorbild-Programm zu fragen oder wisst Ihr, wo ich eines finden kann. Als Orientierungshilfe, um den richtigen Ablauf zu studieren.
Muß ich mal sehen ob ich ein paar Bruchstücke finde. Nur ... verwende die als Anschauungsobjekte. Verfall bitte nicht in eine Copy/Paste-Schlacht. Das hilft dir beim lernen nicht weiter und wird im totalen Desaster enden (oft genug erlebt).

EDIT: Hier hast du mal als Anschauungsobjekt das letzte Grundprogramm das ich als Basis für meine Experimente an meinem selbstgebauten Mega128-Block verwende.
Anhang anzeigen EvalBoard_m128_I2C_DS1307_v05_110912.bas
P1040509.JPG
Sieh dir mal die Tastenabfragen mit DEBOUNCE an und die Initialisierung der I2C-Schnittstelle und was da sonst noch so drin rumfliegt. Du wirst glaube ich nicht wirklich ein GOTO drin finden (hoffe ich mal). Es ist sehr modular aufgebaut und die Teile können schnell wo anders wiederverwendet werden. Es sind auch sehr viele Bemerkungen drin. Man findet selbst nach nem Jahr schnell wieder rein.

Gruß
Dino
 
Hallo DW!

Eines erst mal vorab, damit es keine Missverständnisse gibt.....
Was du da bis jetzt geleistet hast, verdient schon Beachtung, Respekt und Anerkennung!

Es ist wirklich beachtlich, was du da programmtechnisch alles zusammengestellt hattest!
Das muss ich einfach mal loben! :)


Wenn du aber ehrlich bist, dann hast du inzwischen selber festgestellt, dass du mit deiner Art ein Programm zu schreiben so aber nicht weiter kommst.
Dein Programm wird langsam komplexer und es ist noch nicht mal ganz fertig.

Tja, wie du nun ein Programm und ein Menü aufbauen könntest, bleibt dir natürlich selbst überlassen. :wink:

Allerdings solltest du dein Programm gleich zu Beginn zwei grobe Einheiten unterteilen....
1. Einheit:
Bearbeitung (und Anzeige) von Variablen die sich immer wieder ändern.

2.Einheit:
Bearbeitung (und Anzeige) von statischen Werten.

Wenn du dein Programm nach diesen zwei einfachen (aber wichtigen) Einheiten aufgeteilt hast, dann kannst du beide Einheiten danach noch mehr zerlegen.
Nach kurzer Zeit wirst du feststellen, dass du diese ganzen Unterteilungen in Subroutinen schreiben kannst und deine Hauptschleife (DO-LOOP) dann nur noch in bestimmten Abständen die Subs aufruft.


Ich weiß jetzt nicht genau ob es dir hilft oder der Beitrag dich auf Ideen bringt,
aber lies dir mal diesen Beitrag (ab Nr. 56 wird es dann interessant) durch.

Ich habe dem KNUT89 da mal gezeigt, wie man ein Menü aufbauen kann und wie man z.B. statische Werte auch nur einmal am LCD ausgibt.
OK, das Menü ist einfach und es hat auch kein GLCD.... aber das Prinzip ist letztlich immer das Selbe! :wink:
Kannst dir den Thread natürlich auch mal komplett durchlesen. ;)

Grüße,
Cassio
 
Hallo Dino,

bist ja schnell mit dem antworten, das ist gut für mich. Also die I2C-Initialisierung war noch nicht drin. Aber in dem Code-Schnipsel in einem meiner ersten Beiträge, den ich mit funktionierender RTC-Routine bezeichnet habe, sollte es doch richtig sein, oder? Es geht doch sicher um das hier (das ist ein Ausschnitt davon):


.
.
.
Dim _weekday As Byte
Dim _day As Byte
Dim _month As Byte
Dim _year As Byte
Dim _sec As Byte
Dim _min As Byte
Dim _hour As Byte

Dim Ds1307w As Byte
Dim Ds1307r As Byte

Ds1307w = &B11010000
Ds1307r = &B11010001

_day = 31
_month = 12
_year = 09
_sec = 50
_min = 59
_hour = 23


_sec = Makebcd(_sec)
_min = Makebcd(_min)
_hour = Makebcd(_hour)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 0
'I2cwbyte _sec
'I2cwbyte _min
'I2cwbyte _hour
I2cstop
.
.
.

Und falls Du mir einen Beispielcode gibst, macht ja Copy/Paste sicherlich gar keinen Sinn. Mir geht es doch um die Struktur. Habe auch schon einige der Forenbeiträge gelesen, die direkt die Programmierung als Thema haben.


Danke, DW
 

Ü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)