PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bytevergleich fehlerhaft



demmy
30.10.2014, 17:39
Hi zusammen,

ich habe ein kleines Problem, welches mich noch zur Verzweiflung bringt. Und zwar was kann bei einem Atmega1284p dazu führen, das ein normaler Bytevergleich gelegentlich sporadisch fehlerhaft ist?

der Bytevergleich sieht ganz simpel so aus:



If byte1 = byte2 Then
'..... Tue was
else
' Fehler und die Werte der beiden Bytes ausgeben
end if


die beiden Bytes werden zyklisch über die beiden UART-Schnittstellen beschrieben. Jedes mal wenn der Vergleich angeblich ungleich ist und ich mir die beiden angeblich ungleichen Bytes ausgeben lasse, steht aber in beiden Bytes der gleiche Wert drin. Wie kann das sein, das beide Werte identisch sind und er trotzdem in den "Else-Teil" springt?

Das Überprüfen findet in einer eigenen Sub statt, welche zyklisch aus der Hauptschleife angesprungen wird und aus diesem Grund habe ich schon den "$hwstack, $swstack und die $framesize hochgesetzt. Kann es etwas damit zu tun haben?

Ich habe in dem Programm auch alle 4 Timer sowie beide UARTS des Atmega im Einsatz. Ich meine zu glauben, das das Problem verstärkt auftritt, wenn beide UARTS aktiv sind und gleichzeitig Daten ausgetauscht werden. Für die UARTS verwende ich unter anderem auch die Eingang und Ausgangspuffer.

Hat jemand eine Idee oder so ein Phänomen schon mal gehabt?

Ich hoffe jemand hat einen Denkanstoss?

oberallgeier
30.10.2014, 18:57
... Ich habe in dem Programm auch alle 4 Timer sowie beide UARTS des Atmega im Einsatz ...Verbiete doch mal während des Vergleichs die Interrupts, erlaube sie NACH dem Vergleich wieder und schau Dir dann das Ganze nochmal an . . .

demmy
30.10.2014, 19:06
Ok,
du meinst jetzt mittels enable bzw. disable Interrupts?

Was glaubst / hoffst du was das bewirkt wenn ich fragen darf?

Gruß

seite5
30.10.2014, 20:33
evtl. ==

mfg
Achim

peterfido
31.10.2014, 07:56
Da fehlt der Quelltext, wo man den Fehler nachvollziehen kann.

Peter(TOO)
31.10.2014, 09:37
Hallo,

Wir hatten hier letzthin das Problem, dass Bascom keine komplexeren Ausdrücke in einem IF verkraftet:

If ((A AND B) XOR C) Then .....
hat nicht funktioniert, das muss man mit einer Hilfsvariablen machen:
X = ((A AND B) XOR C)
If X Then ...
funktioniert dann.

MfG Peter(TOO)

demmy
31.10.2014, 14:19
mhh das trifft leider alles nicht zu, es ist ein direkter Bytevergleich wie oben beschrieben.

Der Quelltext ist ein paar hundert Zeilen lang, ich glaube nicht das ihr euch das alles antun wollt, der meiste Teil hat eigentlich auch gar nichts mit dem Problem zu tun und läuft autark, ohne das er in diese eine Sub in irgend einer Form eingreift.
Das ganze Programm ist im Grunde so strukturiert das in der Hauptschleife zyklisch einzelne Subs nacheinander aufgerufen werden. Interrupts werden auch keine verwendet außer die Timer. Und bei den Timern wird nur ein Flag gesetzt, welches bei gesetztem Zustand in der Hauptschleife eine Sub anspringen lässt.
Auch die Variablen sind alle Global und die die in dieser Sub verwendet werden, werden eigentlich auch nur dort gebraucht. Sonst nirgends im Programm.

Ich schaue mal ob ich ein paar interessante Auszüge aus dem Quelltet einstellen kann.

peterfido
31.10.2014, 15:35
Evtl. mal den Stack erhöhen. Was passiert, wenn Du zwischen den Bytes eine Dummy-Variable deklarierst?

Dim Byte1 as byte
dim dummy(10) as byte
dim Byte2 as Byte

fredred
31.10.2014, 15:55
Hallo,

ich nehme an die Timereinstellung „spinnen“ beim Mega 128, besser im Header dies einfügen.

Const Timsk = Timsk0

Da kein Code sowie Interrupt- Einstellungen bekannt sind, ist es schwer zu helfen.

Gruß
fredred

demmy
31.10.2014, 17:12
Hi,
was bewirkt denn dieser Befehl?

Const Timsk = Timsk0

Die Stacks habe ich auch schon ganz schön hochgeschraubt!!!


Also folgender Code beinhaltet das Problem:



$regfile = "M1284pdef.dat"
' In den Fusebits wurde der externe Oszillator für 18,432MHz ausgewählt
$crystal = 18432000

$hwstack = 355 ' Standard 42 für den "Hardware Stack"
$swstack = 355 ' Standard 40 für den "Software Stack"
$framesize = 655 ' Standard 40 für den "Frame"

' Baudrate für den ersten seriellen Port
$baud = 9600
' Baudrate für den zweitern seriellen Port
$baud1 = 9600

' Analog Comparator ausschalten ACSR.ACD = 1
Stop Ac
' Watchdog ausschalten
Stop Watchdog

' Echo aus
Echo Off
' Interrupts global zulassen
Enable Interrupts

' KONFIGURATION

' Com1 auf 8 Bit Modus konfigurieren
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
' Com2 auf 8 Bit Modus konfigurieren
Config Com2 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

' Öffnen der zweiten Com-Schnittstelle
Open "COM2:" For Binary As #1

' Empfangspuffer UART
Config Serialin = Buffered , Size = 50
' Sendepuffer UART
Config Serialout = Buffered , Size = 50
' Empfangspuffer UART1
Config Serialin1 = Buffered , Size = 50
' Sendepuffer UART1
Config Serialout1 = Buffered , Size = 50

Declare Sub Kommunikation

Do

....

Call Kommunikation
....

Loop

Sub Kommunikation

' Daten im Empfangspuffer
If _rs_bufcountr1 > 0 Then

fehlende_daten = 0

' Daten vollständig empfangen
If _rs_bufcountr1 >= 5 Then

falsche_laenge = 0

' Daten einlesen
Inputbin #1 , empfangsarray(1) , 5

ziel = empfangsarray(1)
quelle = empfangsarray(2)


If ziel = 0 Then

falscher_kopf = 0

' HIER PASSIERT DER FEHLER!!!!!!!!!!!!!!!!!!!
If quelle = Pruef_quelle Then

falscher_tn = 0

' Empfangene Checksumme mit errechneter vergleichen
If empfangsarray(5) = Crc8(empfangsarray(1) , 4) Then

Err_falsche_checksumme = 0

' Hier tut er dann irgendwas!!!

Else

Err_falsche_checksumme = 1

End If

Else


Err_falscher_tn = 1
' Zur Fehlerüberprüfung springen

End If

Else

falscher_kopf = 1

End If

Else

falsche_laenge = 1

End If

Else

fehlende_daten = 1

End If

End Sub

peterfido
31.10.2014, 19:38
Da fehlt einiges. Der Code mit dem vermeintlichen Fehler sollte zum Nachvollziehen compilierbar sein. Pruef_quelle kann ich auch nicht weiter finden.

i_make_it
01.11.2014, 10:16
1234567890

fredred
01.11.2014, 12:23
Hallo demmy,

Du schreibst “ich verwende alle 4 Timer„.
Ist schon eine weile her als ich ein lauffähiges Projekt mit Mega644 aufgebaut habe, bis ich den Controller durch einen Mega 128 ersetzt habe(100% Code). Ergebnis Projekt instabil. Ursache war Timer0.
Mit $regfile = "m1284pdef.dat" gibt es nur Timer,Timer1,Timer2 und Timer3 aber für die eingebundenen Lib für IR wird Timer0 benötigt. Somit diese Zuweisung. Const Timsk = Timsk0. Alles wieder OK.
Kann sein das dieser Fehler in BASCOM schon behoben wurde.
Ist zwar nicht direkt die Hilfe für Bytevergleich aber wenn in einem größeren Code eine Timer- Interruptsausführung gestartet wird, die im Ablauf nicht passt, kann es schon mal chaotisch werden.
Somit sollte es nur ein Hinweis sein.

Weis auch nicht warum du nicht [Crc] nutzt. Siehe Bascomhilfe.
Nicht vergessen im UART werden immer die Steuerzeichen Chr(10) und Chr(13) angehängt. Diese Zeichen siehst du natürlich nicht am Terminal, wenn er nur Strings anzeigt. In Hexmodus schon.

Mit freundlichen Grüßen
fredred

peterfido
01.11.2014, 15:16
Wäre dann const timsk0 = timsk nicht angebracht, oder habe ich da grad nen Denkfehler?

Oder gar timsk0 alias timsk ?

fredred
01.11.2014, 16:44
Hi,
ja so ist es.

demmy
03.11.2014, 06:47
Guten Morgen zusammen,

leider haben alle Versuche bisher nichts gebracht.

Auch die Zeile für den Timer war leider vergebens.

Ich habe aber inzwischen noch was herausgefunden.
Zunächst noch:

Pruef_quelle ist ein im Programm fest hintelegter wert: dieser wird nur einmal als konstante deklariert.

In folgender Zeile übergebe ich das was über die UART eingelesen wurde an eine Variable.

quelle = empfangsarray(2)

ich habe jetzt wenn der Fehler passiert mit die Werte (pruef_quelle, quelle und empfangsarray(2)) ausgeben lassen.
Diese sind unterschiedlich!
Auch die Konstante pruef_quelle hat plötzlich einen Wert der überhaupt nicht stimmt.

Schaue ich mir das array empfangsarray(1) - empfangsaeeay(5) an, wie bisher, dann sehen die Werte alle korrekt aus.

Es muss also was schief laufen beim übernehmen des Bytes aus dem Bytearray in eine Variable.

Kann es sowas geben?
Wie kann das sein?

Searcher
03.11.2014, 07:18
Guten Morgen demmy,


Kann es sowas geben?
Gibt es wie du siehst, darf aber nicht sein.


Wie kann das sein?
Ich wollte schon öfter raten, wo denn der Bug versteckt ist. Konnte mich aber aufgrund der vielen unbekannten Infos für keine der vielen Möglichkeiten entscheiden.

Du solltest den kompletten Code posten und um es uns noch etwas einfacher zu machen, Teile daraus solange auskommentieren, solange der Fehler noch auftaucht. Vielleicht findest du den Fehler dadurch auch sogar selber :confused:

Gruß
Searcher

i_make_it
03.11.2014, 07:52
1234567890

fredred
03.11.2014, 14:33
Hi demmy,

so da du Interrupt- Timerfehler ausschließen kannst, hätte ich noch Fragen.
Im Codeschnipsel in #10, kann ich nicht erkennen wie groß Array ist. Wichtig für Checksummenbildung mit Crc Auswertung, ist die max Bytelänge und das Abschlusssteuerzeichen zu kennen.
Hast du 50 Byte für Werte muss Sitze zwei Byte größer sein, denn da wird die Checksumme angehängt.
Sehr elegant ist Serial mit Charmatch zuprüfen. Läuft ja im „Hintergrund“, Sub solle aber nach meinen Erfahrungen immer am Ende des Programms stehen.
Declare für Com1 sollte folglich Sub Serial 0charmatch() sein

Kleiner Auszug meiner BAS(Funkbrücke mit RFM12b)

‚++++++++++++++++++++++
'!!!!! muss aktiv sein wenn COM2 Hardware benutzt werden soll !!!!!
Declare Sub Serial1charmatch() 'Sub bekannt machen

Dim Pu As Byte 'Pu prüft den Puffer

'------hier werden die COM-Schnittstellen eingestellt-------
'COM1 ist die V24 für PC / COM2 (TTL) für Empfängervebindung
Config Com1 = 19200 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Com2 = 19200 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

'!!!!! darf nur aktiv sein wenn COM2 Hardware belegt ist !!!!!
'Sonst hält Programm an bis Bytematch 13 ist.
Config Serialin1 = Buffered , Size = 160 , Bytematch = 13 ' 13 gleich Zeilenumbruch

'COM zum einlesen öffnen
Open "COM1:" For Binary As #1 'für Terminal
Open "COM2:" For Binary As #2 'für Empfänger

'diese Sub startet wenn im Puffer COM2 Daten anliegen und
'wird mit Empfang von Chr(13) beendet.

'Pu prüft den Puffer der COM2 wird in diesem Projekt nicht genutzt da
'Empfänger auch eigene Messungen printet wird wohl immer etwas drin sein.

Sub Serial1charmatch()
Pu = Ischarwaiting(2) 'könnte gelöscht werden
Pushall
Input #2 , Kanal Noecho ‚ Kanal alle Byte
Popall
End Sub

Wie schon von peterfide beschrieben solltest du Dummy-Variable deklarierst. Einfach die Bytewerte
ein „Speicherplatz“ mit Länge zuweisen. Mit Overlay sehr übersichtlich und spart noch Resursen.

kleiner Auszug.

Const Max_len = 160
Dim Empfangspuffer(max_len) As Byte
' ab Empfangspuffer(6) die Nutzdaten
Dim Strom As Single At Empfangspuffer(6) Overlay
Dim Spannung1 As Single At Empfangspuffer(3) Overlay
Dim Spannung2 As Single At Empfangspuffer(70) Overlay
Dim Temperatur As Single At Empfangspuffer(102) Overlay
Dim Helligkeit As Single At Empfangspuffer(134) Overlay
‚Crc_ in ist Vergleichsvaiable.
Dim Crc_in As Word At Empfangspuffer(15) Overlay ' CRC muss bei Max_len - 2
Dim Crc As Word
Die As müssen natürlich nicht [Single] sein. Habe ich nur wegen der Auswertungen benötigt.

‘Beispiel prüfen.
Do
Incr Z 'Z um 1 erhöhen
If Z = Max_len Then ' erwarte Anzahl an Bytes empfangen
' CRC berechnen
Z = Max_len - 8
Crc = Crc16(empfangspuffer(6) , Z)

' CRC prüfen
If Crc <> Crc_in Then
Print "Fehler"
End If
If Crc = Crc_in Then
Print "mach weiter"
End If
‘…….

Loop

So wie ich es sehe, hast du schon sehr gute Kenntnisse. Somit, dies nur als Anregung betrachten und selber an dein Projekt anpassen.
{i_make_it} hat es noch besser erklärten können wie ich. Ein MCU ist kein "Hochleistungsrechner",
Freue mich aber wie hartnägig du bist. Wirst bestimmt bald zum Ziel kommen.

Mit freundlichen Grüßen
fredred

demmy
03.11.2014, 19:05
Hi,

vielen Dank schon mal für eure Hilfe!

Also das Array "empfangsarray(5)" ist 5 Byte groß.

empfangsarray(1) = Zieladresse
empfangsarray(2) = Quelladresse
empfangsarray(3) = Nutzdaten1
empfangsarray(4) = Nutzdaten2
empfangsarray(5) = CRC8

In der Zeile: empfangsarray(5) = Crc8(empfangsarray(1) , 4) berechne ich eigentlich die Checksumme des empfangenen Telegramms mit der empfangenen Checksumme
und Prüfe das Telegramm auf Plausibilität.

Darf ich das mit den Dummy-Variablen so verstehen das zwischen den Speicherbereichen der Variablen immer ein Leerplatzt bleibt?


Wenn es in irgendeiner Form zu einer Überschneidung der Variablen kommen sollte, müsste ich das nicht erkennen wenn ich mir in Bascom nach dem Compilieren mit "strg w" den Report anzeigen lasse? Dort kann ich doch die Speicherbereiche der Einzelnen Variablen sehen!?

peterfido
03.11.2014, 19:30
Frei nach Radio Eriwan: Im Prinzip schon. Du kannst aber bei einer falschen Wertzuweisung, wenn Du z.B. mit den Overlays durcheinander kommst, unter Umständen ungewollt dahinterliegende Variablen überschreiben. Wenn sich eine Konstante ändert, dann passt da was nicht. Raten macht mir da nicht soo Spaß. Compilierfähiger Code, wo der Fehler noch auftritt ist immer hilfreich.

fredred
04.11.2014, 11:55
Hi demmy,

Ja Ja perterfido hat schon wieder mal Recht. Es ist wie Topfschlagen wenn nur ein paar Codezeilen bekannt sind.
Hatte als Hinweis auch nur ein paar Codezeilen meines Projekts geschickt, da der komplette Code 879 Zeilen hat.
Erstell doch einfach mal zwei kleine Code. Ein mit Sendebyte und ein mit Empfangsbyte. Natürlich mit Stacks- und Dimzuweisungen.
Somit können wir alles praktisch testen und bestimmt helfen.
Da ich nach wie vor der Meinung bin, Crs wertet auch die Steuerzeichen (Hex 0A uns 0C) aus, könne dies dein Problem sein. So war auch der Vorschlag gemeint, Array als Dummy-Variable, als Paket zu Senden und dieses auch so auszuwerten.
Vielleicht reicht es auch schon du übermittelst Sende- Empfangsbyte in Hexformat.

PS. Bin nicht gut in der deutschen Sprache und Rechtschreibung. Aber ein Hexskript lese ich wie ein Bilderbuch.


Kleiner Spaß(Anregung von peterfido)
Anfrage an Radio Eriwan: „kann man eine Frau aus einer Entfernung von 1 Meter schwängern“
Antwort von Ratio Eriwan: Im Prinzip schon. „wenn Penis 1,10 Meter lang ist und in der Mitte nicht durchhängt“

Gruß
fredred

demmy
05.11.2014, 19:25
Also,
ich habe aktuell ein paar Neuigkeiten.
Ich habe mir jetzt nochmal den $swstack, $hwstack und $Frame vorgenommen und die Werte nochmals erhöht. Jetzt habe ich den Eindruck das das Problem drastisch besser geworden ist. Aber leider noch nicht 100%ig weg.
Gibt es die Möglichkeit zur Laufzeit des Programmes auszulesen, in wie weit die Speicherbereiche belegt oder ausgelastet sind? Also irgendwie einen Stackpointer oder sowas? Ich würde mir gerne ausgeben lassen wie voll die Dinger laufen?

Was wiederum irgendwie gegen die Stacks spricht ist, der Versuch den ich noch gemacht habe alle Sub's rauszunehmen und den gesamten Code direkt in der Hauptschleife laufen zu lassen. Also komplett ohne den Aufruf von Subs, ist das fehlverhalten sprunghaft angestiegen!?

UPDATE:

ich habe die Bibliothek "stackcheck" und deren funktionen entdeckt.

mit der Hilfe der Lib habe ich ein $hwstack von 8 ein $swstack von 9 und ein $Frame von 2045 ermittelt und ausgelesen. Sind das plausibele Werte?

fredred
06.11.2014, 11:39
Hallo demmy,

die Speicherreservierung für lokale Variablen ist ja gewaltig.

Kleine Beschreibung von meinem Freund Peter.
$hwstack bestimmt die Größe des reservierten Speichers in Byte für Sprungmarken. Vor jedem Sprung innerhalb des Programms wird die aktuelle Position (2 Byte) im Hardwarestack gespeichert. Je mehr Sprünge im Programm vorhanden sind, desto größer sollte der Wert gewählt werden.
$swstack bestimmt die Größe des reservierten Speichers in Byte zur Adressierung von zu übergebenden und lokalen Variablen. Jede Variable die einer Sub oder Funktion übergeben oder als Local deklariert wird benötigt 2 Byte des Softwarestacks.
$framesize bestimmt die Größe des reservierten Speichers in Byte für lokale Variablen. Alle zu einem Zeitpunkt benötigten lokalen Variablen werden in diesem Bereich gespeichert. Bei Verwendung vieler lokaler Variablen in Subs oder Funktionen sollte dieser Wert entsprechend groß gewählt werden.

Variablen
Eine Variable wird mit dem Befehl Dim oder Local festgelegt. Die Festlegung einer Variable wird auch als Deklaration bezeichnet. Wird eine Variable mit Dim deklariert, so gilt diese ab dem Punkt ihrer Deklaration programmweit (auch in allen Subs und Funktionen). Innerhalb einer Sub oder Funktion kann eine Variable auch als Local deklariert werden. Dies hat zur Folge, dass diese Variable nur in der einen Durchführung der Sub oder Funktion gültig ist und wieder gelöscht wird, sobald die Sub oder Funktion verlassen wird.Der Wert einer Variable kann wärend der Programmausführung geändert werden. Dies ermöglicht es zum Beispiel das Ergebnis einer Rechnung zu speichern.
Jede Variable benötigt - abhängig von ihrem Typ - eine bestimmte Menge an Speicherplatz im RAM. Bascom-AVR unterstützt die folgenden Datentypen:


Bit: besteht aus nur einem Bit und kann den Wert 0 oder 1 speichern
Byte: besteht aus 8 Bit und kann Ganzzahlen von 0 bis 255 speichern
Word: besteht aus 16 Bit und kann Ganzzahlen von 0 bis 65535 speichern
Integer: besteht aus 16 Bit und kann Ganzzahlen von -32768 bis +327687 speichern
Long: besteht aus 32 Bit und kann Ganzzahlen von -2147483648 bis 2147483647 speichern
Single: besteht aus 32 Bit und kann Fließkommazahlen von 1,5 x 10^–45 bis 3,4 x 10^38 speichern
Double: besteht aus 64 Bit und kann Fließkommazahlen von 5,0 x 10^–324 bis 1,7 x 10^308 speichern
String: kann text mit einer Länge von 1 bis 254 Zeichern speichern, jedes Zeichen benötigt ein Byte und zusätzlich wird ein Byte mehr benötigt als der String lang ist

Sollte deine Angabe stimmen, komme ich ins grübeln, da so etwas noch nicht erlebt.
Rechne mal selber. Double hat 8 Byte(ist das Max). Somit müssten 255 Variablen in dieser Größe im Code stehen(ist Grenzwert). Wie du aber erkennen kannst, mit Verschwendung der Strings, kommt man locker auf diese Größe.
Nur mal so:
Text = „Hallo“ somit 5 Byte + 1(sicher ist +2) = 6 Byte nötig, schreibst du es aber so,
Dim Text AsString*100
werden 94 Byte „verballert“. Warum?

War ja auch mal meine Anfrage poste auch mal die Dim’s deiner Variablen usw.
Bekamst auch schon den Hinweis, wenn Array oder Overlay nicht sauber eingestellt, kommt es zu Überschreibung der Byte. Fehlerfindung sehr schwierig, da dynamisch. Ist wie mit Windows „mal Gates mal nicht“

Bitte beachte, ist keine Belehrung, nur ein Hinweis.

Mit freundlichen Grüßen
fredred .

demmy
06.11.2014, 19:24
Hi nochmals vielen Dank für die super Erklärungen! :)

Also das mit dem extrem hohen Frame hat mich auch sehr verwundert. Ich habe auch meinen Denkfehler dabei gefunden. Wenn man die Lib "stackchek" von Bascom verwendet bekommt man nicht den belegten Frame angezeigt, sondern den Speicher der noch frei ist!!!!!
Ich habe inzwischen die Stack-Werte wieder auf ein normales Level heruntergeschraubt.

Und ich habe endlich die Zeit gefunden und mein Programm nochmal vernünftig auf das wesentliche mit allen Deklarationen zu reduzieren.




$regfile = "M1284pdef.dat"
' In den Fusebits wurde der externe Oszillator für 18,432MHz ausgewählt
$crystal = 18432000

$hwstack = 100 ' Standard 42
$swstack = 100 ' Standard 40
$framesize = 200 ' Standard 40
Const _my_framesize = 200

$lib "stackcheck.lib"

$hwcheck ' hw stack check ein
$framecheck ' frame check ein
$softcheck ' sw stack check ein

' Baudrate für den ersten seriellen Port
$baud = 9600
' Baudrate für den zweitern seriellen Port
$baud1 = 9600


' Analog Comparator ausschalten ACSR.ACD = 1
Stop Ac
' Watchdog ausschalten
Stop Watchdog


' Echo aus
Echo Off
' Interrupts global zulassen
Enable Interrupts



' KONFIGURATION

' Com1 auf 8 Bit Modus konfigurieren
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
' Com2 auf 8 Bit Modus konfigurieren
Config Com2 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

' Öffnen der ersten Com-Schnittstelle
Open "COM1:" For Binary As #1
' Öffnen der zweiten Com-Schnittstelle
Open "COM2:" For Binary As #2

' Empfangspuffer UART
Config Serialin = Buffered , Size = 100
' Sendepuffer UART
Config Serialout = Buffered , Size = 100
' Empfangspuffer UART1
Config Serialin1 = Buffered , Size = 100
' Sendepuffer UART1
Config Serialout1 = Buffered , Size = 100


Const Adc_multi = 0.0025 ' = 2,56V / 1024bit
Config Adc = Single , Prescaler = Auto , Reference = Internal_2.56 ' Es wird die interne Referenzspannung von 2,56V ausgewählt
Start Adc



' TIMER KONFIGURIEREN

'Const Timsk = Timsk0
Config Timer0 = Timer , Prescale = 1024 ' Timer konfigurieren
On Timer0 Timerroutine0 ' Timerinterrupt Subroutine zuweisen
Enable Timer0 ' Timer aktivieren
Stop Timer0 ' Timer stoppen


Config Timer1 = Timer , Prescale = 1024 ' Timer konfigurieren
On Timer1 Timerroutine1 ' Timerinterrupt Subroutine zuweisen
Enable Timer1 ' Timer aktivieren
Stop Timer1 ' Timer stoppen


Config Timer2 = Timer , Prescale = 1024 ' Timer konfigurieren
On Timer2 Timerroutine2 ' Timerinterrupt Subroutine zuweisen
Enable Timer2 ' Timer aktivieren
Stop Timer2 ' Timer stoppen


Config Timer3 = Timer , Prescale = 1024 ' Timer konfigurieren
On Timer3 Timerroutine3 ' Timerinterrupt Subroutine zuweisen
Enable Timer3 ' Timer aktivieren
Stop Timer3 ' Timer stoppen



' SUB'S DEKLARIEREN

Declare Sub Zykluszeitmessung
Declare Sub R_bus_kommunikation
Declare Sub Timerueberlauf0
Declare Sub Timerueberlauf1
Declare Sub Timerueberlauf2
Declare Sub Timerueberlauf3
Declare Sub Stackbelegungmessung



' VARIABLENDEKLARATION

' Schleifenzähler
Dim I As Byte
Dim I1 As Byte
Dim I2 As Byte


Dim Kartenadresse As Byte
Dim Pruef_kartenadresse As Byte

Dim Anzahl_karten As Integer
Anzahl_karten = 2

Dim Aktuelle_karte As Integer
Aktuelle_karte = 1

' Teilnehmer/Karten Speicherbereiche
Dim R_bus_empfangsarray(5) As Byte
Dim R_bus_sendearray(5) As Byte

Dim R_bus_empfangene_zieladresse As Byte
Dim R_bus_empfangene_quelladresse As Byte

Dim R_bus_status As Byte
Dim R_bus_schritt As Byte
R_bus_schritt = 1
Dim R_bus_fehlertyp As Integer
Dim R_bus_diagnosemodus As Bit
Dim R_bus_gesperrt As Bit
Dim R_bus_kein_teilnehmer As Bit
Dim R_bus_fehler As Bit
Dim R_bus_karten_fehler As Bit
Dim R_bus_konfig_fehler As Bit
Dim R_bus_konfig_fehler_position As Integer

Dim Err_falscher_teilnehmer As Bit
Dim Err_fehlende_antwort As Bit
Dim Err_falsche_protokolllaenge As Bit
Dim Err_falscher_telegrammkopf As Bit
Dim Err_falsche_checksumme As Bit

' Timer Reloadwerte festlegen (für 16Bit Timer1 u. 3 mit Prescaler 1024 bei 18,432MHz)
Dim Reload_1s As Word
Reload_1s = 47536
Dim Reload_500ms As Word
Reload_500ms = 56536
Dim Reload_250ms As Word
Reload_250ms = 61036
Dim Reload_150ms As Word
Reload_150ms = 62836

' Zykluszeit Messung
'Const Zeitmessung_divident = 18000 ' 18432000 MHz / 1024 Prescaler
'Dim Zeitmessung_zeit As Single
Dim Zeitmessung_timer_ueberlauf As Bit
Dim Zeitmessung_reloadwert As Word
Dim Zeitmessung_ticks_start As Integer
Dim Zeitmessung_ticks_ende As Integer
Dim Zeitmessung_letzter_ueberlauf As Bit
Dim Zeitmessung_vergangene_ticks As Integer
Dim Zeitmessung_aktiv As Bit


' Timerflags
Dim Timerflag0 As Bit
Dim Timerstatus0 As Bit
Dim Timerflag1 As Bit
Dim Timerstatus1 As Bit
Dim Timerflag2 As Bit
Dim Timerstatus2 As Bit
Dim Timerflag3 As Bit
Dim Timerstatus3 As Bit

' Stackbelegung Messung
Dim Hwstack_belegung As Word
Dim Swstack_belegung As Word
Dim Frame_belegung As Word


' Zu beginn S-Bus / R-Bus Eingangs- / Ausgangspuffer leeren
Clear Serialin
Clear Serialout
Clear Serialin1
Clear Serialout1



' HAUPTSCHLEIFE

Do


' R-BUS KOMMUNIKATION
Call R_bus_kommunikation


' ZYKLUSZEIT MESSEN
Call Zykluszeitmessung


'STACKBELEGUNG MESSEN
Call Stackbelegungmessung


' TIMER0
If Timerflag0 = 1 Then
Timerflag0 = 0
' Call Timerueberlauf0
End If

' TIMER1
If Timerflag1 = 1 Then
Timerflag1 = 0
' Call Timerueberlauf1
End If

' TIMER2
If Timerflag2 = 1 Then
Timerflag2 = 0
' Call Timerueberlauf2
End If

' TIMER3
If Timerflag3 = 1 Then
Timerflag3 = 0
' Call Timerueberlauf3
End If

Loop

' R-BUS KOMMUNIKATION

Sub R_bus_kommunikation

' RINGABFRAGE DER TEILNEHMER

Select Case R_bus_schritt

Case 1: ' KARTE ANSPRECHEN

' Eingangs- / Ausgangspuffer löschen
Clear Serialin1
Clear Serialout1

' Timer zurücksetzen bzw. auf neuen Startwert einstellen (1s)
Timer1 = Reload_1s
Timerflag1 = 0
Timerstatus1 = 1
' Watchdogtimer starten
Start Timer1

' Sendedaten und Kartenadresse zuordnen
Select Case Aktuelle_karte

Case 1 :
Kartenadresse = 255
R_bus_sendearray(3) = 10
R_bus_sendearray(4) = 20
Case 2 :
Kartenadresse = 254
R_bus_sendearray(3) = 11
R_bus_sendearray(4) = 21

End Select

R_bus_sendearray(1) = Kartenadresse
R_bus_sendearray(2) = 0
R_bus_sendearray(5) = Crc8(r_bus_sendearray(1) , 4)

Pruef_kartenadresse = Kartenadresse
R_bus_empfangene_zieladresse = 0
R_bus_empfangene_quelladresse = 0

Waitus 500

' Telegramm an Teilnehmer senden
Printbin #2 , R_bus_sendearray(1) , 5 ;

' In Schritt 2 schalten
R_bus_schritt = 2

Case 2: ' AUF RÜCKMELDUNG DER KARTE WARTEN

' Daten im Empfangspuffer
If _rs_bufcountr1 > 0 Then

Err_fehlende_antwort = 0

' Telegramm vollständig empfangen
If _rs_bufcountr1 >= 5 Then

Err_falsche_protokolllaenge = 0

' Telegramm einlesen
Inputbin #2 , R_bus_empfangsarray(1) , 5

R_bus_empfangene_zieladresse = R_bus_empfangsarray(1)
R_bus_empfangene_quelladresse = R_bus_empfangsarray(2)

' Zieladresse einlesen und mit eigener Adresse vergleichen
If R_bus_empfangene_zieladresse = 0 Then

Err_falscher_telegrammkopf = 0

' HIER PASSIERT DER FEHLER!!!!!!!!!!!!!!
' Quelladresse mit erwarteter vergleichen
If R_bus_empfangene_quelladresse = Pruef_kartenadresse Then

Err_falscher_teilnehmer = 0

' Empfangene Checksumme mit errechneter vergleichen
If R_bus_empfangsarray(5) = Crc8(r_bus_empfangsarray(1) , 4) Then

Err_falsche_checksumme = 0


' Aktuellen Teilnehmer um eins erhöhen
Incr Aktuelle_karte

' Alle Teilnehmer durchgelaufen, wieder von vorne beginnen
If Aktuelle_karte > Anzahl_karten Then
Aktuelle_karte = 1
End If

' WatchdogTimer zurücksetzen bzw. auf neuen Startwert einstellen (1s)
Timer1 = Reload_1s
Timerflag1 = 0

' Zurück zu Schritt 1
R_bus_schritt = 1

Else

' R-bus-fehler
' Timer1 stoppen
Stop Timer1
Timerflag1 = 0
Timerstatus1 = 0
' Zur Fehlerüberprüfung springen
R_bus_schritt = 3
Err_falsche_checksumme = 1

End If

Else

' R-bus-fehler
' Timer1 stoppen
Stop Timer1
Timerflag1 = 0
Timerstatus1 = 0
' Zur Fehlerüberprüfung springen
R_bus_schritt = 3
Err_falscher_teilnehmer = 1

End If

Else

Err_falscher_telegrammkopf = 1

End If

Else

Err_falsche_protokolllaenge = 1

End If

Else

Err_fehlende_antwort = 1

End If


Case 3: ' WATCHDOG / FEHLERÜBERPRÜFUNG WARTEZEIT


End Select

End Sub

' ZYKLUSZEITMESSUNG

Sub Zykluszeitmessung

If Zeitmessung_aktiv = 1 Then

' Timer Ticks ende
Zeitmessung_ticks_ende = Timer3

' Letzten abgeschlossenen Messzyklus auswerten

' gab es seit dem beginn der Zeitmessung einen Timerüberlauf
Zeitmessung_letzter_ueberlauf = Zeitmessung_timer_ueberlauf

If Zeitmessung_letzter_ueberlauf = 0 Then
Zeitmessung_vergangene_ticks = Zeitmessung_ticks_ende - Zeitmessung_ticks_start
Else
' Start bis Überlauf
Zeitmessung_ticks_start = 65536 - Zeitmessung_ticks_start
' Überlauf bis Ende
Zeitmessung_ticks_ende = Zeitmessung_ticks_ende - Zeitmessung_reloadwert
' Summe der Ticks
Zeitmessung_vergangene_ticks = Zeitmessung_ticks_start + Zeitmessung_ticks_ende
End If

' Zeit berechnen
'Zeitmessung_zeit = Zeitmessung_timerticks / Zeitmessung_divident

End If

' Neue Zeitmessung beginnen

' Timer Ticks start
Zeitmessung_ticks_start = Timer3
Zeitmessung_timer_ueberlauf = 0
Zeitmessung_aktiv = 1

End Sub

' STACKBELEGUNG MESSUNG
Sub Stackbelegungmessung

Hwstack_belegung = _hwstackstart - _hw_lowest

Swstack_belegung = _hwstack_low - _sw_lowest

If _fw_highest > 0 Then
Frame_belegung = _frame_high - _fw_highest
' Korrektur bei der Berechnung des belegten Platzes
Frame_belegung = _my_framesize - Frame_belegung ' ohne Korrektur wird verbleibender Platz angezeigt...
End If

End Sub

Timerroutine0:

Timerflag0 = 1

Return

Timerroutine1:

Timerflag1 = 1

Return

Timerroutine2:

Timerflag2 = 1

Return

Timerroutine3:

Timerflag3 = 1

Return

' UART1 schließen
Close #1
' UART2 schließen
Close #2

End


Ich hoffe Ihr könnt da jetzt besser was rauslesen? :)

Und bezüglich Overlays, das verwende ich aktuell nicht in meinem Code.

Viele Grüße

Searcher
07.11.2014, 07:29
Hallo demmy,
ich blicke zwar nicht durch, was das Programm eigentlich tut; glaube aber erstmal zwei nicht initialisierte Variable festgestellt zu haben.

"R_bus_schritt" und "Aktuelle_karte", die nach Deklaration den Wert 0 haben.

Beide werden in "R_bus_kommunikation" in Case Statements abgefragt, die jedoch keinen Case 0 beinhalten, also da auch keine Aktion stattfindet.

Vielleicht bei der Reduzierung draufgegangen?;)

Gruß
Searcher

demmy
07.11.2014, 10:33
Ups ja du hast recht die beiden Variablen werden zu beginn mit 1 initialisiert.

Sinn des Programmes ist es, zyklisch von weiteren an den µC angeschlossenen µC in einer Ringabfrage Daten abzurufen und zu sammeln. Wenn alle Teilnehmer durchlaufen sind, wird wieder mit dem ersten angefangen. Das passiert freilaufend, also ohne Unterbrechung. Es sind verschiedene Mechanismen eingebaut um eine Unterbrechung in der Ringabfrage zu erkennen, zu bereinigen und diese dann neu anzustoßen. Über die UART1 können dann die gesammelten Daten jederzeit abgerufen werden. Die Daten der angeschlossenen Karten werden in einem Ringpuffer gespeichert und immer wieder mit aktuelleren Daten überschrieben.

Das ganze System funktioniert einwandfrei. Ich bekomme eben nur gelegentlich eine Unterbrechung in der Ringabfrage ausgegeben, die an der oben vermerkten Stelle passiert. Wo angeblich die "R_bus_empfangene_quelladresse" nicht = der "Pruef_kartenadresse".
Ich lasse mir dann sofort beide Werte ausgeben und zu diesem Zeitpunkt stehen aber die gleichen Werte in beiden variablen! Ich verstehe also nicht warum er dann in den Else-Teil der abfrage springt!? Der gesammte Rest des Programmes funktioniert ohne Probleme und da sind noch etliche If Then Else abfragen drin!? Wieso gibt es an keiner anderen Stelle mal ein Problem??? Auch die Variablen werden nur in diesem Programmteil verwendet!

Kann das irgendwie ein Bug sein in BASCOM?

UPDATE:

Ich habe die beiden fehlenden Initialisierungen oben Im Code ergänzt.

fredred
07.11.2014, 11:50
Hi demmy,

muss mich Searcher anschließen. Kann noch nicht mal grob nachvollziehen was dein Programm machen soll. Einige „VARIABLENDEKLARATION“ kann ich nicht nachvollziehen bzw. sind Verschwendung.
Lassen wir erst mal so stehen.
Eine wichtige Frage hätte ich aber schon zur Hardware. Hat dein Board noch eine Com Schnittstelle für externen Terminalprogramm. Wenn ja ist dies für Fehlersuche einfach klasse.
Beispiel:
' HIER PASSIERT DER FEHLER!!!!!!!!!!!!!!
' Quelladresse mit erwarteter vergleichen
Print „Adresse “ ; R_bus_empfangene_quelladresse ; „ „ ; „ Pruef " ; Pruef_kartenadresse

If R_bus_empfangene_quelladresse = Pruef_kartenadresse Then ....

Nun siehst du den Inhalt der Variablen. Da du an jeder stelle im Programm solche Abfrage machen kannst, ist die Fehlersuche sehr hilfreich(so mache ich es) natürlich, wenn Erfolg die Prints ausblenden oder löschen. Benötigen viel Speicherplatz.
Hast du diese Möglichkeit, kann ich mein bevorzugtes Terminalprogramm in Anhang legen.
Nur so kannte ich damals den Fehler für „Checksummenprüfung“ finden.
Terminalprogramm hat den Vorteil. Anzeige als Sting/Dec/Hex und Bin gleichzeitig anzuzeigen wenn so eingestellt.

Nun schnell noch deinen letzen Beitrag gelesen. Lass mal Else weg und mach eine neue IF Abrage (wenn NICHT).

Ich schließe ein BASCOM Bug aus.......

Mit freundlichen Grüßen
fredred

WL
07.11.2014, 14:27
Hallo demmy,

Vielleicht liegt es ja an der Hardware.
Die Frequenz liegt ja recht weit am Limit.
Mit welcher Spannung arbeitet der Mega?
Zeig uns doch mal deine Schaltung.

demmy
08.11.2014, 11:37
Hi zusammen,

also die Werte habe ich mir die ganze Zeit schon über eine UART im Fehlerfall ausgeben lassen! Deshalb weiß ich ja das die Werte im Fehlerfall identisch sind. :)

Und ich kann euch versichern, das wir die Hardware ausschließen können. Ja, die Frequenz ist recht hoch, aber der µC läuft mit 5V. Ich habe auch schon mit einem Oszi die Spannung mitgeloggt. Die liegt absolut konstant bei 5,03V. Zudem ist die Brown-Out Detection aktiviert.

Also es muss etwas sein, wenn beide UART'S gleichzeitig senden und empfangen!

Solange nur die eine Schnittstelle aktiv ist, also die, welche zyklisch die Karten abruft, passiert der Fehler nicht.

Erst wenn ich die zweite Schnittstelle dazu nehme, und dort auch aktiv zyklisch sende und empfange, dann tritt der Fehler auf!!!
Aber komischerweise tritt der Fehler immer nur bei der anderen auf.

Ich versuch das jetzt nochmal mit der zweiten IF abfrage auf Not IF ohne das ELSE was fredred vorgeschlagen hat.

fredred
08.11.2014, 13:13
Hallo demmy,

Der Hinweis von Willy ist OK aber wenn es nur Probleme mit Crs sind, können wir dies ausschließen.
Mit Bascom(keile Sache) sollte doch schon einiges beachtet werden. Nur weil im Name BAS erscheint, hat dies nichts mit dem alten Dos- Basic gemein. Der BASCOM- Compiler ist schon sehr nah an Hardware für Controller dran.
Nach Meinen bescheidenen Erfahrungen, sind es häufig nur Fehler der Variablen Einstellungen. Noch schlimmer ist, wenn eine IF- oder Caseabfrage ins Leere läuft.
Nun habe ich mich die Zeit genommen deinen Code nachzuvollziehen. Ist nicht so einfach da sehr viele Schleifen verschachtelt sind.
Frage: hast du in deiner BASCOM Umgebung [Line number und Draw Indention Lines] aktiviert. Somit ist ein Abgleich besser möglich.
Infoaustausch sollt dann besser mit PN erfolgen. Endergebnis dann im Forum.
Wir wollen Forum ja nicht „vermüllen“.
Vorab Hinweis: (Incr Aktuelle_karte) in Zeile 244 kann ich nachvollziehen, müsste dies nicht erst vor End If stehen.
Leider habe ich zur Zeit nicht die Möglichkeit dein Programm hardwaremäßig zu testen.

Mit freundlichen Grüßen
fredred

PS. den letzten Kommentar gelesen.
Somit nehme ich an eine Abfrage/Entscheidung verursacht Fehler.
Ist ja nach wie vor immer das gleiche Problem, man kann sehr viel im Programmablauf abfragen, aber hängt das „Ding“ in einer Schleife fest, kommt keine Fehlermeldung(macht ja alles so wie Programmiert) Somit alles im Terminal anzeigen lassen und an den kritischen Punkten ein Stop einfügen.
Schaust du mal im BASCOM Code für 2 UART abfragen, wirst du erkennen, nur wenn der erste den Status „ich bin fertig“ meldet wird UART zwei freigegeben.

demmy
24.11.2014, 06:31
Guten Morgen zusammen,

ich möchte euch die Lösung des Problems nicht vorenthalten.

An dieser Stelle möchte ich auch nochmal recht herzlich bei allen und speziell bei Fredred bedanken, der mit sehr bei der Findung des Problems geholfen hat.

Also die Lösung des Problems war es, einen Quarz unter 16MHz zu verwenden. Bei verwendung eines Quarzes über 16MHz kommt es scheinbar zu Timingproblemen. Im zusammenhang mit zu langen Flanken aufgrund von 5V-betrieb anstelle von 3,3V.

Aber vielleicht kann Fredred noch ein paar Worte dazu sagen? Er kann das viel besser erklären als ich. ;)

Viele Grüße

fredred
24.11.2014, 17:06
Hallo demmy,

wir bedanken uns auch für die Rückmeldung. Machen einige nicht wen Problem gelöst ist.
Profitieren ja auch von praktischen Erfahrungen.


Aber vielleicht kann Fredred noch ein paar Worte dazu sagen? Er kann das viel besser erklären als ich. :wink:



Na hier würde ich sagen Nein.

Aber eine kleine Erklärung versuche ich mal.
In der Digitaltechnik war viele Jahre die Betriebsspannung 5Volt der Standart. Die Zeit von L nach H oder umgedreht, reichten völlig aus bis zu 16MHz Systemtakte(Physikalisch bedingt) Nun haben wir aber nicht mehr so viel Zeit, wollen ja immer schneller werden. Die Zeit von 0 bis 5 Volt zu erreichen ist viel zu lang.
Nun kommt die neue Technologie 3,3 Volt als Betriebsspannung.
Die Flanken werden kürzer somit alles viel schneller. Bin mich sicher eine neue Technologie kommt, aber bei 1,7 Volt ist Schluss.
Oder wir verlassen die Erde. Es sei denn, es werden nicht mehr Siliziumtransistoren verwendet, sondern Lichtspeicher für diese Aufgaben erfunden (siehe Albert Einstein). Hat ja Anregung veröffentlicht.

Bestimmt kommt nun bald der Hinweis: Digital ist nur 0 oder 1 und Schuss... du Spinner.

Kann ich wiedererlegen. Der Maschinenzyklus(Takt) für MCU hat für Register lesen und schreiben, immer ein Zeitverhalten. Ein 100% es Digital = Zeit ist vernachlässigbar, werden wir wohl nicht mehr erleben.

Schlusswort:
Warum soll der MCU mit Maximemalen Takt tasten, wenn nicht nötig, Abgesehen vom Stromverbrauch.
Meine persönliche Meinung ist, ein optimaler Systemtakt ist das A & O für sichern Betrieb.
Wo ist der Sinn? Drücke Taste einmal pro Minute, Ergebnis an LED anzeigen, abfrage aber alle µs.
Ist schlimm für mich, wenn ich sehe, wie „schlampig“ ein MCU vergewaltigt:( wird.
Motto einiger, ich habe ja ein schnellen und großen Mega im Einsatz Muss ja viel besser sein .

Gruß
fredred

Peter(TOO)
24.11.2014, 21:41
Hallo fredred,

Aber eine kleine Erklärung versuche ich mal.
In der Digitaltechnik war viele Jahre die Betriebsspannung 5Volt der Standart. Die Zeit von L nach H oder umgedreht, reichten völlig aus bis zu 16MHz Systemtakte(Physikalisch bedingt) Nun haben wir aber nicht mehr so viel Zeit, wollen ja immer schneller werden. Die Zeit von 0 bis 5 Volt zu erreichen ist viel zu lang.
Das Problem nennt sich Flankensteilheit, also dU/dt, also wie schnell die Spannung ansteigt, bzw. abfällt.
Eine hohe Flankensteilheit ist zwar machbar, erzeugt dann aber hohe Stromimpulse in der Versorgungsspannung und macht mehr Probleme bei der Störstrahlung (EMV). Steilere Flanken erzeugen höhere Frequenzen (Oberwellen) und eine grösserer Spannungshub gibt diesen auch noch mehr Sendeenergie mit.


Nun kommt die neue Technologie 3,3 Volt als Betriebsspannung.
Die Flanken werden kürzer somit alles viel schneller. Bin mich sicher eine neue Technologie kommt, aber bei 1,7 Volt ist Schluss.
Nö, aktuelle PC-CPUs arbeiten heute schon mit Kernspannungen um 1V, meine RAMs im PC mit 1.4V.

Sinnvoll ist eine Norm mit um die 1V, dann reicht eine einzelne 1.2V NiMh-Zelle zum Betrieb. Die jetzigen Spannungen um 3V sind ideal für direkten Betrieb an eine Lithium-Zelle.



Der Maschinenzyklus(Takt) für MCU hat für Register lesen und schreiben, immer ein Zeitverhalten. Ein 100% es Digital = Zeit ist vernachlässigbar, werden wir wohl nicht mehr erleben.
Habe ich auch vor 40 Jahren nicht erlebt!
Ein typisches Problem war schon immer das Prellen eines Schalters in der Digitaltechnik.
Aber auch manche Schaltungen, welche das Laufzeitverhalten nicht berücksichtigt haben, erzeugen Spikes, also ungültige kurzzeitige Schaltzustände. Bei rein kombinatorischer Logik, konnte man das meist hinnehmen, bei sequenzieller Logik schalten da aber die Flip-Flops schon :-(
Da war das typische Problem ein asynchroner Zahler, welcher nicht binär zählen soll.

Probleme mit dem Oszillator hatte ich vor 20 Jahren mal mit dem NS16450/550 (UART).
NS machte da einen Die-Shrink, d.h. der Chip wird einfach optisch verkleinert, weil man eine neue Technologie mit kleineren Strukturen beherrscht. Da passen dann mehr Chips gleichzeitig auf einen Wafer, was natürlich die Herstellung vergünstigt. Bei CMOS werden dann aber auch die Transistoren schneller, da, unter anderem, auch die Gatekapazitäten kleiner werden.

Mein Effekt war, dass dann der Quarz-Oszillator manchmal auf eine Oberwelle schwang, was natürlich eine andere Baudrate ergab.
Toll war, dass die Kapazität des Oszilloskops gereicht hat, die Flankensteilheit zu verringern, sodass der Effekt beim Messen nicht auftrat :-(

Das Gemeine an der Geschichte war, dass schon um die 200 Geräte mit Chips vor dem Die-Shrink fabriziert wurden und problemlos funktionierten.

Naja, das gute daran war, dass ich so direkten Kontakt ins Entwicklungslabor von NS bekam und ein paar gute Fachgespräche möglich waren. Musste dann halt mit angeklebten 10pF am Ausgang des Oszillators raus gehen.
So nach einem dreiviertel Jahr bekam ich dann noch einen Anruf von NS, dass ab jetzt das Problem behoben sei.

MfG Peter(TOO)

fredred
25.11.2014, 11:27
Hallo Peter(TOO)

Danke für deinen Kommentar und wieder was dazu gelernt.
Ich bin kein Fachmann auf diesem Gebiet, wollte nur drauf Hinweisen, dass eine Übertaktung das Problem von demmy war.
Ich konnte nach einigen Abgleichs der Software auch kein Fehler finden.
Somit hatte ich nur noch die Idee, er soll mal den internen Oszillator(8MHz) für Softwaretest nutzen
(sein externer Takt mit 5 Volt Betriebsspannung war ja schon extrem).
Hat er gemacht und siehe da, kein Problem mehr.Einen 14,7456MHz externen Quarz eingebaut immer noch alles OK
Kein Softwarefehler.
Wie du es bestätigst das Laufzeitverhalten, nicht nur des MCU, sonder das gesamte Projekt sollt immer betrachtet werden.


Nö, aktuelle PC-CPUs arbeiten heute schon mit Kernspannungen um 1V, meine RAMs im PC mit 1.4V.

Die Bemerkung 1,7 Volt bezog sich auf die AT Mega IC’s.

Mit freundlichen Grüßen
fredred