Hallo, ich habe ein Problem mit der Berechnung der Werte des A/D-Wandlers. Momentan bin ich dabei ein Beispielprogramm in MPLAB mit dem C30 Compiler zu schreiben. Dabei verwende ich MPLAB Sim als Simulator. Nun mein Problem. Ich lese am ADCBUF0 einen Wert über den Stimulus ein. Dieser Wert wird mir auch im entsprechenden Register im Watch Window angezeigt. Diesen Wert möchte ich dann weiterverarbeiten und über den UART ausgeben. Leider habe ich inzwischen keine Idee mehr, wie ich den eingelesenen Wert berechne, so dass ich später im SIM UART1 den richtigen Wert angezeigt bekomme. Bsp.: Ich lese über die Datei ADC.txt im ADCBUF0 eine 5 (dezimal) ein. Dann zeigt mir das Watch Windoe für den ADCBUF0 als HEX 0x0005 und DEC 5 an. Wenn ich diesen Wert in das U1TXREG schiebe gibt mir das UART Sim richtigerweise den entsprechenden ASCII Wert für 05 aus. Wie führe ich jetzt die Berechnung durch, dass ich in das U1TXREG entsprechend meinen 5V Spannung, die ich ausgegeben habe eine 0x0035 schiebe und damit im UART Sim eine 5 angezeigt bekomme? Das simpelste ist natürlich, dass ich dem Wert 0x0005 mit 0x0030 addiere nur kann ich mir nicht vorstellen, dass das funktioniert, wenn ich später mit einem dsPIC 30F4012 eine Spannung messen möchte. Vor allem 5V ist momentan das Bsp. Wie mache ich das bspw. für 1,5V? Hat jemand noch ein Beispiel zur Verwendung der uart.h? Hier mein bisheriger Programmcode. #include <p30fxxxx.h> #include <delay.h> _FOSC(CSW_FSCM_OFF & HS); _FWDT(WDT_OFF); _FBORPOR(MCLR_EN & PWRT_OFF); _FGS(CODE_PROT_OFF); int main (void); void lars (void); int main (void) { // Setze alle Ports als Ausgang TRISB = 0; TRISC = 0; TRISD = 0; TRISE = 0; TRISF = 0; TRISBbits.TRISB2 = 1; ADPCFG = 0xFFFF; ADPCFGbits.PCFG2 = 0; ADCON2bits.VCFG = 3; ADCON3bits.ADRC = 1; ADCON3bits.ADCS = 0; ADCON2bits.CHPS = 0; ADCON1bits.SIMSAM = 0; ADCSSL = 0x0000; ADCHS = 0x0002; ADCON1bits.SSRC = 7; ADCON3bits.SAMC = 1; ADCON1bits.FORM = 0; ADCON2bits.SMPI = 0; ADCON1bits.ADON = 1; U1BRG = 0x0081; U1MODEbits.PDSEL = 0; U1MODEbits.STSEL = 1; while(1) { //lars(); int ADC; ADCON1bits.SAMP = 1; Delay_1S_Cnt; ADCON1bits.SAMP = 0; while(!ADCON1bits.DONE); ADC = ADCBUF0; U1MODEbits.UARTEN = 1; U1STAbits.UTXEN = 1; U1TXREG = ADC; U1MODEbits.UARTEN = 0; } return 0; } Danke für die hoffentlich zahlreiche Hilfe. Gruß Lars
Hallo Lars für die Hex-ASCII UMwandlung gibts in der Bibliothek die sprintf-Funktion, oder falls dir sprintf zu viele Resourcen kostet schreib dir selber ein itoa() Gerhard
Der aus dem A/D Wandler gelesene "Rohwert" sollte erst mit einem passenden Skalierungsfaktor multiplizirt werden bevor man ihn ausgibt, dann kann auch z.B. 5V einem Wert von 317 entsprechen.
@all Danke für die schnellen Antworten. @ Gerhard werde ich mal suchen und schauen, wieviel Platz das benötigt. @ Dieter Ich dachte an die Formel: Messwert * (Refspannung/1024) bei 10 Bit Wandlung, nur habe ich wohl irgendwie "nen Brett vorm Kopf", weil ich es dann nicht wieder als Ausgabe umgerechnet bekomme. @ Zoch Ich muss den dsPIC rechnen lassen, weil er in einem Messgerät eingesetzt werden soll, welches in aller letzter Konsequenz die berechneten Werte auf nem LCD anzeigt. Möchte das bloß jetzt testweise dann über die UART an den PC schicken. Muss hinterher auch noch ne FFT auf die Werte basteln, da ich aus den gewandelten Werten den Frequenzanteil brauche. Aber ich möchte alles schrittweise aufbauen und dazu gehört als erstes für mich, die AD-Wandlung und dann die Ausgabe über UART an den PC. Über weitere Tipps bin ich dankbar. Danke Lars
Hallo Lars Zuerst skalierst du den Messwert so, dass du bei 5V den Wert 500 erhälst (bei 3.3V Eingang hast du dann 330 usw). Diesen Wert rechnst du nun durch 100 und bekommst die Hunderter. Dazu addierst du 0x30 und hast den ASCII Wert für die Hunderter. Dann zählst du vom skalierten Messwert die Hunderter*100 ab und teilst durch 10 - so bekommst du die Zehner, wieder + 0x30 und du hast den ASCII Wert usw. bis zu den Einern. Zwischen dem Hunderter und dem Zehner-ASCII Wert sendest du noch den Dezimalpunkt und der PC wird 5 . 0 0 erhalten. Gruss Andi
Hallo, danke nochmal für die Vorschläge und Antworten. Ich habe das Problem jetzt anders lösen können. Es geht mit der printf-Funktion. Es gibt aber einen Bug in der 2.04/2.05 Release der Software und deswegen konnte ich printf nicht nutzen. Hier ein Link der den Bug beschreibt: http://forum.microchip.com/printable.aspx?m=116714 Ich hatte das gleicht Problem, wie nau001133, aber die Antwort von cawilkie hat geholfen. Mein Code sieht jetzt so aus: #include <p30fxxxx.h> #include <dsp.h> #include <stdio.h> #include <delay.h> #include <math.h> #include <libpic30.h> _FOSC(CSW_FSCM_OFF & HS); _FWDT(WDT_OFF); _FBORPOR(MCLR_EN & PWRT_OFF); _FGS(CODE_PROT_OFF); int U2MODEbits; int U2TXREG; int U2BRG; int U2STAbits; int main (void); void lars (void); int main (void) { // Setze alle Ports als Ausgang TRISB = 0; TRISC = 0; TRISD = 0; TRISE = 0; TRISF = 0; TRISBbits.TRISB2 = 1; ADPCFG = 0xFFFF; ADPCFGbits.PCFG2 = 0; ADCON2bits.VCFG = 3; ADCON3bits.ADRC = 1; ADCON3bits.ADCS = 0; ADCON2bits.CHPS = 0; ADCON1bits.SIMSAM = 0; ADCSSL = 0x0000; ADCHS = 0x0002; ADCON1bits.SSRC = 7; ADCON3bits.SAMC = 1; ADCON1bits.FORM = 0; ADCON2bits.SMPI = 0; ADCON1bits.ADON = 1; U1BRG = 0x0081; U1MODEbits.PDSEL = 0; U1MODEbits.STSEL = 1; while(1) { //lars(); double ADC; ADCON1bits.SAMP = 1; Delay_1S_Cnt; while(!ADCON1bits.DONE); ADC = ADCBUF0; ADCON1bits.SAMP = 0; ADC = ADC*5/1023; printf("%f \n", ADC); } return 0; } Gruß Lars
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.