PIC 18 e GPS!
Moderatore:
Paolino
31 messaggi
• Pagina 3 di 4 • 1, 2, 3, 4
0
voti
[22] Re: PIC 18 e GPS!
Cerco di illustrarti i primi risultati:
Se inserisco questo codice per la ricezione della seriale una volta che il bufferGPS supera i 200 caratteri il programma non esce più da questo ciclo e di conseguenza si blocca.
Se lo modifico così:
disattivando l'interrupt sulla periferica usart quando supero i 190 caratteri il PIC riesce a memorizzare l'intero buffer ma solo una volta.
Quando inizializzo la stringaGPS con 5 caratteri quando compilo mi da il warning
Credo che per il compilatore ogni stringa deve conteggiare un carattere in più che corrisponda al carattere di fine stringa.
Siccome ho testato il mio circuito in casa il modulo gps non risuciva ad agganciare nessun satellite, quindi le stringe NMEA sono differenti da quello che ti avevo postato.
Ho sostituito al posto della stringa
con
e ho inserito in vari punti del programma dei comandi di stampa a video, tramite l'usart libera, che ho usato come debug numerandoli in modo consegutivo.
ti posto il codice così capisci meglio
Il codice funziona infatti a video arrivo fino al numero 6 che corrisponde alla scrittura delle coordinate, se invece modifico la stringa da ricercare con un carattere che non è presente nel bufferGPS a video mi stampa solo il numero 1.
Domani provo il tutto a cielo aperto.
- Codice: Seleziona tutto
if (PIR1bits.RC1IF == 1 && i<200) {
LED_GIALLO = LED_GIALLO^1;
bufferGPS[i] = Read1USART();
i++;
}
Se inserisco questo codice per la ricezione della seriale una volta che il bufferGPS supera i 200 caratteri il programma non esce più da questo ciclo e di conseguenza si blocca.
Se lo modifico così:
- Codice: Seleziona tutto
// Controllo che l'interrupt sia stato generato dall'USART 2
if (PIR3bits.RC2IF == 1 ) {
LED_GIALLO = LED_GIALLO^1;
bufferGPS[i] = Read2USART();
i++;
if (i>=190)
PIE3bits.RC2IE=0;
}
disattivando l'interrupt sulla periferica usart quando supero i 190 caratteri il PIC riesce a memorizzare l'intero buffer ma solo una volta.
Quando inizializzo la stringaGPS con 5 caratteri quando compilo mi da il warning
- Codice: Seleziona tutto
const unsigned char stringaGPS[5]="GPRMC";
Warning [2073] null-terminated initializer string too long
Credo che per il compilatore ogni stringa deve conteggiare un carattere in più che corrisponda al carattere di fine stringa.
Siccome ho testato il mio circuito in casa il modulo gps non risuciva ad agganciare nessun satellite, quindi le stringe NMEA sono differenti da quello che ti avevo postato.
Ho sostituito al posto della stringa
- Codice: Seleziona tutto
const unsigned char stringaGPS[5]="GPRMC"
con
- Codice: Seleziona tutto
const unsigned char stringaGPS[5]="YGTOP"
e ho inserito in vari punti del programma dei comandi di stampa a video, tramite l'usart libera, che ho usato come debug numerandoli in modo consegutivo.
ti posto il codice così capisci meglio
- Codice: Seleziona tutto
void decodeNMEA(unsigned char* buff, unsigned char* c1, unsigned char * c2);
void decodeNMEA(unsigned char* buff, unsigned char* c1, unsigned char * c2){
//const unsigned char stringaGPS[6]="GPRMC";
const unsigned char stringaGPS[5]="YGTOP";
const unsigned char dimensioneBufferGPS=200;
const unsigned char dimensioneStringa=5;
unsigned char indice=0;
unsigned char trovato=0;
unsigned char i,j=0;
Write1USART('1');
while (Busy1USART());
for(i=0; i<(dimensioneBufferGPS-dimensioneStringa) && !trovato; i++)
{
if(bufferGPS[i]==stringaGPS[j])
{
Write1USART('2');
while (Busy1USART());
j++;
if(j==dimensioneStringa)
{
trovato=1;
indice=i;
Write1USART('3');
while (Busy1USART());
}
}
else
{
if(j>0)
{
i=i-j;
j=0;
}
}
}//fine ciclo for
if(trovato) //se abbiamo trovato la sequenza GPRMC ora dobbiamo contare tre virgole "," prima di leggere la prima coordinata
{
unsigned char c=0;
unsigned char cont_virgola =0;
unsigned char index=0;
trovato=0; //azzero il flag almeno lo posso riutilizzare
Write1USART('4');
while (Busy1USART());
for(c=0;c<60 && i<200 && !trovato;c++)
{
i++;
if(bufferGPS[i] == ',' )
{
cont_virgola++;
if(cont_virgola==3)
{
Write1USART('5');
while (Busy1USART());
index=i;
trovato=1;
cont_virgola=0; //azzero il contatore delle virgole
}
}
}//fine cilco for
if(trovato && index<174)
{
Write1USART('6');
while (Busy1USART());
for(c=1; c<=11; c++)
bufferGPS[i+c]=coordinata1[i+c];
for(c=13; c<=25; c++)
bufferGPS[i+c]=coordinata2[i+c];
trovato=0;
}
else
{
trovato=0;
i=0;
}
}
} //fine funzione */
Il codice funziona infatti a video arrivo fino al numero 6 che corrisponde alla scrittura delle coordinate, se invece modifico la stringa da ricercare con un carattere che non è presente nel bufferGPS a video mi stampa solo il numero 1.
Domani provo il tutto a cielo aperto.
1
voti
[23] Re: PIC 18 e GPS!
ricello9 ha scritto:...disattivando l'interrupt sulla periferica usart quando supero i 190 caratteri il PIC riesce a memorizzare l'intero buffer ma solo una volta.
Non conosco il PIC che stai usando ma non ho nemmeno notato se ad ogni interrupt esegui il reset del flag di interrupt. Ad ogni interrupt dovresti resettare il relativo flag per poter catturare anche l'interrupt successivo, e' la prima cosa da fare quando entri nella routine di interrupt.
La generazione delle interruzioni deve continuare sempre, solamente quando l'indice supera il valore 200 non scrivi piu il byte nel buffer.
Io proverei cosi:
- Codice: Seleziona tutto
if (PIR1bits.RC1IF == 1) { //questo e' il flag che mi indica l'interrupt della seriale
//****qui devi resettare il flag di interrupt*****
//e successivamente esegui le operazioni che ti interessano
LED_GIALLO = LED_GIALLO^1;
if(i<200){
bufferGPS[i] = Read1USART(); //salvo il dato nel buffer ed incremento l'indice solamente se i<200
i++;
}
}
ricello9 ha scritto:Quando inizializzo la stringaGPS con 5 caratteri quando compilo mi da il warning...
allora dichiara la stringa di 6 caratteri:
- Codice: Seleziona tutto
const unsigned char stringaGPS[6]="GPRMC";
Se non hai a disposizione un segnale GPS valido, puoi semplicemente inizializzare il buffer nel main con una stringa adatta cosi da testare la funzione decodeNMEA...
- Codice: Seleziona tutto
unsigned char buffer[]="GPGSA,A,3,05,29,25,30,16,31,,,,,,,1.51,1.20,0.91*03
$GPRMC,201023.000,A,6548.4901,N,00335.8774,E,0.44,186.45,160512,,,A*61GPGSA,A,3,05,29,25,30,16,31,,,,,,,1.51,1.20,0.91*03
$GPRMC,201023.000,A,6548.4901,N,00335.8774,E,0.44,186.4GPGSA,A,3,05,29,25,30,16,31,,,,,,,1.51,1.20,0.91*03
$GPRMC,201023.000,A,6548.4901,N,00335.8774,E,0.44,186.4";
unsigned char coordinata1[10];
unsigned char coordinata2[10];
decodeNMEA(buffer,coordinata1,coordinata2);
cosi controlli che vengano estrapolati i dati che effettivamente ti interessano
-

AjKDAP
1.255 2 6 9 - Expert EY

- Messaggi: 796
- Iscritto il: 17 mag 2006, 0:13
- Località: nella coda dei pronti
0
voti
[24] Re: PIC 18 e GPS!
Ad ogni interrupt dovresti resettare il relativo flag per poter catturare anche l'interrupt successivo, e' la prima cosa da fare quando entri nella routine di interrupt.
Con il PIC che sto (18lf26k22) usando non è possibile resettare "manualmente" il flag di ricezione seriale, ma solo andando a leggere il contenuto del buffer della seriale il flag viene resettato viene resettato.
- Codice: Seleziona tutto
The RCxIF interrupt flag bit is read-only, it cannot be set or cleared by software.
The RCxIF interrupt flag bit will be set when there is an unread character in the FIFO, regardless of the state of
interrupt enable bits.
Si vede che quando il buffer di ricezione seriale è pieno e non viene azzerato il relativo flag con la lettura del dato il PIC va in casino.
Ottimo il consiglio dell'inizializzazione del bufferGPS con i caratteri che mi servono, non ci avevo pensato.
1
voti
[25] Re: PIC 18 e GPS!
Buono a sapersi, quindi ad ogni interruzione puoi leggere il dato su una variabile temporanea cosi il flag viene resettato e solamente se interessa lo salvi nel buffer
del tipo:
del tipo:
- Codice: Seleziona tutto
if (PIR1bits.RC1IF == 1) {
unsigned char tempData=Read1USART(); //leggo il dato e resetto il flag
LED_GIALLO = LED_GIALLO^1;
if(i<200){
bufferGPS[i] = tempData;
i++;
}
}
-

AjKDAP
1.255 2 6 9 - Expert EY

- Messaggi: 796
- Iscritto il: 17 mag 2006, 0:13
- Località: nella coda dei pronti
0
voti
[26] Re: PIC 18 e GPS!
Ciao, ho testato il codice con l'inizializzazione del bufferGPS come mi hai suggerito e dopo alcuni aggiustamenti al codice a video leggo proprio le due stringhe di latitudine e longitudine.
Se però collego fisicamento il modulo gps e tolgo l'inizializzazione del bufferGPS:
il PIC mi esce dal ciclo principale,come se fosse sempre impeganto nella lettura dei dati in arrivo; mi accorgo perché ho inserito un :
nel cilo while principale e non vedo il led lampeggiare, vedo solo quello collegato alla lettura dei dati in ingresso all'usart che continua a lavorare.
L'unico modo per far eseguire il programma nel modo corretto è disabilitare la ricezione dell'usart dopo aver ricevuto i 200 carartteri ma non penso che sia una soluzione giusta.
Può essere che siccome il modulo gps mi butta fuori la serie di dati quasi in modo continuo il PIC non abbia tempo per eseguire l'accensione e la pausa del led verde che ho messo nel ciclo while.
Hai qualche suggerimento?
Se però collego fisicamento il modulo gps e tolgo l'inizializzazione del bufferGPS:
- Codice: Seleziona tutto
if (PIR3bits.RC2IF == 1) {
unsigned char tempData=Read2USART(); //leggo il dato e resetto il flag
LED_GIALLO = LED_GIALLO^1;
if(i<200){
bufferGPS[i] = tempData;
i++;
}
il PIC mi esce dal ciclo principale,come se fosse sempre impeganto nella lettura dei dati in arrivo; mi accorgo perché ho inserito un :
- Codice: Seleziona tutto
while (1){
LED_VERDE = LED_VERDE^1;
Delay10KTCYx(100);
nel cilo while principale e non vedo il led lampeggiare, vedo solo quello collegato alla lettura dei dati in ingresso all'usart che continua a lavorare.
L'unico modo per far eseguire il programma nel modo corretto è disabilitare la ricezione dell'usart dopo aver ricevuto i 200 carartteri ma non penso che sia una soluzione giusta.
- Codice: Seleziona tutto
while (1){
LED_VERDE = LED_VERDE^1;
Delay10KTCYx(100);
while(i>198); //aspetti mentre ricevi 200bytes
PIE3bits.RC2IE = 0;
decodeNMEA(bufferGPS,coordinata1,coordinata2);
Può essere che siccome il modulo gps mi butta fuori la serie di dati quasi in modo continuo il PIC non abbia tempo per eseguire l'accensione e la pausa del led verde che ho messo nel ciclo while.
Hai qualche suggerimento?
1
voti
[27] Re: PIC 18 e GPS!
Sono contento che la funzione decodeNMEA faccia quello che ti aspettavi, hai fatto un buon lavoro
Quello che non capisco è questo:
se i è impostato a zero ad esempio, questo ciclo while viene saltato direttamente.
Ovviamente prima di iniziare l'acquisizione dei 200bytes devi te impostare manualmente l'indice a zero, io non ho visto nessuna istruzione a riguardo, dovresti fare una cosa del genere:
il comportamento che descrivi dell'interrupt è strano comunque...
Quello che non capisco è questo:
- Codice: Seleziona tutto
while(i>198); //aspetti mentre ricevi 200bytes
se i è impostato a zero ad esempio, questo ciclo while viene saltato direttamente.
Ovviamente prima di iniziare l'acquisizione dei 200bytes devi te impostare manualmente l'indice a zero, io non ho visto nessuna istruzione a riguardo, dovresti fare una cosa del genere:
- Codice: Seleziona tutto
while (1){
LED_VERDE = LED_VERDE^1;
Delay10KTCYx(100);
i=0; //azzeri l'indice per partire a riempire il buffer dalla posizione zero!
while(i<200); //aspetti mentre ricevi 200bytes, quando i==200 esce dal ciclo!
decodeNMEA(bufferGPS,coordinata1,coordinata2);
//qui dovresti inviare al PC le due coordinate per avere un debug...
}
il comportamento che descrivi dell'interrupt è strano comunque...
-

AjKDAP
1.255 2 6 9 - Expert EY

- Messaggi: 796
- Iscritto il: 17 mag 2006, 0:13
- Località: nella coda dei pronti
2
voti
[28] Re: PIC 18 e GPS!
ricello9 ha scritto:
- Codice: Seleziona tutto
if (PIR3bits.RC2IF == 1) {
unsigned char tempData=Read2USART(); //leggo il dato e resetto il flag
LED_GIALLO = LED_GIALLO^1;
if(i<200){
bufferGPS[i] = tempData;
i++;
}
il PIC mi esce dal ciclo principale,come se fosse sempre impeganto nella lettura dei dati in arrivo;
E' normale, se non setti manualmente tu PIR3bits.RC2IF a 0 li dentro, lui continuera' a entrarci continuamente.
Ti faccio vedere come raccolgo io i dati da una UART:
- Codice: Seleziona tutto
void DomotikaSerial_ISR(void)
{
static BYTE toolong = 0;
BYTE dummy;
if(PIR1bits.RCIF)
{
// Get the byte only if we have enough space
// on the circular rx buffer
if(buftbr < SP_MAX_BUF)
{
SP_RXFIFO[rxiidx] = RCREG;
buftbr++;
if(rxiidx < SP_MAX_BUF)
{
rxiidx++;
} else {
rxiidx=0;
}
PIR1bits.RCIF = 0;
toolong=0;
} else {
toolong++;
if(toolong > 10) {
// More than 10 interrupt cycles and we don't are
// capale to clear the buffer? maybe it is better to
// discard this byte!
toolong=0;
dummy = RCREG;
PIR1bits.RCIF = 0;
}
}
}
if(PIR1bits.TXIF)
{
// Try to transmit a byte
if(buftbw > 0)
{
TXREG = SP_TXFIFO[txoidx];
buftbw--;
if(txoidx < SP_MAX_BUF)
{
txoidx++;
} else {
txoidx=0;
}
}
if(buftbw == 0)
PIE1bits.TXIE = 0;
}
}
Franco (nextime) Lanza
Direttore ricerca & sviluppo, main developer e Geek
presso Unixmedia S.r.l. - Sistemi domotici innovativi su rete Ethernet
Sito aziendale: http://www.unixmedia.it
Prodotti, shop, area-tecnca: http://domotika.unixmedia.net
Direttore ricerca & sviluppo, main developer e Geek
presso Unixmedia S.r.l. - Sistemi domotici innovativi su rete Ethernet
Sito aziendale: http://www.unixmedia.it
Prodotti, shop, area-tecnca: http://domotika.unixmedia.net
0
voti
[29] Re: PIC 18 e GPS!
AjKDAP ha scritto:Sono contento che la funzione decodeNMEA faccia quello che ti aspettavi, hai fatto un buon lavoro![]()
Quello che non capisco è questo:
- Codice: Seleziona tutto
while(i>198); //aspetti mentre ricevi 200bytes
se i è impostato a zero ad esempio, questo ciclo while viene saltato direttamente.
Ovviamente prima di iniziare l'acquisizione dei 200bytes devi te impostare manualmente l'indice a zero, io non ho visto nessuna istruzione a riguardo, dovresti fare una cosa del genere:
- Codice: Seleziona tutto
while (1){
LED_VERDE = LED_VERDE^1;
Delay10KTCYx(100);
i=0; //azzeri l'indice per partire a riempire il buffer dalla posizione zero!
while(i<200); //aspetti mentre ricevi 200bytes, quando i==200 esce dal ciclo!
decodeNMEA(bufferGPS,coordinata1,coordinata2);
//qui dovresti inviare al PC le due coordinate per avere un debug...
}
il comportamento che descrivi dell'interrupt è strano comunque...
Come al solito avevi ragione, azzerando il l'indice "i" e sistemando il codice while il tutto sembra andare correttamente, forse l'unico problema è dato dal fatto che il ciclo del PIC attende che il buffer superi i 200 caratteri per poter eseguire qualsiasi istruzione successiva comportando un eccessivo rallentamento.
Devo pensare an un sistema per filtrare il contenuto del buffer ottenendo solo la stringa che mi serve.
0
voti
[30] Re: PIC 18 e GPS!
nextime ha scritto:ricello9 ha scritto:
- Codice: Seleziona tutto
if (PIR3bits.RC2IF == 1) {
unsigned char tempData=Read2USART(); //leggo il dato e resetto il flag
LED_GIALLO = LED_GIALLO^1;
if(i<200){
bufferGPS[i] = tempData;
i++;
}
il PIC mi esce dal ciclo principale,come se fosse sempre impeganto nella lettura dei dati in arrivo;
E' normale, se non setti manualmente tu PIR3bits.RC2IF a 0 li dentro, lui continuera' a entrarci continuamente.
Ti faccio vedere come raccolgo io i dati da una UART:
- Codice: Seleziona tutto
void DomotikaSerial_ISR(void)
{
static BYTE toolong = 0;
BYTE dummy;
if(PIR1bits.RCIF)
{
// Get the byte only if we have enough space
// on the circular rx buffer
if(buftbr < SP_MAX_BUF)
{
SP_RXFIFO[rxiidx] = RCREG;
buftbr++;
if(rxiidx < SP_MAX_BUF)
{
rxiidx++;
} else {
rxiidx=0;
}
PIR1bits.RCIF = 0;
toolong=0;
} else {
toolong++;
if(toolong > 10) {
// More than 10 interrupt cycles and we don't are
// capale to clear the buffer? maybe it is better to
// discard this byte!
toolong=0;
dummy = RCREG;
PIR1bits.RCIF = 0;
}
}
}
if(PIR1bits.TXIF)
{
// Try to transmit a byte
if(buftbw > 0)
{
TXREG = SP_TXFIFO[txoidx];
buftbw--;
if(txoidx < SP_MAX_BUF)
{
txoidx++;
} else {
txoidx=0;
}
}
if(buftbw == 0)
PIE1bits.TXIE = 0;
}
}
Con il PIC che sto (18lf26k22) usando non è possibile resettare "manualmente" il flag di ricezione seriale, ma solo andando a leggere il contenuto del buffer della seriale il flag viene resettato viene resettato.
The RCxIF interrupt flag bit is read-only, it cannot be set or cleared by software.
The RCxIF interrupt flag bit will be set when there is an unread character in the FIFO, regardless of the state of interrupt enable bits.
31 messaggi
• Pagina 3 di 4 • 1, 2, 3, 4
Torna a Firmware e programmazione
Chi c’è in linea
Visitano il forum: Nessuno e 7 ospiti

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)


