Vai al contenuto
PLC Forum


Problema Ricezione Rs232 Pic


Edge

Messaggi consigliati

Il buffer lo dimensioni tenendo conto della velocità di trasmissione e dell'intervallo di tempo masimo che può intercorrere tra du routines di servizio.

Io, solitamente definisco un buffer di 10 caratteri, ma è solo per mia abitudine.

Altro caso se sai che ogni trasmissione termina con un carattre di chiusura ed una lunghezza massima ben precisa. Tipico, ad esempio, il caso di Modbus dive hai 128 caratteri. Qui definisci un buffer di max 128. La routine di servizio la lanci solo quando hai ricevuto il carattere di fine; il test lo fai nella routune di servizio dell'interrupt.

Se invece non hai lunghezze di trasmissione standard o caratteri di fine tx, allora devi lanciare la routine di ricezione ad intervalli più o meno ciclici; mentre svuoti il buffer devi inbire l'interrupt di ricezione onde evitare sovrapposizioni.

Link al commento
Condividi su altri siti


Ecco, questo per esempio non lo facevo.

Bè, quello che so è che se un comando va a buon fine, si conclude sempre con un OK seguito da un CRLF, altrimenti un ERROR seguito da CRLF.

Questo controllo quindi lo posso fare con un IF nella routine di servizio giusto?

Basta che controlli se prima di CRLF c'è un OK o un ERROR.

Saluti

Edge

Link al commento
Condividi su altri siti

Certo. Poi alzi il flag di EOT (End Of Transmission) e se c'è OK alzi anche il flag di DataOK.

Poi dal main e da altro programma con flag EOT vero lanci la routine di ricezione dove svioterai il buffer e abbasserai i flags.

Link al commento
Condividi su altri siti

Oh, bene. Ho capito!

Spero sia la volta buona. A parte che sono un "testone" di natura e ci ragiono 1000 molte e mi dovete scusare.

Saluti

Edge

Link al commento
Condividi su altri siti

Se dici che la comunicazione tra PC e modem funziona (e ovviamente non c’è motivo di dubitarne) il problema, per esclusione, rimane nella routine che legge o meglio gestisce, il buffer Rx.

Mi sembra che in un esempio del main che hai messo sul forum fai lo “switch” sul carattere: è’ più comodo e funzionale fare una macchina a stati e non il controllo sul singolo carattere;

Ho fatto le routine per la gestione di un buffer circolare.

typedef	unsigned char	u_char;
// 0 < MAX_CHAR < 256  	// ATTENZIONE !!!


/* Definizione coda circolare di ricezione RS232 da interrupt	*/
struct	tag_rx
	{
	u_char	n_car;  // numero car. in coda
	u_char	ptr_rd;  // puntatore lettura
	u_char	ptr_wr;  // puntatore crittura
	u_char	car [MAX_CHAR];	// buffer
	u_char	car_rd;  // ultimo carattere letto
	};


/* Dichiarazione    	*/
struct	tag_rx	coda_rx;


/* Svuota coda di ricezione    */
// Solo come inizializzazione
void svuota_rx (void)
  {
  //INTCONbits.GIEH = 0;  // Disable all interrupts high
  //INTCONbits.GIEL = 0;  // Disable all interrupts low
  coda_rx.n_car = 0;
  coda_rx.ptr_rd = 0;
  coda_rx.ptr_wr = 0;
  //INTCONbits.GIEH = 1;  // Enable all interrupts high
  //INTCONbits.GIEL = 1;  // Enable all interrupts low
  }


/* Legge un carattere dalla coda di ricezione  	*/
/* Ritorna: 0x00 = nessun carattere in coda  	*/
/*          0x01 = carattere presente (viene scritto in "car_rd")	*/
u_char read_rx (void)
  {
  u_char  tmp;	
  struct  tag_rx  *ptr_lg = &coda_rx;

  INTCONbits.GIEH = 0;
  INTCONbits.GIEL = 0;
  if (ptr_lg->n_car == 0)
    tmp = 0x00;
  else
    {
    ptr_lg->car_rd = ptr_lg->car[ptr_lg->ptr_rd];
    if (++ptr_lg->ptr_rd >= (u_char)MAX_CHAR)   ptr_lg->ptr_rd = 0;
    ptr_lg->n_car--;
    tmp = 0x01;
    }
  //INTCONbits.GIEH = 1;
  //INTCONbits.GIEL = 1;
  INTCON = INTCON | 0xc0;	// meglio usare questa
  return (tmp);
  }


/* Scrive un carattere nella coda di ricezione  */
/* Deve essere chiamata da interrupt !!!  	*/
void write_rx (u_char tmp)
  {
  struct  tag_rx  *ptr_lg = &coda_rx;

  if (++ptr_lg->n_car > (u_char)MAX_CHAR)
    ptr_lg->n_car--;
  else
    {
    ptr_lg->car[ptr_lg->ptr_wr] = tmp;
    if (++ptr_lg->ptr_wr >= (u_char)MAX_CHAR)   ptr_lg->ptr_wr = 0;
    }
  }

Ci sentiamo.

Link al commento
Condividi su altri siti

Eccomi kappa, ero fuori per lavoro e non ho risposto prima.

Innanzitutto ti ringrazio per la pazienza.

Bè, complimenti, sei un certo programmatore. Da noi si dice che "Mi mangi i risi in testa" . Allora, ci ho messo un pò a capire come l'hai fatto perchè non è così immediato e ci dovevo ragionare sù. Come avevi visto io l'ho implementato in maniera abbastanza "farraginosa". Poi ho provato ad implementarlo e ti posso dire con immenso piacere che funziona!!!

Rimango però ancora col dubbio sul perchè devo per forza fare una gestione di questo tipo.

Per esempio, non sò se hai seguito gli ultimi post che ho scritto, ma ho provato a fare una routine di interrupt molto semplice e ho seguito i consigli di Livio Orsini.

Quando avviene l'interrupt copio il carattere ricevuto nel buffer di ricezione, verifico se l'ultimo carattere ricevuto è un CR seguito da un OK e se è VERO, allora alzo un flag di ricezione completata, altrimenti incremento il puntatore del buffer, e così via...

Poi dal main faccio tutta la gestione.

Nel main in un ciclo for verifico la stringa che è scritta nel buffer:

if(buffer[contatore]=='K' && buffer[contatore-1]=='O')

LCD_Out("OK");

Questo ciclo for è inserito all'interno di un ciclo while e si attiva quando il flag di ricezione completata è a 1.

Allora, questa gestione non funziona al primo colpo, ma bisogna che il comando che invio al modem venga inviato almeno un paio di volte.

Se non ci fosse il ciclo while con cui faccio ripetere la procedura finchè non leggo OK, non funzionerebbe.

Ma perchè?

Saluti

Edge

Link al commento
Condividi su altri siti

Bisogna sempre dividere il problema principale in sottoproblemi (da buon analista).

1 - verificare se si invia sempre il comando corretto al modem. Se non è corretto...

2 - se il comando è corretto verificare se e cosa risponde il modem.

Se tutto è OK dovresti vedere un invio del comando al modem e la sua risposta relativa. Se a volte uno di questi comandi "cicca" ti spieghi il perchè non va

Link al commento
Condividi su altri siti

Mi hai dato una buona idea Livio.

Ho realizzato un piccolo circuito di collegamento tra PIC, modem e Hyperterminal come supervisore del dialogo fra i due.

In questo modo sono riuscito a vedere effettivamente tramite Hyperterminal le stringhe di comandi che si scambiano i due "rompiscatole".

Effettivamente a volte capita che il modem non risponde ne con un OK e ne con un ERROR anche se il comando va a buon fine.

Mistero svelato!

Saluti

Edge

Link al commento
Condividi su altri siti

I motivi per cui il modem non risponde possono essere diversi.

Mi vengono in mente questi:

1) E’ uscito correttamente dalla procedura di power-on ?

2) Non ha capito il comando per cui lo ignora.

3) Il comando ha bisogno di “tempo” per essere effettuato (ad esempio ATD+numero telefonico).

Link al commento
Condividi su altri siti

Per quanto riguarda la procedura di power on, ne sono sicuro che funzioni, ad ogni modo seguo a menadito le specifiche sul datasheet di fornire un fronte 1-0 per almeno un secondo.

Poi se controllo con un tester il pin RXD del modem si nota che passa da 0 a 2.8V una volta attivo.

Per quanto riguarda le tempistiche dei comandi, mi pare strano per i comandi che uso, perchè per ora utilizzo comandi basilari come ATE0, AT+CPIN, AT+CFUN=1...

Ad ogni modo sul datasheet ci sono anche le tempistiche dei comandi.

Per quando riguarda che i comandi non vengano interpretati, può darsi, però a volte ho notato con il circuitino che prima ho fatto, è che il comando va a buon fine senza che ci sia OK come risposta.

Saluti

Edge

Link al commento
Condividi su altri siti

poichè hai un solo un segnale per accendere/spegnere il modem sarebbe buona cosa controllare lo stato leggendo l'output del modem che va a 2.8V quando si accende Così puoi sapere con certezza se è acceso o spento e agire di conseguenza.

Come primissima cosa invia al modem solo AT\r\n serve al modem per stabilire il baudrate sulla seriale in modo automatico Dopo aver ricevuto OK invia ATZ per portare il modem in uno stato noto aspetta l'OK e poi parti con la configurazione.

Prima di eseguire un'operazione verso la rete GMS/GPRS devi controllare almeno che il modulo sia registrato AT+CREG. All'accensione la registrazione può richiedere del tempo (secondi) quindi ti consiglio di controllare periodicamente lo stato della registrazione con il comando di prima.

Il GM862 ha un output per un led che cambia blink quando il modulo è registrato puoi utilizzare quella indicazione per capire cosa succede.

Mi lascia perplesso l'affermazione che il modem esegua un comando e non risponda io per esperienza già fatta sono del parere che l'interfaccia verso il modulo vada realizzata con i pullup che si alimentano dal modem quando si accende come spiegano sulla documentazione.

Modificato: da accacca
Link al commento
Condividi su altri siti

Scusa accaca, ieri ero fuori per delle manutenzioni e non sono riuscito a rispondere.

Allora, ieri sera ho rifatto delle prove e sono riuscito a farlo andare correttamente senza mai sbagliare lasciando il collegamento trai i due pin di RX (sia del PIC che del modem) sotto il collegamento dei due MAX transceiver, mentre i pin di TX gli ho collegati con una resistenza di pull-up e poi ci ho messo anche un diodo con il catodo rivolto verso il pin TX del PIC.

Tutto funziona egregiamente se faccio questo collegamento. Anche perchè lo vedo in tempo reale da hyperterminal che cosa si scambiano pic e modem.

Mi funziona anche senza creare buffer circolare.

Se però ricevo una stringa su due righe del tipo:

"Pinco pallino 123"

OK

e ho un buffer[MAX] con MAX=64, la stringa OK mi si sovrappone alla prima che ricevo, oppure nel buffer trovo un'unica stringa del tipo "Pinco pallino 123"CRLFOK ?

Saluti

Edge

Link al commento
Condividi su altri siti

Con un buffer di 64 caratteri non dovresti avere sovrapposizione, a meno di non aver svuotato il buffer in precedenza.

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...