PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zwei AD im Hintergrund.



Gento
01.05.2006, 22:39
Bis vor 12 Wochen konnte ich kein Bascom und nun stehe ich vor einem kleinen Problem/Aufgabe?

Ich schrieb sonst für die C-Control Main Unit 2.0 in Basic ++ , aber durch Lieferprobleme der CC ,schwang ich auf Mega 32 um und habe auch Pingleiche Module entwickelt.

Erstmal Auszug des Codes:

$regfile = "m32def.dat"
'$framesize = 32
'$swstack = 32
'$hwstack = 32

$crystal = 16000000
$baud = 9600


Config Lcd = 20 * 2

Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.6 , Rs = Portb.5

Config Adc = Single , Prescaler = 32 , Reference = Avcc 'Prescaler = Auto '32'


Declare Sub Ad_wandlertest()

Const A_ad = 0
Const B_ad = 1

Dim A As Word
Dim B As Word

'-------------------------------------------------------------------------------
Initlcd
Cls
Waitms 100
Start Adc
'-------------------------------------------------------------------------------
Do
Call AD_wandlertest()
Locate 1,1
LCD "A : ",A
Locate 2,1
LCD "B : ",B
Loop
'---------------------------------------------------------------------------------
Sub Ad_wandlertest()
A = Getadc(x_ad)
B = Getadc(y_ad)
End Sub
'----------------------------------------------------------------------------------


Das ist nur ein Auszug von z.Z. ca 16 K.

Nun meine Frage :
Kann ich im Hintergrund die AD's einlesen lassen ohne Call und in A,B schreiben lassen?

Das jenes per IRQ geht ist mir klar, bei einem.
Aber zwei im Hintergrung?

Erspare ich mir viele CPU Takte AD abwarten damit ..... ?

könnte bitte jemand dahingehend den Code editieren ?

lg Gento

gpo
02.05.2006, 17:49
Hallo :-k Gento,

auf den ersten Blick: Um Prozessortakte und Speicherplatz zu sparen, lass die Sub-Programme weg. Hab jetzt keine Zeit, um darauf näher einzugehen, man möge mir verzeihen. Ach ja, was macht die Laserei? In Deinen Code sehe ich "x_ad" und "y_ad", also sieht doch sehr nach Laser aus. Erzähle doch genau Dein Vorhaben und Deine (Echt)Zeitanforderung, dann kann Dir sicher besser geholfen werden.

Gruß
Günter (ich kenne Dich nicht persönlich, bin aber auch ein Laserfreak)

RHS
02.05.2006, 18:18
@Gento,

Du könntest einen Timer-IRQ laufen lassen, der bspw. jede
Sekunde aufgerufen wird und dann die ADC's ausliest oder
besser noch nur ein Bit-Flag setzt, welches Du dann in Deiner
Main-Loop auswertest (Flag gesetzt = ADC's auslesen).

Gento
02.05.2006, 19:37
Ich hatte eher im Bereich 0,1 milli Sek gedacht :-& die paare einlesen.

@RHS

Ratber
02.05.2006, 23:41
Du kannst die ADC's manuell bedienen.
also über ihre Regtister und per IRQ dann einlesen.

Das hat den Vorteil daß das Programm nicht groß warten muß da ja erst am Ende des Wandlungsvorganges die beiden Registerpaare kurz übertragen werden.

sieht nach mehr Code aus aber ist unterm Strich nur etwas Tipparbeit

RHS
03.05.2006, 10:30
@Gento,

mit der Sekunde war ja nur ein Beispiel.

Letztendlich bestimmt ja auch Dein sonstiges Programm,
wie lange Du Zeit hast. Allerdings sind 0,1 ms = 100 µs
schon ziemlich häufig, so das Du Dich am besten an Ratber's
Vorschlag orientierst um Wartezeiten möglichst zu minimieren.

Ratber
03.05.2006, 15:32
Ja,da bin ich mir auch nicht sicher gewesen ob er "Alle 100µS Einlesen" oder "Innerhalb von 100µS Einlesen" meint.


Bei ersterem macht sich die Zeitersparnis natürlich stark bemerkbar da je jeder Takt zählt.

Gento
03.05.2006, 16:22
Precaler 32 = 0,105 mSek für je eine a + b AD-Wandlung

Das habe ich ermittelt wenn ich Call AD_wandlertest() ständig nur aufrufe.
Die Werte sind sehr Constant dabei.

Frage a) Kann ich die AD im Hintergrund laufen lassen ohne das er zuviel CPU Takte verbraucht. 2-5 K je Sekunde würden auch reichen.

Frage b) Da ich noch nicht lange Bascom mache könnte jemand ein Beispiel mit 2 AD im Hintergrund einlesen texten ?

Danke
&
Gruß Gento

Ratber
03.05.2006, 16:48
Zu "A":

Der AD-Wandler arbeitet im Grunde eh die meiste Zeit im Hintergrund.
Er bekommt seinen takt,der aus dem Systemtakt abgeleitet wird, und wandelt eigentständig.

Nur für den Start der Wandlung und das ablesen des Ergebnisses muß man zugreifen.

Bascom würde mit Getadc natürklich schön brav warten bis er fertig ist.
Wenn due dazu noch mit "Single Conversion" arbeitest dann dauerts so ziemlich am längsten da Bascom von anfang bis ende der Conversion wartet.

Wie gesagt kannst du es besser machen indem du ihn rechtzeitig startest (Conversionsbit im Steureregister setzen) und dir dann irgendwann das Ergebnis aus beiden Registern ausliest.
Dazwischen kann deine Soft machen was se will.

Um es nochmal zu verdeutlichen:

Du = Meister mit 2 Aufgaben.
1. Beleuchtungsstärke im Raum Messen.
2. Protokollieren der Werte.
Dir zur Seite steht ein Lehrling der das Luxmeter in der Hand hält.

Methode 1. (Bascom standard mit Getadc):
===========================
1:Du haust den Azubi an "Messwert bitte".
2:Er schaut nach
3:Er sagt dir den Wert.
4:Du schreibst auf
5: Goto 1

Wärend Punkt 2 mußt du warten bis er gemessen hat.

Methode 2. (Verfeinert)
==================
Der Azubi misst ständig neu und sagt auch immer den Wert an.
Dein Programm verkürzt sich auf .

1: Du kannst sofort den letzten Wert aufschreiben den der Azubi genannt hat.
2: Goto 1



Ich hoffe mal das war deutlicher.




Zu "B" :

Das Thema hatten wir schonmal vor einigen Monaten und da war auch ein schönes Beispiel dabei.
Such mal danach hier in "Programierung in Bascom"

Wenn de nix findest dann muß ich das mal raussuchen.

hrei
03.05.2006, 21:10
Hallöchen,

also direkt über die Register zu gehen, ist natürlich möglich und auch ganz hübsch und man hat die höchstmögliche Kontrolle, allerdings auch nicht flotter als Bascom im FREE Modus:



'$regfile = "m8def.dat"
$regfile = "m168def.dat"
'$regfile = "m32def.dat"
$crystal = 7372800
'$crystal = 14745600
'$crystal = 16000000

$baud = 9600

$hwstack = 64
$swstack = 64
$framesize = 64

$lib "mcsbyteint.lbx"
Config Adc = Free , Prescaler = Auto
Config Pind.3 = Output

Dim Value0 As Word
Dim Value1 As Word
'-------------------------------------------------------------------------------
nop
nop
nop
nop
nop
Start Adc

Do
Set Portd.3 'ggf. für Oszi-überwachung
Value0 = Getadc(0)
Value1 = Getadc(1)
Reset Portd.3
Loop
nop
nop
nop
nop
End

'Im FREE Modus (ADC triggert sich ständig selbst) ------------------------------
'
'kurz und knackig, allerdings werden u.U. Werte mehrmals gelesen...

'+0000005a : 9170007a Lds R23 , 0x007a Load Direct From Data Space
'+0000005C: 6870 ORI R23,0x80 Logical OR with immediate
'+0000005D: 9370007A STS 0x007A,R23 Store direct to data space
'
'
'+0000005F: 9A5B SBI 0x0B,3 Set bit in I/O register
'+00000060: E080 LDI R24,0x00 Load immediate
'+00000061: 9380007C STS 0x007C,R24 Store direct to data space
'+00000063: 91800078 LDS R24,0x0078 Load direct from data space
'+00000065: 91900079 LDS R25,0x0079 Load direct from data space
'+00000067: E0AF LDI R26,0x0F Load immediate
'+00000068: E0B1 LDI R27,0x01 Load immediate
'+00000069: 938D ST X+,R24 Store indirect and postincr
'+0000006A: 939C ST X,R25 Store indirect
'+0000006B: E081 LDI R24,0x01 Load immediate
'+0000006C: 9380007C STS 0x007C,R24 Store direct to data space
'+0000006E: 91800078 LDS R24,0x0078 Load direct from data space
'+00000070: 91900079 LDS R25,0x0079 Load direct from data space
'+00000072: E1A1 LDI R26,0x11 Load immediate
'+00000073: E0B1 LDI R27,0x01 Load immediate
'+00000074: 938D ST X+,R24 Store indirect and postincr
'+00000075: 939C ST X,R25 Store indirect
'+00000076: 985B CBI 0x0B,3 Clear bit in I/O register
'+00000077: 940C005F JMP 0x0000005F Jump



'Im SINGLE Modus --------------------------------------------------------------
'Hier wird's dann lang und umständlich, dafür ist aber das Ergebnis garantiert
'richtig.


'+0000005A: 9170007A LDS R23,0x007A Load direct from data space
'+0000005C: 6870 ORI R23,0x80 Logical OR with immediate
'+0000005D: 9370007A STS 0x007A,R23 Store direct to data space
'+0000005F: 9A5B SBI 0x0B,3 Set bit in I/O register
'+00000060: E080 LDI R24,0x00 Load immediate
'+00000061: 9380007C STS 0x007C,R24 Store direct to data space
'+00000063: 940E0084 CALL 0x00000084 Call subroutine
'+00000065: E0AF LDI R26,0x0F Load immediate
'+00000066: E0B1 LDI R27,0x01 Load immediate
'+00000067: 938D ST X+,R24 Store indirect and postincr
'+00000068: 939C ST X,R25 Store indirect
'+00000069: E081 LDI R24,0x01 Load immediate
'+0000006A: 9380007C STS 0x007C,R24 Store direct to data space
'+0000006C: 940E0084 CALL 0x00000084 Call subroutine
'+0000006E: E1A1 LDI R26,0x11 Load immediate
'+0000006F: E0B1 LDI R27,0x01 Load immediate
'+00000070: 938D ST X+,R24 Store indirect and postincr
'+00000071: 939C ST X,R25 Store indirect
'+00000072: 985B CBI 0x0B,3 Clear bit in I/O register
'+00000073: 940C005F JMP 0x0000005F Jump
'+00000075: 0000 NOP No operation
'+00000076: 0000 NOP No operation
'+00000077: 0000 NOP No operation
'+00000078: 0000 NOP No operation
'+00000079: 94F8 CLI Global Interrupt Disable
'+0000007A: CFFF RJMP PC-0x0000 Relative jump
'+0000007B: 9731 SBIW R30,0x01 Subtract immediate from word
'+0000007C: F7F1 BRNE PC-0x01 Branch if not equal
'+0000007D: 9508 RET Subroutine return
'+0000007E: 9468 SET Set T in SREG
'+0000007F: F862 BLD R6,2 Bit load from T to register
'+00000080: 9508 RET Subroutine return
'+00000081: 94E8 CLT Clear T in SREG
'+00000082: F862 BLD R6,2 Bit load from T to register
'+00000083: 9508 RET Subroutine return
'+00000084: 9180007A LDS R24,0x007A Load direct from data space
'+00000086: 6C80 ORI R24,0xC0 Logical OR with immediate
'+00000087: 9380007A STS 0x007A,R24 Store direct to data space
'+00000089: 9180007A LDS R24,0x007A Load direct from data space
'+0000008B: FD86 SBRC R24,6 Skip if bit in register clear
'+0000008C: CFFC RJMP PC-0x0003 Relative jump
'+0000008D: 91800078 LDS R24,0x0078 Load direct from data space
'+0000008F: 91900079 LDS R25,0x0079 Load direct from data space
'+00000091: 9508 RET Subroutine return
'+00000092: 0078 ??? Data or unknown opcode
'+00000093: 91900079 LDS R25,0x0079 Load direct from data space
'+00000095: 9508 RET Subroutine return


An den NOPS bitte nicht stören, die sind nur drin, damit ich die richtige Stelle im Disassembler schnell finde.

Kommt man mit 8 Bit Auflösung aus, kann das nochmal deutlich flotter werden (Leftadjust wählen und nur ADCH auslesen). Im FREE-Modus kommt man auf max ~ 15kHz Abtastrate, mit 8Bit pi mal Daumen auf max. ~ 22 kHz.

Grüße
Henrik