Problema RS232 tra PIC e PC

  • Ricky85
  • Autore della discussione
  • Anziano Utente
  • Anziano Utente
Di più
14 Anni 2 Mesi fa #1 da Ricky85
Problema RS232 tra PIC e PC è stato creato da Ricky85
Ciao a tutti!

Innanzitutto complimenti per il forum e per il sito, davvero geniale!

Sono un felicissimo "utente" della guida PIC18 step by step e possessore di Freedom II

Sto sviluppando un sistemino per comunicare tra PIC e PC tramite la seriale, l'obbiettivo è quello di poter comandare delle uscite del PIC dal PC e leggere sul PC i valori di alcuni sensori collegati al PIC.

Andando avanti nelle mie prove mi sono "arenato" cercando di mandare al PC il valore di un sensore di temperatura, in pratica quando "spedisco" il valore del sensore al PC a terminale riceve solamente simboli strani. Per inviare dati sulla seriale posso usare due comandi:

WriteUSART che puo spedire solamente un tipo char
putrsUSART che puo spedire stringhe (ma pare non gli piaccia spedire delle variabili)

Di seguito il listato

Code:
#include <p18f4550.h> #include <usart.h> #define LCD_DEFAULT #include <LCD_44780.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF //Prototipo di funzione int lett_temp0 (); void main (void){ //***************************************** // DICHIARAZIONI VARIABILI/COSTANTI //***************************************** // Variabile per salvare il dato di ritorno unsigned char data = 0; //***************************************** // SETUP PORT //***************************************** // Imposto PORTA tutti ingressi LATA = 0b00000000; TRISA = 0b11111111; // Imposto PORTB tutti ingressi LATB = 0b00000000; TRISB = 0b11111111; // Imposto PORTC tutti ingressi LATC = 0b00000000; TRISC = 0b11111101; // Imposto PORTD tutte uscite LATD = 0b00000000; TRISD = 0b00000000; // Imposto PORTE tutti ingressi LATE = 0b00000000; TRISE = 0b11111111; //***************************************** // SETUP LCD //***************************************** OpenLCD (20); BacklightLCD (TURN_ON); //***************************************** // SETUP ADC //***************************************** // Abilito AN0-AN1-AN2 come ingressi analogico // VREF sono impostate a massa e VCC ADCON1 = 0b00001101; // Seleziono AN1 come ingresso ADCON0 = 0b00001000; // Imposto i tempi di conversione e giustificazione a destra // TAD : FOSC/4 // TACQ: 16 TAD ADCON2 = 0b10110100; // Abilito l' ADC ADCON0 |= 0b00000001; //***************************************** // SETUP USART //***************************************** // Configura l'USART // 8 bit // 19200 bit/s // 1 bit stop // 0 bit parità OpenUSART( USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 64 ); // Invio la stringa al terminale putrsUSART ("...start writing: "); // Invio la stringa all'LCD WriteStringLCD ("...start writing"); // Attendo di ricevere un dato dal PC while(!DataRdyUSART( )); ClearLCD (); // Ciclo infinito while(1) { // Leggo il dato dal buffer di ricezione data = ReadUSART(); WriteCharLCD (data); // Invio il carattere al terminale WriteUSART (data); // Attendo che il dato venga trasmesso while (BusyUSART()); // Se premo Back Space pulisco lo schermo if(data == 0x08) { ClearLCD (); } // Se premo Esc termino l'applicazione if(data == 0x2B) { putrsUSART ("Vado a leggere la temp"); while (BusyUSART()); WriteIntLCD (lett_temp0(),2) ; WriteUSART (lett_temp0()); while (BusyUSART()); } // Se premo Esc termino l'applicazione if(data == 0x1B) { break; } // Attendo di ricevere un dato dal PC while(!DataRdyUSART( )); } // Chiudo l'USART CloseUSART(); // Ripulisco LCD prima di riscrivere ClearLCD (); // L'USART è stata chiusa WriteStringLCD ("RS232 : Closed"); // Ciclo infinito while (1) { } } int lett_temp0 () { int temp0; // Avvio la conversione Analogico/Digitale ADCON0bits.GO = 1; // Attendo la fine della conversione while(ADCON0bits.GO); // Prelevo il valore della conversione temp0 = (((int) ADRESH) << 8) | ADRESL; // 1 shift per avere la temperatura in gradi // divido cioè per 2 temp0 = temp0 >> 1; return (temp0); }

Sul lato PC sto utilizzando un simil-Hyperterminal che ho trovato in rete (ho i sorgenti e lo sto modificando per le mie esigenze)

Qualcuno puo darmi qualche consiglio per riuscire a mandare questo malefico dato della temperatura al PC?

L'unica possibilità che mi viene ancora in mente è provare a trasformare il dato int in una stringa (o meglio un array di char) e spedire un char per volta, ma non ci sono ancora riuscito!

Grazie! ^^

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
14 Anni 2 Mesi fa #2 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Re: Problema RS232 tra PIC e PC
Ciao Ricky,

benvenuto nel Forum.

Riguardo alla tua domanda assumo che la parte del programma relativa alla visualizzazione delle stringhe sul display funzioni correttamente, visualizzando anche la temperatura. Inoltre assumo che sul terminal riesci a visualizzare le stringhe che invii, eccetto la temperatura. Se non è così hai anche altri problemi.

Relativamente alla temperatura è normale che non riesci ad inviarla poiché il valore letto è un intero.
Mentre le funzioni che hai usato inviano rispettivamente un byte mentre un int è composto da due byte.
Nel caso specifico, visto che le temperature sono basse potresti anche fare un casting in char

WriteUSART ( (char) lett_temp0());

In ogni modo quello che otterresti sul terminal non sarebbe il valore della temperatura ma un carattere strano ASCII associato al valore della temperatura.

Per visualizzare sul terminal direttamente il valore della temperatura devi convertire il valore intero in stringa e poi usare la funzione per inviare la stringa (che di suo non converte in automatico in stringa il valore di un intero).

Per convertire un intero in stringa puoi far riferimento alla seguente funzione (usata nella libreria LCD)
Code:
//************************************************************ // WriteIntLCD Implementation //************************************************************ void WriteIntLCD(int value, char number_of_digits){ // The array size is 5 plus end of string \0 unsigned char convertedInt [6]; // Index used to shift to the right the digit char index; // Integer is converted to string itoa (value, (char*) convertedInt); if (number_of_digits >0 ) { convertedInt[number_of_digits] = '\0'; // Shift the digit to the right removing the empty one while (!isdigit(convertedInt[number_of_digits-1])) { for (index = number_of_digits-1; index > 0; index--){ convertedInt[index] = convertedInt[index-1]; convertedInt[index-1] = ' '; } } } WriteVarLCD (convertedInt); }


in particolare la funzione di tuo interesse è :
Code:
// Integer is converted to string itoa (value, (char*) convertedInt);

per essere utilizzata devi includere il seguente file:
Code:
#include <ctype.h>

Saluti,

Mauro

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Ricky85
  • Autore della discussione
  • Anziano Utente
  • Anziano Utente
Di più
14 Anni 2 Mesi fa #3 da Ricky85
Risposta da Ricky85 al topic Re: Problema RS232 tra PIC e PC
Ciao Mauro,

intanto grazie mille della risposta...

Stasera ho fatto un po di prove ma non ho ancora risolto...

Questo è il codice modificato
Code:
#include <p18f4550.h> #include <usart.h> #include <ctype.h> #define LCD_DEFAULT #include <LCD_44780.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF //Prototipo di funzione int lett_temp0 (); void WriteIntUSART(int value, char number_of_digits); void main (void){ //***************************************** // DICHIARAZIONI VARIABILI/COSTANTI //***************************************** // Variabile per salvare il dato di ritorno unsigned char data = 0; int dato_da_convertire; //***************************************** // SETUP PORT //***************************************** // Imposto PORTA tutti ingressi LATA = 0b00000000; TRISA = 0b11111111; // Imposto PORTB tutti ingressi LATB = 0b00000000; TRISB = 0b11111111; // Imposto PORTC tutti ingressi LATC = 0b00000000; TRISC = 0b11111101; // Imposto PORTD tutte uscite LATD = 0b00000000; TRISD = 0b00000000; // Imposto PORTE tutti ingressi LATE = 0b00000000; TRISE = 0b11111111; //***************************************** // SETUP LCD //***************************************** OpenLCD (20); BacklightLCD (TURN_ON); //***************************************** // SETUP ADC //***************************************** // Abilito AN0-AN1-AN2 come ingressi analogico // VREF sono impostate a massa e VCC ADCON1 = 0b00001101; // Seleziono AN1 come ingresso ADCON0 = 0b00001000; // Imposto i tempi di conversione e giustificazione a destra // TAD : FOSC/4 // TACQ: 16 TAD ADCON2 = 0b10110100; // Abilito l' ADC ADCON0 |= 0b00000001; //***************************************** // SETUP USART //***************************************** // Configura l'USART // 8 bit // 19200 bit/s // 1 bit stop // 0 bit parità OpenUSART( USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 64 ); // Invio la stringa al terminale putrsUSART ("...start writing: "); // Invio la stringa all'LCD WriteStringLCD ("...start writing"); // Attendo di ricevere un dato dal PC while(!DataRdyUSART( )); ClearLCD (); // Ciclo infinito while(1) { // Leggo il dato dal buffer di ricezione data = ReadUSART(); WriteCharLCD (data); // Invio il carattere al terminale WriteUSART (data); // Attendo che il dato venga trasmesso while (BusyUSART()); // Se premo Back Space pulisco lo schermo if(data == 0x08) { ClearLCD (); } // Se premo Esc termino l'applicazione if(data == 0x2B) { putrsUSART ("Vado a leggere la temp"); while (BusyUSART()); WriteIntLCD (lett_temp0(),2) ; dato_da_convertire = (lett_temp0(),2); WriteUSART (WriteIntUSART(dato_da_convertire,2)); while (BusyUSART()); } // Se premo Esc termino l'applicazione if(data == 0x1B) { break; } // Attendo di ricevere un dato dal PC while(!DataRdyUSART( )); } // Chiudo l'USART CloseUSART(); // Ripulisco LCD prima di riscrivere ClearLCD (); // L'USART è stata chiusa WriteStringLCD ("RS232 : Closed"); // Ciclo infinito while (1) { } } int lett_temp0 () { int temp0; // Avvio la conversione Analogico/Digitale ADCON0bits.GO = 1; // Attendo la fine della conversione while(ADCON0bits.GO); // Prelevo il valore della conversione temp0 = (((int) ADRESH) << 8) | ADRESL; // 1 shift per avere la temperatura in gradi // divido cioè per 2 temp0 = temp0 >> 1; return (temp0); } //************************************************************ // WriteIntLCD Implementation //************************************************************ void WriteIntUSART(int value, char number_of_digits){ // The array size is 5 plus end of string \0 unsigned char convertedInt [6]; // Index used to shift to the right the digit char index; // Integer is converted to string itoa (value, (char*) convertedInt); if (number_of_digits >0 ) { convertedInt[number_of_digits] = '\0'; // Shift the digit to the right removing the empty one while (!isdigit(convertedInt[number_of_digits-1])) { for (index = number_of_digits-1; index > 0; index--){ convertedInt[index] = convertedInt[index-1]; convertedInt[index-1] = ' '; } } } }

Ma quando compilo ricevo questo errore: type mismatch in argument 1
riferito alla chiamata della funzione WriteIntUSART

Mi sta dicendo che il tipo di dato del primo argomento non è giusto... ma la variabile "dato_da_convertire" è un int come richiesto...

Non ci sto capendo più nulla...

Sono ancora troppo "ignorante" in materia, perdonatemi ><

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
14 Anni 2 Mesi fa - 14 Anni 2 Mesi fa #4 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Re: Problema RS232 tra PIC e PC
Ciao,

districarsi nel programma che hai scritto richiede già una buona comprensione di quello che sia tra ha le mani, per cui sei già a buon punto.

Il compilatore fa bene a reclamare poiché hai usato impropriamente la funzione WriteIntUSART. Quella usata per LCD ritorna un void poiché scrive direttamente sull'LCD il valore d'interesse.
Nel tuo caso dei ritornare il valore della stringa convertita. In particolare poi non puoi usare writeUSART poiché invii solo un byte e non una stringa.

per il tuo esempio usa solo questo pezzo di codice:
Code:
// The array size is 5 plus end of string \0 unsigned char convertedInt [6]; // Integer is converted to string itoa (value, (char*) convertedInt);

in particolare la variabile convertedInt la devi scrivere subito dopo il main assieme alle altre variabili. Dopo itoa la variabile convertedInt contiene la stringa di tuo interesse.

Saluti,

Mauro
Ultima Modifica 14 Anni 2 Mesi fa da Mauro Laurenti.

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Ricky85
  • Autore della discussione
  • Anziano Utente
  • Anziano Utente
Di più
14 Anni 2 Mesi fa #5 da Ricky85
Risposta da Ricky85 al topic Re: Problema RS232 tra PIC e PC
Grazie ancora Mauro...

Ora sono riuscito ad ottenere qualcosa... ma... sul terminal mi esce una "D" (13 decimale) quando in realtà dovrebbe uscirmi un 23

Questo è il codice attuale...
Code:
#include <p18f4550.h> #include <usart.h> #include <ctype.h> #define LCD_DEFAULT #include <LCD_44780.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF //Prototipo di funzione int lett_temp0 (); void WriteIntUSART(int value, char number_of_digits); void main (void){ //***************************************** // DICHIARAZIONI VARIABILI/COSTANTI //***************************************** // Variabile per salvare il dato di ritorno unsigned char data = 0; int dato_da_convertire; char convertedInt; //***************************************** // SETUP PORT //***************************************** // Imposto PORTA tutti ingressi LATA = 0b00000000; TRISA = 0b11111111; // Imposto PORTB tutti ingressi LATB = 0b00000000; TRISB = 0b11111111; // Imposto PORTC tutti ingressi LATC = 0b00000000; TRISC = 0b11111101; // Imposto PORTD tutte uscite LATD = 0b00000000; TRISD = 0b00000000; // Imposto PORTE tutti ingressi LATE = 0b00000000; TRISE = 0b11111111; //***************************************** // SETUP LCD //***************************************** OpenLCD (20); BacklightLCD (TURN_ON); //***************************************** // SETUP ADC //***************************************** // Abilito AN0-AN1-AN2 come ingressi analogico // VREF sono impostate a massa e VCC ADCON1 = 0b00001101; // Seleziono AN1 come ingresso ADCON0 = 0b00001000; // Imposto i tempi di conversione e giustificazione a destra // TAD : FOSC/4 // TACQ: 16 TAD ADCON2 = 0b10110100; // Abilito l' ADC ADCON0 |= 0b00000001; //***************************************** // SETUP USART //***************************************** // Configura l'USART // 8 bit // 19200 bit/s // 1 bit stop // 0 bit parità OpenUSART( USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 64 ); // Invio la stringa al terminale putrsUSART ("...start writing: "); // Invio la stringa all'LCD WriteStringLCD ("...start writing"); // Attendo di ricevere un dato dal PC while(!DataRdyUSART( )); ClearLCD (); // Ciclo infinito while(1) { // Leggo il dato dal buffer di ricezione data = ReadUSART(); WriteCharLCD (data); // Invio il carattere al terminale WriteUSART (data); // Attendo che il dato venga trasmesso while (BusyUSART()); // Se premo Back Space pulisco lo schermo if(data == 0x08) { ClearLCD (); } // Se premo Esc termino l'applicazione if(data == 0x2B) { putrsUSART ("Vado a leggere la temp"); while (BusyUSART()); WriteIntLCD (lett_temp0(),2) ; dato_da_convertire = (lett_temp0(),2); // Integer is converted to string itoa (dato_da_convertire, (char*) convertedInt); putrsUSART (convertedInt); while (BusyUSART()); } // Se premo Esc termino l'applicazione if(data == 0x1B) { break; } // Attendo di ricevere un dato dal PC while(!DataRdyUSART( )); } // Chiudo l'USART CloseUSART(); // Ripulisco LCD prima di riscrivere ClearLCD (); // L'USART è stata chiusa WriteStringLCD ("RS232 : Closed"); // Ciclo infinito while (1) { } } int lett_temp0 () { int temp0; // Avvio la conversione Analogico/Digitale ADCON0bits.GO = 1; // Attendo la fine della conversione while(ADCON0bits.GO); // Prelevo il valore della conversione temp0 = (((int) ADRESH) << 8) | ADRESL; // 1 shift per avere la temperatura in gradi // divido cioè per 2 temp0 = temp0 >> 1; return (temp0); }

p.s. ho messo la conversione direttamente nel main per non incasinarmi ulteriormente e fare una funzione extra e provare solamente il codice

Non capisco dove sbaglio... sono ancora "nabbo" per quanto riguarda la programmazione...

Si prega Accesso o Crea un account a partecipare alla conversazione.

Moderatori: Mauro LaurentiPinnaStefAMatteo Garia

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.

Forum - Ultimi messaggi