PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Variable in Funktion übergeben!?



BASTIUniversal
03.03.2006, 13:03
Hallo!
Ich hab da ein kleines Problem mit einer Function. Ich möchte, je nach dem was über die SPI-Schnittstelle angekommen ist, einen ADC auslesen.
Da ich 3 Werte des ADC auslesen möchte und einen Mittelwert daraus berechnen will, hab ich mir gedacht das ich dafür eine Funktion benutze (hab ich bisher noch nie gemacht).
In der Simulation klappt das aber nicht so recht, hier mal ein paar Code-Fetzen:


Declare Function Adcx(byval Adcnummer As Byte) As Byte
.
.
Adcsr = &B10000101 'ADC konfigurieren
.
.
Select Case A 'Je nachdem was über SPI gekommen ist...
Case 0 : C = Adcx(32)
Case 1 : C = Adcx(&B00100001)
End Select
.
.
Function Adcx(byval Adcnummer As Byte) As Byte

Local B0 As Byte , B1 As Byte , B2 As Byte , B3 As Byte , B4 As Byte
Local X0 As Byte

Admux = Adcnummer
X0 = 0

For B4 = 0 To 2

Adcsr.adsc = 1

While Adcsr.adif = 0
Wend

Select Case B4
Case 0 : B1 = Adch
Case 1 : B2 = Adch
Case 2 : B3 = Adch
End Select

Next

B0 = B1 + B2
B0 = B0 + B3
B0 = B0 / 3

Adcx = B0


End Function

Laut dem Simulator von Bascom wird anstatt der Zahl "32" nur "186" übergeben, und das Bit im Register Adcsr.adsc (also ADC Starten) wird auch nicht gesetzt.
In folge dessen kommt das Programm auch nicht mehr aus der While...Wend Schleife (wenn der ADC nicht läuft kann das Flat Adif auch nicht gesetzt werden).
Kann ich überhaupt Zahlen in eine Function übergeben und dort Register ändern?

MfG
Basti

PicNick
03.03.2006, 13:09
Du wirst setzen müssen

$SWSTACK = 64 '(schätzwert)
$FRAMESIZE = 24 '(schätzwert)

Mit den defaultwerten kommst du da nicht durch


EDIT: wenn du auch noch Interrupts verwenden willst:
$HWSTACK = 64 '(schätzwert)

BASTIUniversal
03.03.2006, 13:48
Danke, funktioniert...nur sind die 128Byte SRAM (ATTiny26) nicht genug für so viele Variablen.
Muss wohl ein wenig improvisieren...

PicNick
03.03.2006, 14:15
Mach aus deinen "LOCAL" "DIM" , das spart mächtig Platz
Aber jetzt weißt du, worum's geht. Das kriegst du schon hin

oe9vfj
04.03.2006, 10:51
Bei den begrenzten SRAM-Möglichkeiten des ATTiny26 würde ich auf die Verwendung von Functions mit byval Parameter-Übergabe und einigen internen Variablen verzichten und anstatt dessen mit einem GOSUB - RETURN Konstrukt arbeiten.

Bei der Durchsicht Deines Programmes sind mir einige Dinge aufgefallen:

Warum verwendest Du nicht die BASCOM-Funktion GETADC(channel)?

Du stellst den ADC auf linksbündige Ausgabe und verwendest nur das High-Byte der Ausgabe und machst aus einem 10Bit AD-Wandler einen 8-Bit AD-Wandler und verschenkst damit 2 Bit der Auflösung?

Das High-Byte der linksbündigen ADC Ausgabe kann den höchsten Wert 255 haben. Du zählst 3 solcher Ausgaben in einer Byte Variablen zusammen um daraus einen Mittelwert zu bilden. Sofern die Summe aller 3 Ausgaben größer als 255 wird, hast Du einen Overflow und damit ein falsches Ergebnis?

Wenn Du zur Mittelwertbildung für die Sample-Anzahl eine 2-Potenz Zahl nimmst wie 2, 4, 8, .... kannst Du die Division durch eine Shift rechts Operation ersetzen. Shift Right,1 ist dividiert durch 2, Shift Right,2 ist dividiert durch 4, Shift Right, 3 ist dividiert durch 8 usw.
Eine Shift-Operation ist nicht nur wesentlich schneller als eine Division sondern braucht auch weniger Programm-Speicher.

Schau Dir mal folgender Code an (nicht auf Hardware getestet)


Config Adc = Single , Prescaler = Auto

Start Adc


Dim ADCNum as Byte
Dim wADCWert as Word
Dim bADCWert as Byte
Dim bCounter as Byte

ADCNum = 0 ' Kanal setzen


Gosub HoleADC

' End



HoleADC:
wADCWert = 0
' 4 AD-Werte einlesen und Mittelwert bilden
For bCounter = 1 to 4
wADCWert = wADCWert + getADC(ADCNum)
next

' Hier könnte man wADCWert als Pseudo-12Bit-Wandlung verwenden
' RETURN


' oder in einen 10Bit Wert umwandeln (Mittelwert bilden)
' Shift wADCWert, Right, 2
' Return


' oder wenn es ein Byte-Wert sein muss (8Bit)

Shift wADCWert, Right, 4
bADCWert = wADCWert

RETURN

BASTIUniversal
04.03.2006, 17:19
Hallo!
Also, die GetADC Funktion verwende ich nicht, weil bei einem Testlauf das ganze nicht funktioniert hat (mit der manuellen Eingabe tut's aber, die SPI-Befehle funktionieren auf meinem Tiny26 auch nicht).
Die 2 Bit verschenke ich, weil das ganze sowieso um 4-5 LSB rauscht (was aber an der aktuellen Betriebsweise über nen 100Ohm "Sicherheitswiderstand" liegt) und das Übertragungsprotokoll über SPI einfacher ist.
Das mit dem Byte/Word fehler hab ich auch bemerkt und muss ich noch ändern.

Das mit dem Shift Right wusste ich noch nicht, muss ich mal ausprobieren (hab aber beim Testen meinen Tiny gegrillt) :-)