Sida 1 av 1

Skillnad på timing i och utanför interrupt i PIC

Postat: 9 juli 2012, 19:33:39
av Rick81
Jag behöver en extra UART till PIC2550 och implementerade en i mjukvara.

Problemet är att när jag försöker köra den via interrupt på negativ flank på INT1 (dvs startbiten) så blir resultatet helt annorlunda mot när jag pollar startbiten.

Jag kör med intern oscillator på 8 MHz.

Koden ser ut följande:

Interruptfunktionen

Kod: Markera allt

void interrupt isr(void)
{
	if(INT1IF == 1)
	{
		SW_UART_RX_Int();
		INT1IF = 0;
	}
}
Koden som läser från uart

Kod: Markera allt

void SW_UART_RX_Int()
{
	char i, c = 0;
	if(RX_PIN == 0)	// Start bit
	{
		UART_Delay();
		HALF_DELAY();	// Hamna mitt i biten

		for(i = 0; i < 8; i++)
		{
			c = (c >> 1) & 0x7F;
			c = c | (RX_PIN << 7);	//  LSB först!
			UART_Delay();
		}
		getChar = c;
	}
}
Koden som hämtar char

Kod: Markera allt

char getChar = 0;
char SW_UART_GetChar()
{
	char c;
	char lastGIE = GIE;
	GIE = 0;
	c = getChar;
	getChar = 0;
	GIE = lastGIE;
	return c;
}

De olika looparna

Kod: Markera allt

	GIE = 0;	//Stäng av interrupt

	// Denna loop läser UART korrekt via pollning
	while(1)
	{
		CLRWDT();
		SW_UART_RX_Int();	// 
		swc = SW_UART_GetChar();
		if(swc != 0)
		{
				SW_UART_PutString("Du tryckte: ");
				SW_UART_PutChar(swc);
				SW_UART_PutString("\r\n");
		}
	}
	

	// Denna loop läser ut felaktiga värden via interrupt där SW_UART_RX_Int körs
	GIE = 1;	//Slå på interupt
	while(1)
	{
		CLRWDT();
		swc = SW_UART_GetChar();
		if(swc != 0)
		{
				SW_UART_PutString("Du tryckte: ");
				SW_UART_PutChar(swc);
				SW_UART_PutString("\r\n");
		}
	}

Det körs inga interrupt utöver INT1.

De felaktiga värdena blir (inom parentes anges det decimala värdet)
1 (49)
Du tryckte: ó (243)
2 (50)
Du tryckte: ™ (153)
3 (51)
Du tryckte: ó (243)
4 (52)
Du tryckte: š (154)
5 (49)
Du tryckte: ÿ (255)
6 (49)
Du tryckte: › (155)
7 (49)
Du tryckte: ÿ (255)
8 (49)
Du tryckte: œ (156)
9 (49)
Du tryckte: ó (243)
0 (48)
Du tryckte: ˜ (152)

Jag kan inte förstå varför dessa loopar beter sig annorlunda. Någon som har någon ide vad som kan orsaka detta?

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 9 juli 2012, 19:47:38
av H.O
Har du koll på hur lång tid det tar från det att linjen går låg (startbiten) tills du verkligen börjar exekvera SW_UART_RX_INT? Sätt en utgång det första du gör i ISR'en och mät (om du har ett oscillskop eller annat lämpligt). Jag vet inte hur din kompilator hanterar context save etc men det kan ju vara så att det tar så pass mycket tid (vilken baudrate kör du?) så att du "hamnar fel".

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 9 juli 2012, 19:58:51
av Rick81
Testade att simulera interruptet i MPLAB och det tog hela 32 us från flank till biten kollades vilket gör att första biten missas. Jag köra på 38400 i baud och då motsvarar en bit 26 us.

Kunde inte tänka mig att det skulle ta 32 us ( 64 instruktioner) att hoppa in i ett interrupt. Ett sätt att lösa detta är borde då vara att man bara kollar interupt och då anser att man fått en startbit och läser på direkten. Ska testa detta i morgon.

Jag trodde att det enda som gjordes vid interupt var att spara undan w och PC. Vad mer görs på dessa instruktioner? Det är hoppet till interrupt och inte funktionsanrop som tar tid.

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 9 juli 2012, 20:05:26
av H.O
Troligen så har din kompilator ett antal interna "arbetsvariabler" som den måste spara undan innan den kan börja exekvera interruptrutinen - och återställa innan den returnerar från interruptrutinen.

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 9 juli 2012, 20:14:59
av vfr
Ska man göra saker med sådana krav på timing, så är det assembler som gäller. Med en kompilator, oavsett språk, så har du inte den detaljkollen på vad den gör. I ditt fall skulle du väl kunna plocka ut en assemlerlistfil för att kartlägga vad den verkligen gör. Det måste ju gå att göra från vilken kompilator som helst, tycker jag...

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 9 juli 2012, 23:25:06
av sodjan
> Vad mer görs på dessa instruktioner?

Varför inte helt enkelt kolla ? :-)
Det är bara att titta i assembler listningen från kompilatorn.
Om nu inte dokumentationen har något om det.

38 å 4 med SW USART är kanske lite "to push it"...

> PIC2550

PIC18F2550 ??

Än lite äldre modell. Med modernare processor kan du få upp även
INTOSC i lite högre speed än 8 MHz. Har kompilatorn möjlighet att
stänga av körning med båda interrupt-nivåerna ? Det skulle kunna
få den (kompilatorn) att generera lite kompaktare/snabbare kod
eftersom shadow-registren då kan användas istället för att spara
unden registren via koden.

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 10 juli 2012, 09:06:59
av Rick81
Det fungerade klockrent när jag gjorde om funktionen enligt:

Kod: Markera allt

void SW_UART_RX_Int()
{
	char i, c = 0;
	EXTRA_DELAY();
	for(i = 0; i < 8; i++)
	{
		c = (c >> 1) & 0x7F;
		c = c | (RX_PIN << 7);	//  LSB först!
		UART_Delay();
	}
	getChar = c;
}
Jag använder då tiden för att hoppa in i interuptet ca 32 us till att hoppa 1,5 bit in i läsningen (startbit + mitten på avläsning = 39 us).

> 38 å 4 med SW USART är kanske lite "to push it"...
Jo kanske, men nu verkar det funka.

> PIC18F2550 ??
Ja det stämmer, skrev fel. Har du tips på nyare PIC med 28 pin, SPI/I2C (helst x2), uart (helst x2), intern osc, USB, mycket flash, mycket RAM, låg effektförbrukning? Eller ännu bättre hur man lämpligt ser vilka PIC som är nya? Går man in på microchip är det ett virrvarr med PIC och det finns inget smidigt sett att se vilka som är modernast.

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 10 juli 2012, 10:31:33
av Icecap
Microchip har deras parametriska sökfunktion... mycket användbar!

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 10 juli 2012, 11:41:11
av sodjan
Kanske inte helt "klockrent" att använda en egenskap hos kompilatorn
till kritisk timing i applikationen. :-) Det kan hända mycket som plötsligt
får den timingen att ändras utan att du har någon kontroll alls.

När det gäller "nyare" processorer så hör man det på namnet. :-)
Börja t.ex på http://www.microchip.com/pagehandler/en-us/family/8bit/
och klicka dig fram via "Architecture" => "PIC18" o.s.v.

Gå in i "parametric search" och börja med de enkla villkoren, 2 st USART t.ex.
Enbart det villkoret ger "124 of 201 PIC18 MCU Devices are found." Gå sedan vidare
med antal ben o.s.v tills du hittar något som passar.

A/E/USART = 2
MSSP (SPI/I2C) = 2
# USB Channels = 1
Total Package Pin >= 28
Total Package Pin <= 40

Ger 5 st kretsar. Alla dock 28 pin och 3.3V, jag vet inte om det är ett problem.
I så fall får du söka vidare...

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 10 juli 2012, 12:54:23
av Rick81
Kan hålla med om att det inte är optimalt med att använda kompilator egenskap för fördöjning och ibland blir det fortfarande felaktiga tecken. Men i nuläget är det viktiga utskrifterna och de är felfria. Inmatning är bara för debug. Får ev. sänka baud om jag behöver förbättra inmatningen.

parametric search var riktigt bra!

Tyvärr klarar inte min gamla PICstart plus programmerare av de nya PIC med dubbla UART och dubbla SPI.

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 10 juli 2012, 13:00:49
av Icecap
Skaffa då en PICkit3! Ganska billig och du får en massa möjligheter - samtidig som du inte behöver dra ut kretsen.

Re: Skillnad på timing i och utanför interrupt i PIC

Postat: 10 juli 2012, 14:54:32
av Johanb
Jag är fortfarande nyfiken på vad de 64 instruktionerna gör :)