Vai al contenuto
PLC Forum


Problemi Ricezione Dati Pic 16f628 Su Bus Mdb


Micron2006

Messaggi consigliati

Salve a tutti questo è il mio primo post e Topic.

Vi pongo subito il quesito che mi sta facendo impazzire da un pò di tempo. Sto procgettando tramite un PIC 16F628 un Master che gestiswca due periferiche Slave tramite protocollo MDB (Multi Drop Bus). Per comunicare con le periferiche Utilizzo la USART del PIC configurata ne seguente modo:

void UsartCfg(void) //configurazione del modulo Usart clock Int RC 4Mhz

{

SYNC=0;

BRGH=1;

SPBRG=25;

TXIE=0;

RCIE=0;

TX9=1;

RX9=1;

SPEN=1;

CREN=1;

TXEN=1;

}

Il sistema strutturato nella seguente maniera: Invio dal Master un messaggio (per esempio un poll) attivo l'interrupt RCIE=1; e rimango in attesa della risposta della periferica che ho interrogato.

Tutto procede bene, i sistemi rispondono, ed il PIC acquisisce ed elabora, ma ad un certo momento apparentemente Random il PIC decide di non scaricare i messaggi a lui inviati e va avanti per la sua strada, non scaricando dal registo RCREG il messaggio. al poll successivo il PIC prova invece a scaricare i messaggi trovando la diagnostica di overflow attiva OERR perchè non ha scaricato il messaggio prima perdendo quindi i dati ricevuti.

Queste informazioni le ho reperite tramite un Logic Analyzer. L'errore avviene su messaggi che precedentemente non avevano dato problemi (per alcuni minuti).

Vi è mai capitata una cosa del genere? Cambiando il PIC con uno nuovo (sempre 16F628) la questione è rimasta tale.

Chiedetemi tutte le informazioni che vi occorrono per tentare di capire dove secondo voi potrebbe essere il problema. Grazie a tutti coloro che tenteranno di aiutarmi su questo problema che mi sta facendo impazzire!

Ciao

Link al commento
Condividi su altri siti


Quando ho realizzato un'applicazione simile alla tua lavoravo sull'interrupt alla ricezione di ogni carattere che salvava il carattere in un buffer globale ed incrementava il conteggio dei caratteri salvati.

Poi nel main loop adavo a processare il buffer.

Per avere risposte al tuo problema dovresti postare per lo meno il codice utilizzato ...

Io avevo lavorato in C col PCM della CCS

Ciao :)

Link al commento
Condividi su altri siti

unsigned char MasterCommand(unsigned char CMD,unsigned char *CodUart)

{

unsigned char RisCode;

command=CMD;

chk=CMD;

UsartOutput(CMD,1);

UsartOutput(chk,0);

Retransmit:

TimerOn();

while (InterruptRX)

{

#asm

NOP

#endasm

}

if (*CodUart==1)

{

UsartOutput(ACK,0);

}

if (*CodUart==2)

{

UsartOutput(RET,0);

RB6=1;

goto Retransmit;

}

if (*CodUart==0)

{

#asm

NOP

#endasm

}

RisCode=*CodUart;

return RisCode;

}

Questa è la routine che utilizzo per mandare i comandi ed è quella a cui saltuariamente non ho risposta.

TimerOn() in sostanza abilita l'interrupt.

Inoltro anche le routine di interrupt e ricezione Byte:

unsigned char UsartInput(void) //RX singolo byte

{

unsigned char ERRORE=0;

unsigned char RXbyte;

CodiceErrore=0;

TMR0=TIMER_INT;

T0IF=0;

while((!RCIF)&&(!ERRORE))

{

if(OERR)

{

RA3=1;

CREN=0;

CREN=1;

ERRORE=1;

}

if(FERR)

{

RA1=1;

RXbyte=RCREG;

ERRORE=1;

CREN=0;

CREN=1;

}

if(T0IF)

{

ERRORE=1;

}

}

if (ERRORE)

{

CodiceErrore=1;

BitNove=1;

RXbyte=COD_ERR;

}

else

{

BitNove=RX9D;

RXbyte=RCREG;

}

return RXbyte;

}

void interrupt RicezioneSegnale(void) //routine che gestisce RX pacchetti e TimeOut

{

unsigned char n,Error;

unsigned int cnt;

InterruptRX=0;

if(T0IF!=1) //se TimeOut non è scaduto (5ms)

{

T0IE=0;

RCIE=0;

for(i=0;i<30;i++)

{

RispostaPRF=0;

}

if((command&0b11111000)==0x30)

{

r=0;

}

if((command&0b11111000)==0x08)

{

s=0;

}

BitNove=0;

n=0;

chk=0;

CodiceRisposta=2;

while(!BitNove)

{

RispostaPRF[n]=UsartInput();

if(CodiceErrore==1)

{

do

{

Error=RCREG;

CREN=0;

CREN=1;

for(cnt=0;cnt<950;cnt++)

{

#asm

NOP

#endasm

}

}

while(RCIF);

goto fine;

}

n=n+1;

}

n=n-1;

for(i=0;i<n;i++)

{

chk=(chk+RispostaPRF)&MASK;

}

if((RispostaPRF[0]==ACK)&&(n==0))

{

CodiceRisposta=0;

}

if((chk==RispostaPRF[n])&&(n!=0))

{

CodiceRisposta=1;

}

if((chk!=RispostaPRF[n]))

{

CodiceRisposta=2;

RB6=1;

}

fine:

if(CodiceErrore==1)

{

CodiceRisposta=2;

RB6=1;

}

}

else //se TimeOut è scaduto lo scrivo dentro il codice di risposta

{

RCIE=0;

T0IE=0;

T0IF=0;

CodiceRisposta=3;

RA7=1;

if((command&0b11111000)==0x30)

{

r=r+1;

if(r>100)

{

r=0;

CodiceRisposta=4;

RA6=1;

StepBill=0;

}

}

if((command&0b11111000)==0x08)

{

s=s+1;

if(s>100)

{

s=0;

CodiceRisposta=4;

RA7=1;

StepChanger=0;

}

}

}

}

Quindi anche io come te mi svuoto il buffer quando mi arriva l'interrupt attivato da RCIF.

Grazie per aver risposto al mio problema, mi rendo conto che non è semplice cercare di aiutarmi.

Ciao

Modificato: da Micron2006
Link al commento
Condividi su altri siti

Non ti invio tutto insieme altrimenti diventa un caos, magari ponetemi dei quesiti che man mano rispondo inoltrando pezzi di codice.

Grazie ancora per l'interessamento, io non saprei più dove sbattere la testa.

Ciao

Micron

Link al commento
Condividi su altri siti

Dando un'occhiata VELOCE vedo che quando arriva l'interrupt fai troppe cose (per i miei gusti) ; se fossi in te mi limiterei a spostare nel buffer il solo carattere letto ; liberando il buffer ad ogni interrupt ricevuto (eventualmente scartando il carattere ricevuto se il buffer e' pieno) ; e poi mi processo i dati con calma ...

La gestione del time-out deve bloccarti la trasmissione e dopo una piccola attesa per scartare eventuali dati in arrivo liberi il buffer di ricezione ; spedisci la richiesta ; attendi che tutti i dati in spedizione siano partiti e quando arriva il numero di dati che ti aspetti vai a processare il buffer.

Ad ogni arrivo di carattere il time-out lo resetti.

Ciao :)

Link al commento
Condividi su altri siti

Per la tua esperienza su questi sistemi, è possibile che un sistema concepito come il mio possa dare errori "random"? Ti spiego: se il tutto funziona correttamente ad "n giri" su tutte le tipologie di messaggi inviati/ricevuti ed improvvisamente al "n+1" giro si incarta, è possibile che sia dovuto ad operazioni/routine non ottimali con cui gestisco il PIC, anche senza "errori" veri e propri?(e che quindi mi farebbero andare in errore il sistema tutte le volte, in modo sistematico!) Quello che mi fa impazzire è che il problema accade apparentemente random. Secondo te è possibile "random" oppure in qualche modo sbaglio il SW per cui mi infilo in situazioni che danno malfunzioni (secondo la logica, prima o poi accadrà è solo questione di tempo!)

Ti ringrazio per l'interessamento, e per il tempo che mi hai dedicato. Proverò sicuramente a cambiare la routine di ricezione, mi piacerebbe avere una tua opinione su quello che ho scritto, per capire se la mia impostazione di logica su questo tipo di sistemi è secondo te corretta o sbagliata.

Grazie ancora e ciao.

Link al commento
Condividi su altri siti

Per esperienza personale i problemi che avevo avuto con l'approccio che ti ho sopra descritto erano legati al fatto che se alla ricezione dell'interrupt non toglievi il carattere dal buffer di ricezione del pic , mi si impallava la comunicazione ; io lo ho risolto leggendo il carattere sempre e scartandolo se non avevo piu' spazio nel mio buffer globale in ram.

I problemi ti possono venire da errori ti overrun / caratteri errati ed allora devi prevedere dei time-out che puliscono il buffer e dopo un tempo stabilito riparti a spedire i pacchetti ...

Se vuoi ti posso spedire a titolo di esempio il mio codice che avevo scritto pero' e' per il C della CCS mentre vedo che tu usi un compilatore differente ...

Ciao :)

Modificato: da ifachsoftware
Link al commento
Condividi su altri siti

Se ti è possibile, mi farebbe piacere che mi inviassi un codice di esempio. Per il compilatore non è un problema: mi serve per afferrare l'approccio che hai avuto tu, poi cercherò di riportarlo nel mio progetto e con il mio compilatore.

Ciao

Link al commento
Condividi su altri siti

  • 4 years later...

Buongiorno a tutti.

Mi sto scontrando con un problema di "interpretazione" del protocollo MDB.

Sto cercando di scrivere un Master MDB che comunichi con una gettoniera rendiresto.

Il problema di interpretazione al quale mi riferisco è il comando EXPANSION ($0F)

Per lo standard MDB, il bit 9 della trasmissione dovrebbe essere impostato ad 1 quando si invia l'indirizzo ed a 0 quando si iniziano a trasferire dei dati.

La cosa che non capisco è la seguente:

dal momento che il comando EXPANSION necessita di un sub-comando immediatamente dopo, cosa devo farne del bit 9?

Cioè, invio il comando EXPANSION, lascio il bit9 impostato e poi invio il sub-comando $00 (IDENTIFICATION), oppure tratto il sub.comando come fosse un dato? (cioè bit9 impostato quando invio il comando EXPANSION e poi bit9=0 quando invio il sub-comando IDENTIFICATION?

Se possibile, sarei grato di poter prendere visione (in un qualsiasi linguaggio) di un tratto di codice che effettui, per esempio, l'inizializzazione di un qualsiasi dispositivo MDB, al fine di comprenderne bene la sequenza.

Grazie per l'aiuto.

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...