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