Guten Tag,
aktuell bin ich an einem Projekt für das es nötig ist zwei Spannungen zu
vergleichen.
Die eine Spannung ist konstant und die andere kann schwanken. Sollte
diese Spannung schwanken soll die über LEDs angezeigt werden.
Nun zu meinem Problem:
Es ist völlig egal was am PIC an Spannung anliegt. Er gibt für jede
Spannung den gleichen Wert aus. Ich hatte mal ein kleines Programm was
lief, wiederrum gab es da noch Probleme mit einer externen Hardware,
welche die Spannungen liefert. Dieses Problem ist nun behoben aber das
Programm funktioniert nicht mehr bzw. der PIC liefert falsche
Ergebnisse.
Merkwürdig ist, dass wenn ich das AD1CON3 register ändere sich auch der
Ergebnis der Convertierung ändert.
Beispiel:
AD1CON3 = 0b0000000100000010; : ADCrefValue = ADCValue = 127
AD1CON3 = 0b0001111100000111; : ADCrefValue = ADCValue = 0
AD1CON3 = 0b1001111100000010; : ADCrefValue = ADCValue = 1023
Hier ist der Code von meinem Testprogramm was nur dazu dient um zu
schauen ob der PIC die Spannung korrekt umconvertiert.
#include <p24FJ64GB106.h>
#include <stdio.h>
#include <stdlib.h>
_CONFIG1 (FWDTEN_OFF) //Watchdogtimer off
int main(void)
{
int ADCrefValue = 0;
PORTB = 0b0000000000000000;
TRISB = 0b1111111111111001; //RB1-2 = Output, RB0/3-15 = Input
AD1CON1 = 0b0000000011100000; // SSRC<2:0> = 111 implies internal
counter ends sampling and starts converting.
AD1CON2 = 0b0010000000000000; // Vr+ = Vref+
AD1CON3 = 0b1001111100000010; // Sample time = 31Tad, Tad = 3Tcy
AD1PCFG = 0b1111111111100110; // AN0, AN3 & AN4 as Analog Input
AD1PCFGL = 0b1111111111100110; // AN0, AN3 & AN4 as Analog Input
AD1PCFGH = 0b0000000000000011;
AD1CSSL = 0b0000000000000000;
AD1CSSH = 0b0000000000000000;
AD1CHS = 0b0000000000000011; // Negative Input Vr-, analog signal
from PIR (MUX A = AN4)
AD1CON1bits.ADON = 1; //Turn on ADC
while (1) // repeat continuously
{
AD1CON1bits.SAMP=1; //start sampling
while(!AD1CON1bits.DONE); //conversion done?
AD1CON1bits.SAMP=0; //start sampling
ADCrefValue = ADC1BUF0; //yes then get ADC value
if (ADCrefValue > 300){
PORTB = 0b0000000000000110;
}
else
PORTB = 0b0000000000000010;
} // repeat
}
In diesem Fall liegt der Wert den der PIC einliest knapp über 300 (es
leuchten beide LEDs an RB1 und RB2) aber auch hier ist es egal wie hoch
die Spannung ist (auch wenn garkeine Spannung an dem PIN anliegt ist das
Ergebnis wie sonst auch). Ich hab leider keine andere Möglichkeit mir
den Wert der in ADC1BUF0 steht anders als über die beiden LEDs
anzuzeigen.
Besteht vllt. die Möglichkeit der der interne AD-Converter defekt ist?
Ich würde mich über jede Art von Hilfe sehr freuen.
Danke schonmal im Vorraus.
Gruß Alex
Erstmal Danke Andreas.
Leider klappt es so auch nicht.
Erst habe ich mal eine Frage:
Kann ich den Inputchannel für den ADC überhaupt ändern wenn der ADC
eingeschaltet ist? Weil zuerst wird bei dir die initADC aufgerufen, in
der der ADC eingeschaltet wird, und dann wird erst der Channel
ausgewählt welchen der ADC auslesen soll.
Bei deim ersten Beispiel hängt der PIC dann vor dem "while (TMR1< 100);
// 6.25 us" und geht an dort nicht weiter.
Muss der Timer noch besonders initialisiert werden?
Beim 2ten Beispiel bekomme ich wieder den Wert "0" raus.
Ich hab auch die Beispiele von Microchip selbst versucht aber bei denen
ist das gleiche Bild :(
Hat jemand vllt. mal ein ähnliches Problem gehabt und eine Lösung bzw.
weitere Vorschläge?
Hallo,
bei mir funktioniert folgender Code auf einem PIC24FJ256GA110 mit dem
C30 Compiler.
Ich habe Autosampling gewählt damit ich irgendwo im Code den AD-Wert aus
dem register ADC1BUF3 lesen kann.
1
voidADC_Init(void)
2
{
3
AD1PCFGLbits.PCFG3=0;// AN3 PIN Analogfunktion
4
TRISBbits.TRISB3=1;// Input
5
6
// Analogwert lesen von ADC1BUF3 !!!!
7
8
AD1CON1bits.FORM=0b00;// integer format
9
AD1CON1bits.SSRC=0b111;// auto convert
10
AD1CON1bits.ASAM=1;// Auto-Sampling aktivieren
11
12
AD1CON2bits.VCFG=0b000;// AVdd und AVss als referenz
13
AD1CON2bits.CSCNA=1;// Scan inputs
14
AD1CON2bits.SMPI=0b1111;// 16 Werte in den den Buffer schreiben
15
16
AD1CON3bits.SAMC=0b1111;// Auto Sample Time Tad
17
AD1CON3bits.ADCS=0b00111111;// 64 TCY
18
19
AD1CSSL=0xFFFF;// Alle 16 AN Pins scanen auch wenn digital
Ja, Du kannst meiner Meinung nach die Eingänge beim Auslesen ändern,
auch wenn der ADC aktiv ist.
Ja, der Timer muss natürlich initiallisiert sein. Du kannst für Tests
aber auch nur ein Delay (>6,25us) einfügen.
Hast Du die entsprechenden Inputs auch als Analogeingänge definiert?
Bsp: AD1PCFG = 0xFFFE; // Select analog input pins
Die jeweiligen Pins sind im Analogmodus. Leider funktioniert auch das
Programm von Manuel nicht.
Ich denke das es nicht am Programm liegt sondern an der Hardware, was
natürlich der schlimmste Fall wäre.
Aber mit dem Programm womit es mal lief, klappt es nun auch nicht mehr
und ein anderes Programm macht auf diesem PIC leider auch Probleme die
auf anderen Boards mit gleichem PIC fehlerfrei laufen.
Kann es sein das der ADC irgendwie einen Defekt hat, der PIC aber
troztdem andere Aufgabe bearbeitet? Wenn ja gibt es eine Möglichkeit das
festzustellen?
Ich bedanke mich aber schonmal für die bisherige Hilfe.
Gruß Alex
Ist das zufälligerweise ein PIC24FJ64GB mit 64-Pins? Dann könnte es auch
daran liegen:
http://ww1.microchip.com/downloads/en/DeviceDoc/80369k.pdf
"When using PGEC1 and PGED1 to debug an application on any 64-pin
devices in this family, all voltage references will be disabled. This
includes VREF+, VREF-, AVDD and AVSS. Any A/D conversion will always
equal 0x3FF."
Ja es handelt sich um ein PIC24FJ64 GB106 also ein PIC24 mit 64 PINs.
Aber das bezieht sich nur aufs "Debuggen" und nicht aufs "Realeasen"
oder irre ich?
Den debug-Modus kann ich leider garnicht nutzen wegen eines Fehlers
(PK3Err0040).
In einem anderen Programm wiederrum funktioniert das debuggen weswegen
ich dort auch hänge aber da es mal funktioniert hat (auch ohne den
ebug-Modus) habe ich mich mit dem Problem nicht weiter beschäftigt.
Guten Tag,
ich habe das ganze nun mal im "debug-Modus" laufen lassen und mir dann
die Register angeguckt.
Die Register AD1CON2, AD1CON3, AD1CHS, AD1PCFGL, AD1PCFGH, AD1CSSL und
AD1CSSH sind alle so wie ich sie eingestellt habe.
Im AD1CON1 Register wiederrum steht etwas völlig falsches.
Im Programmcode habe ich stehen: AD1CON1 = 0b0000000011100000;
Im Special Function Register Fenster wird mir aber angezeigt das im
AD1CON1 Register xC0E1 steht. Müsste da nicht x00E0 stehen?
Ich Debuge mit PEGC2/PEGD2, also an dem Problem worauf mich Arc Net
(danke nochmal) aufmerksam gemacht hat kann es nicht liegen.
Hat einer einen Rat für mich?
Gruß Alex
OK die Frage hat sich selbst beantwortet.
Das C verwirrt zwar, da das bit 14 dem Datenblatt nach "unimplemented"
ist und als 0 gelesen werden soll, aber auf 1 steht und somit nach dem
setzten der ADON bits nicht 8 sondern C steht.
Auch das SAMP bit arbeitet völlig korrekt und setzt sich automatisch von
1 auf 0 wenn das Sampeln fertig ist.
Ich werde nun erstmal schauen woran es genau liegt und mich nochmal
melden.
Ich habe es nun ans Laufen bekommen.
Ich bedanke mich nochmal für die Hilfe.
Im Endeffekt hat mir das Programm von Manuel geholfen.
Ich habe hier nochmal den gesamten Programmcode gepostet.
Zum Verständniss:
ADCrefValue ist eine feste Spannung die 1/2*Vref+ beträgt.
ANAFValue ist die Spannung die aus dem Bewegungsmelder kommt und bei
keiner Bewegung gleich ADCrefValue sein sollte und bei Bewegungen
kleiner oder größer wird was dann über das leuchten der LEDs an RB1 und
RB2 angezeigt wird.
Hier der Code:
#include <p24FJ64GB106.h>
#include <stdio.h>
#include <stdlib.h>
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF &
ICS_PGx2 & FWPSA_PR32 & WDTPS_PS2048);//& WINDIS_OFF & FWPSA_PR32 &
WDTPS_PS2048
int reference(void);
int analog(void);
int difference(void);
int delay(void);
/**********************MAIN************************/
int main(void)
{
int ADCrefValue = 0;
int ANAFValue = 0;
int dif = 200;
int ug = 0;
int og = 0;
PORTB = 0b0000000000000000;
TRISB = 0b1111111111111001; //RB1-2 = Output, RB0/3-15 = Input
PORTC = 0x0000;
TRISC = 0xFFFF;
PORTD = 0x0000;
TRISD = 0xFFFF;
PORTE = 0x0000;
TRISE = 0xFFFF;
PORTF = 0x0000;
TRISF = 0xFFFF;
PORTG = 0x0000;
TRISG = 0xFFFF;
T1CON = 0b0000000000110000; //Stops the Timer1 and reset control
reg.
TMR1 = 0x0000; //Clear contents of the timer register
PR1 = 0xFFFF; //Load the Period register with the value
0xFFFF
IPC0bits.T1IP = 0x01; //Setup Timer1 interrupt for desired
priority level
// (This example assigns level 1 priority)
IFS0bits.T1IF = 0; //Clear the Timer1 interrupt status flag
IEC0bits.T1IE = 1; //Enable Timer1 interrupts
AD1CON1 = 0b0000000011100100; // SAMP bit=0 ends sampling
AD1CON2 = 0b0010010000111100; // Vref+ (^= Original reference signal
from PIR (Vcc/2)
AD1CON3 = 0b0001111100111111;
AD1PCFGL = 0b1111111111000110; // AN0, AN3 & AN4 as Analog Input
AD1PCFGH = 0b0000000000000000;
AD1CSSL = 0b1111111111111111; // Analog channel omitted from input
scan
AD1CON1bits.ADON = 1;
while(1)
{
ADCrefValue = ADC1BUF4;
ANAFValue = ADC1BUF3;
og = ADCrefValue+dif;
ug = ADCrefValue-dif;
if ((ANAFValue < ug)||(ANAFValue > og)){
PORTB = 0b0000000000000110;
} //if ((ANAFValue < ADCrefValue)||(ANAFValue > ADCrefValue))
else
PORTB = 0b0000000000000000;
} //while(1)
} //main
/******************END*MAIN************************/
Gruß Alex