Sida 1 av 2

Problem med att använda Analog ingång på PIC

Postat: 19 maj 2007, 18:36:42
av fruce
Håller på med ett projekt där jag ska ta in en batterispänningsnivå på analoga ingången på picen för att varna när den går låg. Resultatet skriver jag ut på en display men problemet är att resultatet blir 0 hela tiden, jag har debuggat och kollat vad resultat ADRESH och ADRESL innehåller men jag får ut att de innehåller 0. Min programkod:

//ADCON0 Kontrollerar operationerna i AD-Modulen
//ADCON1 Configurerar funktionerna för portarna

ADCON0=00000001;
ADCON1=01001110;

Void BatteryCheck(void)
{
static int Counter=0, Value=0,Temp;
static char FirstPart=0, SecondPart=0;

++counter; //Räknare räknas upp

if(Counter==1000)
{

if(ADCON0 && 0b00000100)
{
FirstPart=ADRESH;
SecondPart=ADRESL;

Temp=FirstPart;
Temp<<=8;

Value=(Temp|SecondPart);
}

Counter=0;
printNumber(Value,0,0,NEW_NUMBER); //Skriv ut ByteValue som ett nummer på Column 0, Rad 0

}

}

Lite mer info

Postat: 19 maj 2007, 18:39:09
av fruce
Picen Jag använder är en 18F458

Postat: 19 maj 2007, 19:23:37
av lgrfbs
Välkommen till forumet.

Kommer den spännign du ska övervaka även att driva MCU:n?

Postat: 19 maj 2007, 20:40:36
av v-g
TRIS registren är korrekt satta antar jag?

RE: Analog ingång

Postat: 19 maj 2007, 21:42:39
av fruce
Ja, den kommer även att driva MCUn. Jag satte AN0 till ingång på trisregistret.

Postat: 19 maj 2007, 22:27:54
av sodjan
Var startar du konverteringen ?
Konstig kod, för övrigt, det där kan väl aldrig fungera, det saknas ju massor.
T.ex TRIS konfiggen...
V.v posta en *komplett* kod som uppvisar det problem du beskriver.
Det är även lite dåligt kommenterat, fixa det.
Använd code-taggarna när du postar kod.

Trisconfigurationen

Postat: 19 maj 2007, 23:23:12
av fruce
Ja, jag håller med dig att det var lite dåligt kommenterat, triskonfigurationen är klar innan, det är ett rätt stort projekt så hela koden är rätt omfattande. Jag ska försöka fixa till den ytterligare imorgon.

Enklast?

Postat: 20 maj 2007, 01:06:33
av fruce
Är det någon som vet eller har förslag om hur man enklast använder AN0- ingången utan att använda interrupt för att få ett värde i proportion till spänningen?

Postat: 20 maj 2007, 07:42:50
av Icecap
Detta är delar av ett projekt som aldrig blev av pga. ändringar av hårdvaran. Gjort för PIC18F4550.

Kod: Markera allt

void Initialize_AD(void)
  {
  ADCON0   = 0b00000001; // Enable AD
  ADCON1   = 0b00001101; // AN0 & AN1 as analog
  ADCON2   = 0b10100001; // Could need tweaking
  TRISA.F0 = true; // Set as input
  TRISA.F1 = true; // Set as input
  }

I main lade jag sedan:
    ADCON0.CHS0 = false; // Select channel 0
    ADCON0.GO   = true;  // Start converting
för att starta omvandlingen och jag kollade på ADCON0.GO om den var klar (='0') eller om den höll på att omvandla (='1')
Om detta fungerar som tänkt kan jag inte svara på men det borde vara nära iaf.

Postat: 20 maj 2007, 13:36:02
av sodjan
> Är det någon som vet eller har förslag om hur man enklast använder AN0- ingången utan att använda interrupt för att få ett värde i proportion till spänningen?

"Enklast" ? Vad är det ? :-)

Men i princip är det väl :
Sätt ADC konfiggen så att AN0 är "analog".
Konfigga övriga ADC register efter behov.
Starta (efter specad fördröjning) ADC.
När ADC'n har kört klart (kolla lämplig bit), läs av !

Om du använder interrupt eller inte har helt valfritt,
det har inte så mycket med ADC'n i sig att göra, utan hur
din överripande applikationsstruktur ser ut. Om det i ditt
fall är lämpligare att polla ADC'n så visst, gör det.

Om du tror att du har problem med just ADC'n, så skriv ett
litet test-case som bara testar just de delarna...

Postat: 20 maj 2007, 21:21:00
av fruce
Jag har gjort lite ändringar, utifrån tipsen typ även pollningen var helt fel, men såhär ser det ut nu:

Kod: Markera allt

//ADCON0 Kontrollerar operationerna i AD-Modulen
//ADCON1 Configurerar funktionerna för portarna

void InitBatteryCheck(void)
{
ADCON0=11000001; //AD CONVERT POWERED UP
ADCON1=01001110; //AN1=ANALOG IN
}

Void BatteryCheck(void)
{
	static int Counter=0, Value=0, Temp;		//Räknare resultat och tempfil för behandling av resultat
	static char FirstPart=0, SecondPart=0;		//Variabler för att behandla första och andra delen av resultatet i registrena
	
	if(Counter<1000)
	counter++;					//Räknare räknas upp
	else
	Counter=0;
	
	if(!Counter) 					//För att inte fylla upp bufferten måste vi vänta, dessutom måste en kondensator hinna laddas upp för att kunna läsa av ingången
	{

		if(ADCON0 & 0b00000000)			//Kolla GO-bit ifall den är redå att läsa av från analog ingång
		{
			FirstPart=ADRESH;		//Första 5 bitarna är ADRESH
			SecondPart=ADRESL;		//Sista 5 bitarna är ADRESL
	
			Temp=FirstPart;			//Första 5 bitarna läggs i Temp
			Temp<<=8;			//Temp skiftas 5 åt vänster

			Value=(Temp|SecondPart);	//Temp pollas med SecondPart som tillsammans läggs in i ByteValue
		}
		printNumber(Value,0,0,NEW_NUMBER);	//Skriv ut ByteValue som ett nummer på Column 0, Rad 0, egen funktion för displayen... funkar
	}

 	
}
Borde kunna fungera :?

Pollning rätt?

Postat: 20 maj 2007, 21:24:04
av fruce
Jag undrar fortfarande om jag fått till pollningen rätt ändå nu när jag tänker efter...

kanske måste kolla GO/DONE Biten om den är 0? genom att bara skriva dit den o pröva att den är 0 istället för att polla ut den?

Postat: 20 maj 2007, 22:18:20
av sodjan
Var *sätter* du GO/DONE biten ?
D.v.s var *startar* du konverteringen ?

Det är ju ingen mening att kolla om det
är klart om du aldrig startar konverteringen...

Men det är väl lite för enkelt, det är ju
ganska tydligt i kapitlet om ADC'n...

Go/Done-bit

Postat: 20 maj 2007, 22:33:35
av fruce
När jag kollade i databladet för 18F458 var Go/Done-biten statusbiten som clearades av processorn då konverteringen var klar. Jag vet inte, kanske har missuppfattat det hela.

Läste vidare i databladet

Postat: 20 maj 2007, 22:35:22
av fruce
Nu förstod jag vad du menade...