Home
Accesso / Registrazione
 di 

SIM340 E PIC

31 risposte [Ultimo post]
ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23

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);
}
}
}

ritratto di Emanuele
Offline
Titolo: Moderator
Moderatore
Ultima visita:
4 ore 47 min fa
Utente dal: 28/07/2007
Messaggi: 1022
Utente PREMIUM
C18

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)

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Ho provato anche in debug ma

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.

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Ciao davix10, se non ho

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.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Grazie per la risposta. Per

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);
}

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Ok, ora hai corretto

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.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Ho provato a mettere const

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

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Effettivamente mi sono

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.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
In questo modo compila ma in

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);
}

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
La funzione "strcmp" accetta

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

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Anche così non

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);
}

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Hai controllato il valore che

Hai controllato il valore che c'è su "data"?

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

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Su data c'è la stringa OK

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

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Il fatto che non lampeggia è

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.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Però il fatto è che non

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

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Che non lampeggia nemmeno al

Che non lampeggia nemmeno al primo loop potrebbe essere una cosa normale: se la funzione che realizza il delay è molto breve è normale che non vedi il lampeggio perchè è eseguito molto velocemente. A quanti secondi corrisponde quella routine di delay che utilizzi?

Comunque si, fai bene a controllare il valore tramite la "watch" dell'mplab.

Fammi sapere che risultati ti da.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Quello non è possibile perchè

Quello non è possibile perchè il ritardo è di un secondo.

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Il led è pilotato dal

Il led è pilotato dal microcontrollore attraverso l'anodo giusto?! Se così allora vuol dire che va sul ramo dell'if in cui non ha riconosciuto la stringa "OK".

Controlla da MPLAB cosa contiene la variabile "data", magari può trattarsi anche di un problema di "maiuscole-minuscole".

Fammi sapere.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Su data come valore mi mette

Su data come valore mi mette 0, come è possibile?

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Innanzitutto mi sono accorto

Innanzitutto mi sono accorto che "data" lo hai dichiarato come un "unsigned char", in realtà per il tuo utilizzo devi dichiararla come un array di "char", per esempio "char[20]".
Inoltre ti consiglio di eseguire la lettura solo quando il dato è disponibile sulla RS232 e non ad ogni loop (per esempio puoi utilizzare un "if" che controlla la funzione che segnala quando sono disponibili i dati su RS232), altrimenti potresti leggere qualcosa che non è corretto.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Ok guarda come ho modificato

Ok guarda come ho modificato ora aggiungendo while (!DataRdyUSART())

while (1)
{
const unsigned char corretto[10]={'O','K',0};
unsigned char i=0;
unsigned char input,error;
unsigned char output;
char data[20];
unsigned char risultato;
input = 0;
output = 0;

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

data[0] = 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);
}

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Si ok, prova a farlo

Si ok, prova a farlo funzionare così e verificare i valori.

Due piccoli suggerimenti:
- non utilizzerei gli "while" perchè sospensivi (non è mai buona cosa far rimanere il software in sospeso dentro un loop che non sia quello della Main), io utilizzerei dei semplici if in cui controllano rispettivamente se la USART è occupata e se è disponibile il dato e che quindi eseguono l'operazione corrispondente.
- quando esegui la lettura da USART è sufficiente indicare "data" senza le parentesi "[0]". E' la stessa cosa in quanto entrambe le metodologie rappresentano il primo puntatore dell'array ma è più sintatticamente corretto scrivere solo "data".

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Se metto data senza le

Se metto data senza le parentesi [0] quando compilo mi da questi errori:
Error [1153] cannot assign array type objects
Error [1102] cannot assign to 'const' modified object
Error [1131] type mismatch in assignment
Warning [2054] suspicious pointer conversion

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
cosa può essere?

cosa può essere?

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Eccomi e scusa il ritardo.

Eccomi e scusa il ritardo. Rispondo qua altrimenti le finestre diventano sempre più piccole :)

Se ti da errore molto probabilmente è perchè la funzione che legge i valori dall'USART non restituiscono un puntatore. Ora non ho la guida sotto mano, se hai modo dovresti verificare i dati che vengono restituiti da questa funzione, altrimenti devi aspettare ancora un po' e quando avrò la guida sotto mano ti faccio sapere.

Fammi sapere

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Proverei a verificare i dati

Proverei a verificare i dati della funzione ma non riesco a capire come fare perchè dalla funzione 'WATCH' non visualizzo nessun valore

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Ciao davix10, dando per

Ciao davix10,

dando per scontato che stai usando un PIC18 (dopo l'intervento di Emanuele non hai più risposto) questa mattina aprendo l'help della Microchip mi sono accorto che la funzione di lettura della USART che stai usando tu, leggono un byte alla volta dalla USART e quindi è normale che ti da quell'errore in quanto, con "data[0]" metti il byte sulla prima locazione del vettore, con "data" semplicemente lo assegni come puntatore, operazione non corretta.
Qualche post fa ti avevo suggerito in modo sbagliato perchè non ricordavo bene che tipo di dato restituisse quella funzione e mi sono fidato di quello che avevi scritto tu nel codice iniziale.
Farebbe comunque comodo sapere che microcontrollore della famiglia PIC18 stai usando.

Anche se con "data[0]" il compilatore compila, l'algoritmo non è corretto in quanto ad ogni ciclo il valore viene messo sempre su "data[0]" rendendo inutile la definizione di "data" come vettore. Dovresti reimplementare l'algoritmo in modo che accumula o rielabora i dati provenienti dall'USART un byte alla volta.

Un'ultima cosa: usa i manuali che ti da a disposizione la Microchip perchè altrimenti rischi di riempire il forum di post che si risolvono semplicemente dando un'occhiata più attenta ai manuali.

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Grazie della risposta. Io

Grazie della risposta. Io utilizzo un PIC18F4520, ora darò un'occhiata ai manuali della Microchip

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Ho provato a leggere i

Ho provato a leggere i manuali ma non ho trovato nessuna soluzione.

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
Ciao davix10, nessuna

Ciao davix10,

nessuna soluzione a cosa? Come ti ho detto nel post precedente, per farlo compilare devi usare "data[0]" ma poi devi riscrivere il codice in modo che via via l'algoritmo mette sulle locazione successive del vettore, dati provenienti dall'USART, insomma devi usare "data[i]" al posto di "data[0]" in cui l'indice "i" punta alla prima locazione libera (attenzione, in questo caso devi considerare un buffer come circolare).

Implementa questa soluzione e vedi come va.

Facci sapere.
Ciao!

ritratto di davix10
Offline
Titolo: User+
Utente+
Ultima visita:
1 anno 16 settimane fa
Utente dal: 19/06/2011
Messaggi: 23
Ho già provato in questo modo

Ho già provato in questo modo ma se controllo "data" risulta vuoto e quindi è come se non avessi ricevuto nulla.

ritratto di lucagiuliodori
Offline
Titolo: PowerUser
Utente Power
Ultima visita:
4 giorni 12 ore fa
Utente dal: 21/03/2011
Messaggi: 195
A questo punto è difficile

A questo punto è difficile fare una valutazione del problema senza avere il progetto sotto mano.
Ti abbiamo dato diverse indicazioni su dove andare ad agire e come intervenire, ora prova a "giocarci" un po' tu e vedere se riesci a risolvere il problema da solo.

Ciao!

 

 

Login   
 Twitter Facebook LinkedIn Youtube Google RSS

Chi è online

Ci sono attualmente 8 utenti e 55 visitatori collegati.

Ultimi Commenti