Sida 1 av 1

Visa värde på 7 segment display

Postat: 12 november 2011, 20:05:27
av morre95
Jag försöker lära mig att programmera PIC. Och i den boken som jag läser så är avslutas varje kapitel med övningar. Och i den övningen som jag inte lyckas lösa så ska man mäta på en potentiometer och skriva ut resultatet på två 7 segment displayer. Den ända hjälpen man får är ett kopplingsschema.

Jag har dubbelkollat så jag har kopplat rätt. Så jag misstänker att det är jag som missat något i koden:

Kod: Markera allt

#include <pic18.h>
#include <delay.c>

unsigned char sjuseg(unsigned char siffra);
unsigned char ad8bit(unsigned char kanal);

double Ain;
char Aint;

void main () {
	TRISC = 0x00;
	ADCON0 = 0xC1;
	TRISD = 0x00;
	CMCON = 0x07;

	LAT7 = 1;	
	LAT6 = 1;
	
	while(1) {
		Ain = 0.01953*ad8bit(0)+0.05;
		Aint = (char)(Ain * 10);
		PORTC = sjuseg(Aint/10+0x30);

		LAT6=0;
		DelayMs(1);
		LAT6=1;

		PORTC = sjuseg(Aint%10+0x30);
		LAT7=0;
		DelayMs(1);
		LAT7=1;
	}
}

unsigned char ad8bit(unsigned char kanal) {
	kanal <<= 3;
	ADCON0 = 0xC1;
	DelayMs(10);
	GODONE = 1;
	while (GODONE);
	return ADRESH;
}

unsigned char sjuseg(unsigned char siffra) {
	unsigned char seg;
	switch (siffra)  {
		case 0:
			seg = 0x3f;
			break;
		case 1:
			seg = 0x06;
			break;
		case 2:
			seg = 0x5b;
			break;
		case 3:
			seg = 0x4f;
			break;
		case 4:
			seg = 0x66;
			break;
		case 5:
			seg = 0x6d;
			break;
		case 6:
			seg = 0x7d;
			break;
		case 7:
			seg = 0x07;
			break;
		case 8:
			seg = 0x7f;
			break;
		case 9:
			seg = 0x6f;
			break;
	}

	return seg;
}
Jag får inga felmeddelanden när jag kompilerar koden och jag lyckas ladda in den i PIC:en med min PICKIT 3. Men displayerna visar inget. Är det någon som kan hjälpa mig med vad jag gjort för fel? Behöver ni kopplingsschemat så säg till så ska jag försöka fixa till något.

Re: Visa värde på 7 segment display

Postat: 12 november 2011, 20:10:53
av Klas-Kenny
Jag vill i alla fall gärna se kopplingsschemat.

Sen kan du ju testa ett väldigt simpelt program, att bara tända alla segment i displayerna genom att sätta PORTC och PORTD till 255, för att se om det fungerar alls.

Edit: Förresten, det är inte så att det är displayer med gemensam Anod, och du kopplat Anoden till 0v? Eller tvärt om.

Re: Visa värde på 7 segment display

Postat: 12 november 2011, 20:14:24
av anders_bzn
1. Testa med att i din loop anropa sjuseg() med tex 1. Vad händer.
2. Fundera på vad som händer i funktionen om in argumentet är skilt från 0..9
3 Kolla hur du anropar funktionen just nu, vilka värden skickar du in.

EDIT: Jag ser fel, men försöker göra en Sodjan!

Re: Visa värde på 7 segment display

Postat: 12 november 2011, 20:37:20
av Icecap
Jag ser felen också men har lite kommentarer till själva programmet.

morre95: du använder flyttal, varför?
Tydligen vill du visa de höga 8 bit från AD-omvandlaren på 2 siffror och efter vad jag kan räkna ut ska de visa 00-50. Men det kan åstadkommas mycket snabbare och enklare med heltal! Flyttal tar lång tid att räkna med om man undviker dom mest möjligt i µC, helt enkelt för att det är så resurskrävande och nästan alltid onödiga.

För att konvertera 0-255 till 0-50 ska du egentligen dela med 5,1 bara - men det går ju inte med heltal! Men gör som följer:
Aint = (ad8bit(0) * 10)/51; // Då så, värdet är omräknat från 0-255 till 0-50
Ain = Ain % 10; // Ain är nu 1-tals värdet
Aint /= 10; // Aint är numera 10-värdet

Sedan borde din scanning av displayen vara baserat på en timer-interrupt och du skulle bara skriva mönstret i var sin minneslokation, dessa lokationer skulle interrupt-rutinen sedan läsa av och visa på rätt display men till detta kan det väl duga, det är dock ett mycket fel sätt att lösa det på.

Din sjuseg() är inte imponerande heller, mest överskådligt (och snabbare i.o.m. PIC18) hade varit att bygga en tabell:
unsigned char sjuseg(unsigned char siffra)
{
const unsigned char Pattern[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6f};
return(Pattern[siffra]);
}

Re: Visa värde på 7 segment display

Postat: 12 november 2011, 21:08:43
av morre95
Tack för snabba svar, det är uppskattat!

@Icecap: Jag använder flyttal för att det är vad författaren i boken gör. Jag är på kap. 11 av 28 så det är ju lite tråkigt om man får lära sig fel från början.

Jag lyckades lösa det. Så här ser min while loop ut nu:

Kod: Markera allt

while(1) {
	Aint = (ad8bit(0) * 10)/51;
	LATD6=0;
	PORTC = sjuseg(Aint%10);
	DelayMs(1);
	LATD6=1;
	LATD7=0;
	PORTC = sjuseg(Aint/10);
	DelayMs(1);
	LATD7=1;
}
Kan man skriva ut värden eller på något vis ta reda på vad en variabel innehåller för värde? Det skulle underlätta massa när man felsöker i så fall.

Re: Visa värde på 7 segment display

Postat: 12 november 2011, 21:15:55
av Icecap
Såklart man kan! Med en PICKit3 och MPLAB ska du kunde debugga direkt och då placera de önskade värden i ett watch-fönster. Då kan du t.ex. köra programmet till cursorn, singlesteppa, se alla värden i watch-fönstret osv.

Men sättet jag gör det på när jag startar upp ett nytt projekt är att koppla upp en seriell port, med en nivå-omvandlare (t.ex. MAX232 eller klon) kan jag sedan koppla till en seriell port på en PC och använda ett terminalprogram och då går det snabbt.

Men att debugga med PICKit3 fungerar minst lika bra!

Re: Visa värde på 7 segment display

Postat: 12 november 2011, 23:29:17
av sodjan
> Kan man skriva ut värden eller på något vis ta reda på vad en variabel innehåller för värde?

En enkel felsökning är att köra det i MPSIM.
Du får kanske hårdkoda ett värde från ADC'n istället för att läsa från den,
men du kan enkelt köra 7-seg rutinerna och se om du får ut det som du tror.

Sen så är det ju helt onödigt att köra float/double här, som Icecap också skrev.
Men å andra sidan, för denna demo så fungerar det ju och det kanske är viktigast.