PIC18F2620, UART a problém

Pavel Kořenský pavel.korensky@dator3.cz
Pondělí Leden 9 16:24:40 CET 2006


Zdravím,

mám tady takový podivný problém s PIC18F2620 a jeho UARTem.

PIC přijímá data z radiomodemu (Linx modul) o rychlosti 19200,N,8,1.
Data vypadají tak, že nejprve se vysílá start (2x byte 0x33), pak 4 byty
dat a nakonec jeden byte kontrolní součet.

Když ten program pustím v simulátoru MPLAB, tak vše funguje jak má,
zkoušel jsem testovací hodnoty pro dobrý i špatný packet.

Když to naprogramuju do PICu, tak se to chová podivně. Po zapnutí
zařízení to někdy přijímá a někdy nepřijímá, přičemž tato vlastnost má
náhodný charakter. Někdy to například funguje pokaždé i když to zapnu
třeba 5x. Pak to zase třeba při třech následných zapnutích nefunguje,
při čtvrtém to zase fuguje, při dalším zase ne a pak třeba zase 3x po
sobě to funguje.

Když jsem připojil jeden kanál osciloskopu na vstup UARTu a druhý na
volný pin a v rutině přerušení jsem šmrdlal tím volným pinem, tak bylo
na osciloskopu vidět, že na vstup UARTu lezou správná data a rutina
přerušení se skutečně po každém bytu zavolá (byte je tedy přijat). V
případě, že zařízení po zapnutí fungovalo, tak vše proběhlo správně a
zavolala se procedura ProcessPacket (to jsem ověřil delším pulsem na
volném testovacím pinu).

V případě těch zapnutí, kdy zařízení nepracovalo správně, byla data na
vstupu UARTu rovněž v pořádku, přerušení přijalo každý byte, ale
procedura ProcessPacket se po přijetí celého packetu nezavolala, jako
kdyby neseděl kontrolní součet nebo jako kdyby nebyla správně přijata
počáteční sekvence 0x33,0x33.

Netuší někdo, v čem by mohl být zádrhel ? Nějak tam nemůžu najít žádnou
chybu.


Zdraví PavelK





Program PICu vypadá zhruba takto (zkráceno):

========================================================================
=================================

BYTE RxChar;
BYTE PacketStatus;
BYTE PacketReceived;
BYTE	i;
BYTE	j;
BYTE	InBuf[8];

BYTE CalcCS(void)
{
	BYTE a;
	BYTE csum;

	csum=0;

	for(a=0;a<=5;a++)
	{
		csum+=InBuf[a];
	}
	return csum;
}

void interrupt low_priority LoPriorInt (void)
{
	if(RCIF)
	{
		if((FERR==1)||(OERR==1))
		{
			RxChar=RCREG;
			CREN=0;
			CREN=1;
		}
		else
		{
			RxChar=RCREG;			// Copy received
character and clear RCIF
			if((PacketStatus==0) && (RxChar==0x33))
// first packet start byte ?
			{
				InBuf[PacketStatus]=RxChar;
				PacketStatus++;
			}
			else
			{
				if((PacketStatus==1) && (RxChar==0x33))
// second packet start byte ?
				{
					InBuf[PacketStatus]=RxChar;
					PacketStatus++;
				}
				else
				{
					if((PacketStatus>=2) &&
(PacketStatus<=5))	// data bytes ?
					{
	
InBuf[PacketStatus]=RxChar;
						PacketStatus++;
					}
					else
					{
						if(PacketStatus==6)
// CS byte
						{
	
InBuf[PacketStatus]=RxChar;
	
if(InBuf[6]==CalcCS()) PacketReceived=1;		// if packet is
OK, signal it
							PacketStatus=0;
// reset status
						}
						else
						{
							PacketStatus=0;
// reset status
						}
					}
				}
			}	
		}
	}
}
		



void PICInit(void)
{
	TRISA=0xFF;
	TRISB=0xE7;				// Only RB4,RB3 is
output
	TRISC=0xFC;				// RC0,RC1 out, RC6 out
	BRGH=1;
	BRG16=0;
	SPBRG=129;				// 19200 Bd
	SPEN=1;					// Enable EUSART
	TXEN=1;					// Enable transmit
	SYNC=0;					// Async mode
	RCIE=1;					// Enable RX int
	CREN=1;					// Enable receive	
	IPEN=1;					// Enable interrupt
priorities
	RCIP=0;					// EUSART receiver is
low priority int
	RxChar=RCREG;
	RxChar=RCREG;			// Empty buffer
	RCIE=1;					// Enable EUSART receive
int
	RXENABLE=1;
	TXENABLE=0;				// set modem to receive
mode

	IRPIN=1;				// IR is idle
	PacketStatus=0;			// Recieve packet state is at
the beginning
	PacketReceived=0;		// No packet in buffer
	Del_5ms();
	Del_5ms();				// wait for radiomodem
RX mode set
	RxChar=RCREG;
	RxChar=RCREG;			// Empty buffer
	CREN=0;					// clear possible errors
	CREN=1;
	GIE=1;					// Enable global int
	PEIE=1;					// Enable peripheral int
}


void SendIRByte(BYTE ir)
{
	IRPIN=0;

// posilame neco nekam
	IRPIN=1;
}


void ProcessPacket(void)
{
	if(InBuf[2]>=0x80) SendIRByte(InBuf[2]);
	PacketReceived=0;
}

void main (void)
{
	for(i=0;i<=10;i++) Del_5ms();
	PICInit();
	while(1)
	{
		if(PacketReceived) ProcessPacket();
	}

}

========================================================================
========================================================================
===




Další informace o konferenci Hw-list