Home Forum MICROCONTROLLORI SIM340 E PIC

Questo argomento contiene 31 risposte, ha 3 partecipanti, ed è stato aggiornato da  lucagiuliodori 2 anni, 11 mesi fa.

Stai vedendo 15 articoli - dal 1 a 15 (di 32 totali)
  • Autore
    Articoli
  • #58385

    davix10
    Membro

    Salve a tutti volevo sapere come gestire un modulo GSM tramite la seriale del PIC e come confrontare le stringhe ricevute dal modulo. Di seguito posto ciò che ho provato a fare ma in realtà non confronta le stringhe.
    while (1)
    {
    unsigned char corretto = “OK”;
    unsigned char i=0;
    unsigned char input,error;
    unsigned char output;
    unsigned char data[80+1];
    unsigned char x_dati; // Indice all’array.
    input = 0;
    output = 0;

    putrsUSART((const far rom char *)”AT\r\n”);// AT command test
    while(!BusyUSART());
    Delay10KTCYx(200);
    Delay10KTCYx(200);
    Delay10KTCYx(200);

    data[x_dati] = ReadUSART();

    WriteUSART (data[x_dati]);

    if (strcmppgm2ram(corretto,data[0])==0)
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    PORTAbits.RA0=0;
    Delay10KTCYx(200);
    }
    else
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    }
    }
    }

    #70248

    Emanuele
    Keymaster

    Mi sembra di capire che stai usando il C18,
    ora sono di fretta, ma posso dirti che se entri in debug con mplab puoi verificare dall’assembler cosa non va, in fin dei conti è solo un confronto :)

    Puoi anche eliminare le seriali e verificare che il tuo codice di comparazione sia corretto inserendo costanti, tramite il simulatore.

    Ricontrolla le dichiarazioni di “corretto” e “data” e poi, nella gestione della ricezione buffer seriale, la libreria considera anche un eof? (non mi ricordo)

    #70252

    davix10
    Membro

    Ho provato anche in debug ma non capisco il perchè non avvenga il confronto in modo corretto. Io su hyperterminal grazie al comando WriteUSART (data[x_dati]); vedo proprio la scritta OK. Non capisco dove sbaglio.

    #70257

    lucagiuliodori
    Partecipante

    Ciao davix10,

    se non ho capito male il tuo problema dovrebbe essere che non esegue il confronto tra la stringa ricevuta da seriale e il valore contenuto in “corretto” giusto?

    Be’ se è così i tuoi problemi dovrebbero essere due:
    – il primo sta proprio nella funzione che tu usi per fare il confronto, ossia “strcmppgm2ram”. Questa routine infatti confronta un valore che sta in RAM con un valore costante ossia un valore che sta nella program memory; non a caso “strcmppgm2ram”: str -> stringa, cmp -> compare, pgm -> program memory, 2 -> to, ram -> RAM.

    – il secondo sta nella definizione della variabile “corretto”. In C per definire una stringa devi definire un array. Una definizione fatta in quel modo ti da sicuramente un “warning” al momento della compilazione e il confronto non verrà comunque eseguito.

    Per poter fare il confronto che desideri fare devi definire la variabile “corretto” nel seguente modo: “unsigned char corretto[2] = {‘O’,’K’};” e quindi adottare due soluzioni per eseguire il confronto:

    – se il valore di “corretto” è sempre “OK” puoi mettere l’attributo “const” davanti alla tua dichiarazione “unsigned char corretto[2] = {‘O’,’K’};”, o addirittura creare una definizione del tipo “#define corretto OK” da utilizzare nelle varie routine di confronto.
    Sono simili le due proposte ma intrinsecamente differenti: il primo setta una o più locazioni (dipendente dal valore) della program memory con il valore “OK” e usa quella o quelle locazioni per il confronto; nel secondo caso viene settato il valore ogni volta che deve essere eseguito il confronto. Se conosci un po’ i microcontrollori e la programmazione in assembler, riesci bene a capire la differenza.

    – puoi utilizzare una funzione che esegue il confronto tra due stringhe in RAM. Non credo che il compilatore ne abbia una che svolga questa operazione, io per esempio me ne sono fatta una che svolge questa operazione.

    #70258

    davix10
    Membro

    Grazie per la risposta. Per il problema del comando ‘strcmppgm2ram’ hai ragione ma era solo una prova dato che ho sempre provato ‘strcmp’. Ho provato a modificare così:
    while (1)
    {
    unsigned char corretto[10];
    unsigned char i=0;
    unsigned char input,error;
    unsigned char output;
    unsigned char data;
    unsigned char risultato;
    input = 0;
    output = 0;
    corretto[0] = ‘O';
    corretto[1] = ‘K';
    corretto[2] = 0;

    putrsUSART((const far rom char *)”AT\r\n”);// AT command test
    while(!BusyUSART());
    Delay10KTCYx(200);

    data = ReadUSART();

    WriteUSART (data);

    risultato=strcmp(corretto,data);

    if (!risultato)
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    PORTAbits.RA0=0;
    Delay10KTCYx(200);
    }
    else
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    }

    #70259

    lucagiuliodori
    Partecipante

    Ok, ora hai corretto l’inizializzazione della stringa “corretto” (anche se è sufficiente utilizzare un vettore a 3 locazioni) ma comunque rimane il problema del confronto: se vai alla definizione di “strcmppgm2ram” vedrai che è definita uguale a “strcmp”, quindi il confronto viene comunque eseguito tra una stringa in RAM e una in program memory.
    Se vuoi procedere per questa strada metti “const” davanti la dichiarazione di “corretto” oppure cambia routine di confronto.

    #70260

    davix10
    Membro

    Ho provato a mettere const davanti alla dichiarazione di corretto ma quando compilo mi da errore

    #70262

    lucagiuliodori
    Partecipante

    Effettivamente mi sono dimenticato di dirti una cosa: dichiarando una variabile costante, non puoi inizializzarla durante il codice, altrimenti il compilatore la dovrebbe definire “non costante”, cosa che va in conflitto con quanto tu hai indicato nella dichiarazione con l’attributo “const”.

    Quando dichiari una variabile “const” devi inizializzarla nella dichiarazione. Nel tuo caso: “const unsigned char corretto[10]={‘O’,’K’,0};”.
    Per mettere un carattere di fine stringa o utilizzi ‘\0′ con le virgolette singole oppure semplicemente il valore 0. Se usi il carattere ‘0’ tra virgolette singole, ti mette il carattere 0 e non il valore di fine stringa.

    #70263

    davix10
    Membro

    In questo modo compila ma in realtà non funziona:
    while (1)
    {
    const unsigned char corretto[10]={‘O’,’K’,0};
    unsigned char i=0;
    unsigned char input,error;
    unsigned char output;
    unsigned char data;
    unsigned char risultato;
    input = 0;
    output = 0;

    putrsUSART((const far rom char *)”AT\r\n”);// AT command test
    while(!BusyUSART());
    Delay10KTCYx(200);

    data = ReadUSART();

    WriteUSART (data);

    risultato=strcmp(corretto,data);

    if (!risultato)
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    PORTAbits.RA0=0;
    Delay10KTCYx(200);
    }
    else
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    }

    #70264

    lucagiuliodori
    Partecipante

    La funzione “strcmp” accetta due parametri: il primo è la stringa in RAM e il secondo è la stringa in program memory. Inverti le due e vedrai che funziona…

    #70265

    davix10
    Membro

    Anche così non funziona:
    while (1)
    {
    const unsigned char corretto[10]={‘O’,’K’,0};
    unsigned char i=0;
    unsigned char input,error;
    unsigned char output;
    unsigned char data;
    unsigned char risultato;
    input = 0;
    output = 0;

    putrsUSART((const far rom char *)”AT\r\n”);// AT command test
    while(!BusyUSART());
    Delay10KTCYx(200);

    data = ReadUSART();

    WriteUSART (data);

    risultato=strcmp(data,corretto);

    if (!risultato)
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    PORTAbits.RA0=0;
    Delay10KTCYx(200);
    }
    else
    {
    PORTAbits.RA0=1;
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    }

    #70261

    lucagiuliodori
    Partecipante

    Hai controllato il valore che c’è su “data”?

    Poi una domanda: che significa non funziona?! Mi puoi dare informazioni più precise?

    #70280

    davix10
    Membro

    Su data c’è la stringa OK perchè la controllo da hyperterminal, dico che non funziona perchè nel mio programma il led dovrebbe lampeggiare se la stringa è uguale ad OK ma in realtà continua ad essere acceso

    #70285

    lucagiuliodori
    Partecipante

    Il fatto che non lampeggia è normale: ad ogni ciclo della “MainLoop” (realizzata da te con il “whilw(1)”) il microcontrollore legge un valore diverso dalla USART e quindi, al primo loop leggerà “OK” ma al secondo leggerà un altro valore (che molto probabilmente sarà un valore nullo), è per questo che il led cambia di stato ma non lampeggia.
    In questo caso per eseguire un lampeggio puoi procedere con due strade:
    – prima di leggere il dato da USART controlli se effettivamente ci sono i dati, in questo modo dal momento in cui ricevi la stringa “OK” il led inizierà a lampeggiare finchè non ricevi un’altra stringa diversa da “OK”.
    – una seconda soluzione (a mio parere la più corretta ma più difficile da implementare) è quella di utilizzare una variabile contenente lo stato che indica se è stata ricevuta o meno la stringa “OK” o quindi far lampeggiare il led (magari con un timeout che dopo un po lo arresta) quando questa variabile è settata.

    Dovresti controllare, magari con un tool per eseguire il debug, se l’esecuzione del codice effettivamente il codice entra nel ramo corretto dell’istruzione “if”, in quanto, se il led è pilotato dal micro mettendo il segnale a massa, è giusto che rimanga acceso, altrimenti c’è un errore sul confronto delle stringhe.

    Facci sapere.

    #70287

    davix10
    Membro

    Però il fatto è che non lampeggia nemmeno al primo loop, devo provare a vedere in MPLAB con la funzione watch cosa c’è in ‘data’

Stai vedendo 15 articoli - dal 1 a 15 (di 32 totali)

Devi aver eseguito l’accesso per poter rispondere a questa discussione.