Hallo ich möchte gerne den ADC 0-2 auslesen und in Variablen speichern um diese dann in die Register campare1a,compare1b und ocr2 zu schreiben und damit dann das PWM signal zu steuern. Ich weiß in meinem Code ist der ADC zur zeit auf 10bit eingestellt das werde ich aber später noch ändern auf 8bit sodas die Variablen in die Register passen. Bis jetzt habe ich einfach erstmal Werte in die 3 Register geschrieben um nachzuprüfen ob die PWM Signale funktionieren.Das klappt auch. Dann wollte ich auf dem Display erstmal die Werte von ADC0 ADC1 und ADC2 anzeigen lassen bis jetzt wird aber nur 0 angezeigt. In der ISR_ADC habe ich die ganzen if then drin, wenn das so nicht geht dann erklärt mir mal bitte wie man das macht. Ich poste einfach mal meinen Code bitte erschlagt mich nicht ich bin noch Anfänger. $regfile "m8def.dat " $crystal = 3689400 $baud = 9600 Config Adc = Single , Prescaler = Auto , Reference = Avcc Start Adc Enable Interrupts On Adc Isr_adc Dim W As Word , Channel As Byte Dim Adc0 As Word Dim Adc1 As Word Dim Adc2 As Word Channel = 0 Config Portd = Output Config Portc = Input Config Timer0 = Timer , Prescale = 1 Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 Config Timer2 = Pwm , Prescale = 1 , Compare Pwm = Clear Up , Pwm = On Pwm1a = 0 Pwm1b = 0 Ocr2 = 0 'Die Timer freigeben Enable Timer0 Enable Timer1 Enable Timer2 'Die Timer starten Start Timer0 Start Timer1 Start Timer2 'Timer Interrups On Timer0 Isr_timer0 On Timer1 Isr_timer1 On Timer2 Isr_timer2 Sreg.7 = 1 Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2 Config Lcd = 16 * 2 Cls Do Locate 1 , 1 Lcd "" ; Adc0 Locate 1 , 7 Lcd "" ; Adc1 Locate 2 , 1 Lcd "" ; Adc2 Loop End '----------------------------------------------------------------------- --- Isr_adc: W = Getadc(channel) If Channel = 0 Then Adc0 = W If Channel = 1 Then Adc1 = W If Channel = 2 Then Adc2 = W Incr Channel If Channel > 2 Then Channel = 0 Return '----------------------------------------------------------------------- ---- Isr_timer0: 'Mach irgendwas für was auch immer Return '----------------------------------------------------------------------- ---- Isr_timer1: Pwm1a = 50 Pwm1b = 10 Return '----------------------------------------------------------------------- ---- Isr_timer2: Ocr2 = 100 Return '----------------------------------------------------------------------- ----
ich denke, dass Getadc eine Wandlung auslöst, wenn die fertig ist gibts den ADC Interrupt, du wirst also ständig in deiner Routine bleiben.
> W = Getadc(channel)
Wenn du sowieso GETADC benutzt, wozu dann der Interrupt? (ABgesehen
davon, dass das so sowieso nicht geht. Der INterrupt würde aufgerufen
werden, wenn das ADC Ergebnis fertig ist, d.h. man benutzt dann gar
nicht mehr GETADC
Benutze GETADC einfach in der Hauptschleife und gut ists. Du brauchst
dafür keine Interrupts.
1 | Config Adc = Single , Prescaler = Auto , Reference = Avcc |
2 | Start Adc |
3 | |
4 | |
5 | Do |
6 | |
7 | Adc0 = GetADC( 0 ) |
8 | Adc1 = GetADC( 1 ) |
9 | Adc2 = GetADC( 2 ) |
10 | |
11 | Locate 1 , 1 |
12 | Lcd "" ; Adc0 |
13 | Locate 1 , 7 |
14 | Lcd "" ; Adc1 |
15 | Locate 2 , 1 |
16 | Lcd "" ; Adc2 |
17 | |
18 | Loop |
UNd die ganze INterruptbehandlung im Zusammenhang mit dem ADC wirfst du raus.
gib das in den Timer0 Interrupt Isr_timer0: W = Getadc(channel) If Channel = 1 Then compare1a = W If Channel = 2 Then compare1b = W Incr Channel If Channel < 2 Then incr channel else channel = 0 endif return den ADC Interrupt brauchst du nicht. Prescale 1 ist warscheinlich zu schnell, habs jetzt nicht nachgerechnet
Okay vielen dank Euch allen ich hatte auch alles in der Hauptschleife aber irgendeiner sagte mir mal sowas mach man im Interrupt.
So ich habe es jetzt so gemacht könnte mir einer genau erklären was getadc macht ich möchte die register selber schreiben. $regfile "m8def.dat " $crystal = 3689400 $baud = 9600 Adcsra = &B11000101 Admux = &B01000000 Dim W As Word , Channel As Byte Dim Adc0 As Word Dim Adc1 As Word Dim Adc2 As Word Channel = 0 Config Portd = Output Config Portc = Input Config Timer0 = Timer , Prescale = 8 Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 Config Timer2 = Pwm , Prescale = 1 , Compare Pwm = Clear Up , Pwm = On Pwm1a = 0 Pwm1b = 0 Ocr2 = 0 'Die Timer freigeben Enable Timer0 Enable Timer1 Enable Timer2 'Die Timer starten Start Timer0 Start Timer1 Start Timer2 'Timer Interrups On Timer0 Isr_timer0 On Timer1 Isr_timer1 On Timer2 Isr_timer2 Sreg.7 = 1 Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2 Config Lcd = 16 * 2 Cls Do Locate 1 , 1 Lcd "" ; Adc0 Locate 1 , 7 Lcd "" ; Adc1 Locate 2 , 1 Lcd "" ; Adc2 Waitms 20 Cls Loop End '----------------------------------------------------------------------- ---- Isr_timer0: W = Getadc(channel) If Channel = 0 Then Adc0 = W If Channel = 1 Then Adc1 = W If Channel = 2 Then Adc2 = W Incr Channel If Channel > 2 Then Channel = 0 Return '----------------------------------------------------------------------- ---- Isr_timer1: Pwm1a = 50 Pwm1b = 10 Return '----------------------------------------------------------------------- ---- Isr_timer2: Ocr2 = 100 Return '----------------------------------------------------------------------- ----
Basti schrieb: > So ich habe es jetzt so gemacht könnte mir einer genau erklären was > getadc macht Die BASCOM Hilfe. Du musst dir angewöhnen, dass die Hilfe des Herstellers deine erste Anlaufstelle ist. > ich möchte die register selber schreiben. Wozu? Genau aus dem Grund verwendest du doch BASCOM, damit du dich um diesen Kleinkram eben nicht selber kümmern musst. GETACD startet eine Wandlung, wartet bis sie fertig ist und holt das Ergebnis ab. Ich seh jetzt ehrlich gesagt nicht, warum das in einer Timer ISR passieren muss, aber seis drum.
Hi, man macht im Interrupt so wenig wie möglich aber vor allem wird deine Adc_isr nie aufgerufen weil die dann kommt wenn der ADC fertig ist. Die Ints für die PWM-Timer sind auch Quatsch. Es ist der Sinn der PWM, daß man zu beliebiger Zeit Pwm1a usw. setzt und den Rest macht der Timer alleine im Hintergrund. Die Timer-Ints kommen beim Überlauf des Timers, die brauchst Du gar nicht. Also: Do ADCs lesen PWM setzen Werte anzeigen Loop Fertig, Du brauchst keinen einzigen Int. Noch eleganter wäre es die drei Punkte jeweils in Gosubs zu machen. Hier ist das noch übersichtlich aber wenn es mehr wird ist das eleganter.
Ne mir ist klar das ich die ISR nicht brauche die hatte ich nur zum Testen mal mit eingebaut.Ich würde gerne die Register selber schreiben,weil ich irgendwann auf C umsteigen möchte.Bascom ist nur der erste Schritt.Ich habe das ganze jetzt so gemacht.So funktioniert es $regfile "m8def.dat " $crystal = 3689400 $baud = 9600 Adcsra = &B11000101 Admux = &B01100000 Dim W As Word , Channel As Byte Channel = 0 Config Portd = Output Config Portc = Input Config Timer0 = Timer , Prescale = 8 Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 Config Timer2 = Pwm , Prescale = 1 , Compare Pwm = Clear Up , Pwm = On Pwm1a = 0 Pwm1b = 0 Ocr2 = 0 'Die Timer freigeben Enable Timer0 Enable Timer1 Enable Timer2 'Die Timer starten Start Timer0 Start Timer1 Start Timer2 'Timer Interrups On Timer0 Isr_timer0 Sreg.7 = 1 Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2 Config Lcd = 16 * 2 Cls Do Loop End '----------------------------------------------------------------------- ---- Isr_timer0: W = Getadc(channel) If Channel = 0 Then Pwm1a = Adch If Channel = 1 Then Pwm1b = Adch If Channel = 2 Then Ocr2 = Adch Incr Channel If Channel > 2 Then Channel = 0 Return
Basti schrieb: > Ne mir ist klar das ich die ISR nicht brauche die hatte ich nur zum > Testen mal mit eingebaut.Ich würde gerne die Register selber > schreiben,weil ich irgendwann auf C umsteigen möchte. Dann steig auf C um. > W = Getadc(channel) > If Channel = 0 Then Pwm1a = Adch Das ist doch Schwachsinn. Getadc macht die ganze Arbeit und du holst dir dann hinten nach noch einmal das Ergebnis ab. Den ADC auf einen Kanal konfigurieren, ihn aktivieren, die Wandlung abwarten und das Ergebnis abholen, das sind 4 Schritte. Alles was du tust ist, du wiederholst den letzten (den einfachsten) dieser Schritte. Du bist im Brotberuf nicht zufällig Politiker? Die machen das auch so: andere für sich arbeiten lassen und dann so tun, als ob sie alles gemacht hätten. Wenn du an den ADC auf Registerebene rann willst, dann tu das. Aber dann tu es dann auch wirklich und richtig und schmück dich nicht mit fremden Federn, indem du GETADC die Arbeit machen lässt und hinten nach das Ergebnis noch einmal abstaubst.
Ja möchte ich ja selber machen ich habe das jetzt nur so gemacht wenn ich einfach GETADC benutze habe ich keine 8bit und diese passen dann auch nicht in den Timer für das PWM Signal oder nicht.Deswegen habe ich dann nur das Register ADCH nochmal gelesen.Ich würde ja Getadc weglassen das habe ich vorher versucht aber ich weiß nicht genau wie ich ADMUX und ADCSRA ansprechen muss.Was ich soweit bis jetzt verstanden habe ist das ich ja oben (config ADC) die erste Konversation gestartet habe mit ADC0 Dann muss ich warten bis das Ergebnis in den Registern steht.Ich habe den ADC (left adjust ) das heißt ADCH=0-255.Dann muss ich Admux den ADC1 wählen und wieder die Konversation starten.Ich hoffe ich habe das so richtig verstanden. Was mich jetzt interessieren würde wie ich in Bascom warten kann bis das Register ADCH ein Ergebnis hat PS ich hoffe ihr versteht mich!!!!
Basti schrieb: > Ja möchte ich ja selber machen ich habe das jetzt nur so gemacht wenn > ich einfach GETADC benutze habe ich keine 8bit sondern 10. ALso Werte von 0 bis 1023 > und diese passen dann > auch nicht in den Timer für das PWM Signal oder nicht. Du willst also Werte von 0 bis 255. Ist dividieren durch 4 wirklich so schwer (zumal das für den µC ein Klacks ist, einfach um 2 Bit nach links schieben und ich denke BASCOM hat sogar explizite Schiebeinstruktionen) > Was mich jetzt interessieren würde wie ich in Bascom warten kann bis das > Register ADCH ein Ergebnis hat Wenn du sowieso nach C willst: AVR-GCC-Tutorial Auch das AVR-Tutorial wird hilfreich sein In beiden Tutorien gibt es einen Abschnitt über den ADC und wie das funktioniert. Da sind die Register, die Bits in den Registern und in welcher Reihenfolge was zu machen ist. Selbst wenn du nicht in C oder Assembler programmierst sind sie hilfreich, denn die Vorgehensweise ist absolut identisch. Nur die Schreibweise ist ein wenig anders.
Basti schrieb: > Was mich jetzt interessieren würde wie ich in Bascom warten kann bis das > Register ADCH ein Ergebnis hat Du startest im Single Mode eine Wandlung mit ADSC = 1 und wartest solange bis ADSC wieder 0 ist. Dann ist die Wandlung fertig.
Ja das mit dem Devidieren kenne ich dachte sowas sei nicht so gut.Hatte gedacht wenn ich direkt das ADCH nehme sei besser
Basti schrieb: > Ja das mit dem Devidieren kenne ich dachte sowas sei nicht so gut.Hatte > gedacht wenn ich direkt das ADCH nehme sei besser Mit Verlaub: Aber wenn du den letzten Taktzyklus aus dem µC herausholen willst, dann fang damit an, nicht BASCOM zu benutzen. BASCOM ist zum schnellen Entwickeln super. Aber so wie in jeder Hochsprache bleibt immer ein bischen was auf der Strecke. Gott sei Dank, kommt es aber nur selten auf den letzten einzusparenden Taktzyklus an, so dass man sich ein bischen Schwund immer leisten kann. Ob dein µC jetzt 95% oder 94.8% seiner Zeit Däumchen dreht und das LCD vollkleistert, spielt keine wirkliche Rolle. Wie schon gesagt: wenn du dem Compiler nicht traust, dass er eine Division durch 4 mittels Schieben realisiert, dann kannst du ja auch die Schiebebefehle von BASCOM direkt benutzen. Besser ist immer relativ: Es ist relativ sinnfrei, GETADC ein 10 Bit Ergebnis fertig herrichten zu lassen, nur um es dann zu verwerfen und seinen eigenen Zugriff zu machen.
Könnte das ganze dann so aussehen?? Isr-Timer0 If ADCSRA.6 = 0 then ADC0= ADCH Admux=&B01100001 ADCSRA.6=1 if adcsra.6 = 0 then adc1 = adch usw.
Basti schrieb: > Könnte das ganze dann so aussehen?? > Nein. Was musst du tun? Du musst das ADSC Bit (welches Bit 6 ist) auf 1 setzen (Siehe Datenblatt oder die Tutorien) dann musst du warten, bis das ADSC Bit wieder auf 0 zurückfällt. (SIehe Datenblatt oder die Tutorien) Dann kannst du dir das Ergebnis abholen (Siehe Datenblatt oder die Tutorien) ADCSRA.6 = 1 ; bit auf 1 WHILE ADCSRA.6 = 1 ; warten bis es nicht mehr 1 ist WEND adc1 = ADCH ; wert abholen
Danke das ist was ich brauchte (while) jetzt hab ich es verstanden vielen lieben dank
So hoffe so habe ich das jetzt richtig funktionieren tut es so Isr_timer0: Admux = &B01100000 Adcsra.6 = 1 While Adcsra.6 = 1 Wend Pwm1a = Adch Admux = &B01100001 Adcsra.6 = 1 While Adcsra.6 = 1 Wend Pwm1b = Adch Admux = &B01100010 Adcsra.6 = 1 While Adcsra.6 = 1 Wend Ocr2 = Adch return
Karl Heinz Buchegger schrieb: > ADCSRA.6 = 1 Karl Heinz, man kann in Bascom Register zusammen mit Bitnamen verwenden, das erspart die kryptische Bitabzählerei, also: ADCSRA.ADSC = 1
Basti schrieb: > Isr_timer0: > Admux = &B01100000 Wurde Dir schon gesagt, dass es keine gute Idee ist, in der ISR zu wandeln und damit zu warten ? Wenn ich mich nicht verrechnet hab', dürfte das bei angenommenen 200kHz ADC-Clock so ca. 35% der verfügbaren Rechenleistung kosten. 1 /(200000 : 13 : 3) = 195µs pro Wandlung bei 3689400 = 719 µC-Clocks Abstand zwischen den Timer0-Aufrufen: 256 x 8 = 2048 µC-Clocks Ergibt +35% Auslastung. Basti schrieb: > Ja danke gut zu wissen geht das auch irgendwie mit den Mux Registern > einfacher Die Kenntnis darum ist auch in C weiterverwendbar, nur die Syntax ist da etwas anders.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.