Vai Indietro   PcTuner Forum > Sezione Hardware > Programmazione PIC
Arcade Registrazione Blogs Regolamento Feedback FAQ Lista Utenti Calendario Segna come Letti

Ultimi 5 blog pubblicati su PcTuner Blog
Data Titolo

Rispondi
 
Strumenti Discussione Modalità Visualizzazione
Vecchio 12-12-2008, 23.11.56   #1
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
PIC 18F4520 - problemi con la seriale

Ciao a tutti, mi sono appena iscritto e premetto che mi sono dato da poco alla programmazione PIC...
Mi sono inceppato in un paio di problemi che non riesco a risolvere nonostante una ricerca in rete approfondita...
Sto programmando un PIC 18F4520 in C (compilatore CCS) con lo scopo di interpretare delle stringhe ricevute via RS232 da un computer e attivare o disabilitare delle uscite in funzione di queste stringhe.

**********

Problema 1:
su un pc con porta COM integrata la comunicazione funziona perfettamente nei due sensi, mentre sul mio portatile con adattatore USB-RS232 (link al modello) riesco solamente a ricevere sul pc ma non è possibile mandare niente al pic. Solo saltuariamente quando premo ripetutamente dei caratteri nell'HyperTerminal il PIC riceve qualcosa ma sbagliato... Le impostazione dell'HyperTerminal sono sicuro che sono giuste, infatti sul pc con COM integrata funziona
Qualcuno sa da cosa può essere causato?

**********

Problema 2:
Presupponiamo che la COM del problema 1 funzioni...
Dal mio programma sul pc invio delle stringhe di 11 caratteri, sul pic controllo che questa stringa è uguale a dei comandi definiti ed attiva in funzione del risultato delle uscite. In principio è un programma banale!!
Con l'HyperTerminal funziona tutto alla grande, mentre se invece faccio partire il mio programma sul pc il PIC mi si blocca dopo aver ricevuto 2 o 3 caratteri
Ora, il programma dal pc invia le stringhe in maniera successiva (8 stringhe da 11 caratteri) e da quello che ho capito il buffer del PIC si "intasa" e tutto si blocca
Sapreste darmi un consiglio?

**********

Codice provvisorio

Codice:
#include <18F452.h>
#include <string.h>
#use delay(clock=4000000)						// prima di #use rs232!!
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7, ERRORS)	// imposta rs232
#include <lcd_new.c>

#define TIMER_RELAOD (65536-2500) 		// set timer to 2.0us * 2500 = 5 ms
#define MAX 11					// lunghezza massima della stringa (senza \0)

#use fast_io(B)
#byte portB = 0xF81

char stringa[MAX+1];				// stringa contenente i caratteri ricevuti
int index = 0;					// indice del prossimo carattere da ricevere
int string_ready = 0;				// a 1 quando la stringa è completa con MAX caratteri
int received = 0;
long counter = 0;

int char_old2 = 0;					// penultimo carattere letto
int char_old1 = 0;					// ultimo carattere letto
int char_old0 = 0;					// carattere attuale

#INT_TIMER0						// la funzione che segue è quella che viene chiamata dall'interrupt
interrupt(){
	set_timer0(TIMER_RELAOD);			// reinizializza il contatore a (65536-2500)
	counter++;
	if(counter == 200){				// 200 x 5ms = 1s
		printf("%d",RS232_ERRORS);
		counter = 0;
	}
}

#INT_RDA
receive(){
	stringa[index] = getc();
	received = 1;
}

main(){
	char stringa_1[12] = {"sez01chiuso"};
	char stringa_2[12] = {"sez01aperto"};
	char stringa_3[12] = {"sez02chiuso"};
	char stringa_4[12] = {"sez02aperto"};
	char stringa_5[12] = {"sez03chiuso"};
	char stringa_6[12] = {"sez03aperto"};
	char stringa_7[12] = {"sez04chiuso"};
	char stringa_8[12] = {"sez04aperto"};
	char stringa_9[12] = {"sc00deviata"};
	char stringa_10[12] = {"sc00diritto"};
	char stringa_11[12] = {"sc01deviata"};
	char stringa_12[12] = {"sc01diritto"};
	int i;

	set_tris_B(0x00);
	portB = 0x00;
	lcd_init();
	setup_timer_0(RTCC_INTERNAL | RTCC_DIV_2);		//velocità clock interrupt: RTCC_DIV_2 -> f = 4MHz/4/2 = 0.5MHz -> T = 2.0us
	set_timer0(TIMER_RELAOD);						// ogni volta che TIMER_RELAOD passa i 65536 viene chiamata la funzione interrupt()
	enable_interrupts(INT_TIMER0);					// attiva l'interrupt Timer0
	enable_interrupts(INT_RDA);						// attiva l'interrupt RDA
	enable_interrupts(GLOBAL);						// abilita tutti gli interrupt, senza di questo non ne va neanche uno.
	printf(lcd_putc,"\fALIVE");
	printf("ALIVE");
	while(1){
		//-----------------------------
		// creazione stringa
		//-----------------------------
		if(received == 1){
			received = 0;
			if(index == 0)
				string_ready = 0;
			stringa[index+1] = '\0';
			printf(lcd_putc,"\f%s",stringa);

			char_old2 = char_old1;
			char_old1 = char_old0;
			char_old0 = stringa[index];

			if(char_old0 == char_old1 && char_old0 == char_old2){		// RESET
				index = 0;
				printf("RESET  //  ");
				printf(lcd_putc,"\fRESET");
				char_old2 = 0;
				char_old1 = 0;
				char_old0 = 0;
			}
			else
				if(index<(MAX-1)){
					index++;
				}
			else{
				index = 0;
				string_ready = 1;
				printf("Stringa = %s  //  ",stringa);
				printf(lcd_putc,"\nCompleted");
			}
		}
		//-----------------------------
		// comparazione stringa
		//-----------------------------
		if(string_ready == 1){
			if(strcmp(stringa, stringa_1)==0)		// sezionamento 1
				output_bit(PIN_B0, 0x01);
			else if(strcmp(stringa, stringa_2)==0)
				output_bit(PIN_B0, 0x00);
			else if(strcmp(stringa, stringa_3)==0)	// sezionamento 2
				output_bit(PIN_B1, 0x01);
			else if(strcmp(stringa, stringa_4)==0)
				output_bit(PIN_B1, 0x00);
			else if(strcmp(stringa, stringa_5)==0)	// sezionamento 3
				output_bit(PIN_B2, 0x01);
			else if(strcmp(stringa, stringa_6)==0)
				output_bit(PIN_B2, 0x00);
			else if(strcmp(stringa, stringa_7)==0)	// sezionamento 4
				output_bit(PIN_B3, 0x01);
			else if(strcmp(stringa, stringa_8)==0)
				output_bit(PIN_B3, 0x00);
			string_ready = 0;
		}
	}
}
Grazie a tutti per ogni tipo di aiuto, e scusate se ci sono errori banali nel mio codice...
Cahapo Non in Linea   Rispondi Citando
Vecchio 13-12-2008, 09.29.45   #2
Registered User
 

Iscritto da: 29-10-2006
Messaggi: 1,613
Feedback: (0)
Per il problema 1 non so che dirti...
Per il secondo, quando invii i caratteri da hyperterminal c'è un'ampia pausa tra uno e l'altro, mentre nella tua applicazione i caratteri vengono iniviati in rapida successione; evidentemente il tuo programma non riesce a star dietro a questa velocità.
Non capisco bene quale sia il meccanismo con cui funziona il tuo programma, ma tanto per cominciare, non vedo perché non incrementi "index" direttamente nella ISR, in modo tale che se arriva un altro carattere questo venga accodato nell'interrupt. Se le stringhe sono tutte di pari lunghezza, ad esempio, potresti effettuare un rapido controllo nella ISR che la stringa sia completamente ricevuta e disabilitare l'interrupt. L'importante è che la ISR abbia una durata tale da garantire la ricezione di caratteri in rapida successione.
Un'altra cosa che personalmente eviterei, è l'uso di stringhe come "chiuso", "aperto", ecc. dal momento che il PIC non capisce l'italiano, questo comporta soltanto uno spreco di memoria e tempo di computazione; a seconda del numero di comandi, potrebbero bastare semplicemente uno o due caratteri.
Volendo potresti usare i meccanismi di sincronizzazione hardware della seriale (CTS/RTS)
__________________
Paolo BB Conte - Utente PIC Dipendente
DEV - L'Elettronica Open Source
Le mie Foto
BitBerzerkir Non in Linea   Rispondi Citando
Vecchio 13-12-2008, 16.18.12   #3
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Grazie dei consigli!
Il programma non fa altro che ricevere dei caratteri e collocarli nella prossima posizione della stringa. Se ci sono 3 caratteri uguali di fila esegue un reset della stringa stessa (mette l'index a 0). Quando la stringa è completa (sono tutte lunghe uguali) le compara con le altre e attiva le rispettive uscite.
Effettivamente le stringhe potrei anche accorciarle, ho messo dei testi in italiano per renderle più maneggiabili durante lo sviluppo del programma su pc.

All'interno della ISR ho messo solo lo stretto indispensabile per velocizzare il tutto, ma mi sa che non serve a niente perchè comunque il numero di cicli da fare (sia nella ISR che nel while(1)) per comparare la stringa sono sempre gli stessi

Al momento uso un quarzo da 4MHz, che mi pare che permetta 208 cicli tra la ricezione di un carattere e l'altro a 9600 baud...

Cosa intendi "meccanismi di sincronizzazione hardware"?

P.S: esistono forse metodi più diretti per collocare i caratteri ricevuti in una stringa??
Cahapo Non in Linea   Rispondi Citando
Vecchio 13-12-2008, 17.25.50   #4
Registered User
 

Iscritto da: 29-10-2006
Messaggi: 1,613
Feedback: (0)
Trovo sbagliatissimo incrementare la variabile index nel main, infatti nel ciclo infinito hai messo un sacco di cose, tra cui la scrittura sul display LCD che richiede molto tempo, perciò, da quando il carattere viene ricevuto a quando la variabile viene incrementata, possono passare diversi millisecondi, e quindi i byte ricevuti non vengono memorizzati nella locazione giusta.
Per sincronizzazione intendevo l'uso dei segnali RTS/CTS della RS232 che permettono di segnalare al PC se il PIC può ricevere e viceversa.
__________________
Paolo BB Conte - Utente PIC Dipendente
DEV - L'Elettronica Open Source
Le mie Foto
BitBerzerkir Non in Linea   Rispondi Citando
Vecchio 14-12-2008, 15.37.35   #5
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Non sto ad analizzare tutto ma di passo alcune dritte per velocizzare le cose.
index, perché definirlo come int quando come char è più che sufficiente. Questo vale anche per altre variabili in cui non sia strettamente necessario l'uso dell'intero (es. received).
MAX, anche se ti occorrono solo 11 posizioni è meglio dimensionarlo come un quadrato di 2 per facilitare il controllo di sconfinamento.
Codice:
Io faccio così per non scordarmi di questo.
#define MAX (2*2*2*2)  // lunghezza massima della stringa (senza \0)
Io preferirei l'aggiornamento di index e il controllo subito nella ricezione.
Codice:
    ++index;
    index &= MAX-1;  // Per non sconfinare.
Vista la criticità in velocità del progetto userei 2 buffer in ingresso così mentre uno riceve i dati l'altro viene analizzato.
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 14-12-2008, 22.05.25   #6
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Grazie Camillo, ma non ho mica capito perché usare una potenza di 2

Come si fa ad usare due buffer? L'interrupt #INT_RDA rimane sempre uno solo? Ho cercato un po' in giro ma non ho trovato niente (non so neanche con che parole chiave cercare...). Scusate, ma sono veramente alle prime armi con i microprocessori

P.S: int e char non sono tutti e due di 8 bit?
Cahapo Non in Linea   Rispondi Citando
Vecchio 15-12-2008, 09.36.53   #7
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Quote:
Originariamente inviato da Cahapo Visualizza Messaggio
Grazie Camillo, ma non ho mica capito perché usare una potenza di 2

Come si fa ad usare due buffer? L'interrupt #INT_RDA rimane sempre uno solo? Ho cercato un po' in giro ma non ho trovato niente (non so neanche con che parole chiave cercare...). Scusate, ma sono veramente alle prime armi con i microprocessori

P.S: int e char non sono tutti e due di 8 bit?
Se non usassi una potenza di 2 non potrei fare: index &= MAX-1

Un uso potrebbe essere: finito di ricevere il pacchetto nel primo buffer lo copio sul secondo così lascio il primo libero per ricevere un nuovo pacchetto mentre analizzo i dati nel secondo.
Un'altro uso è quello alternativo (si possono usare anche più buffer) metto i dati nel primo buffer e quando ricevo il terminatore carico la ricezione sul secondo e vado ad analizzare il primo.

L'int è generalmente da 16 bit anche se dipende dal compilatore. Sarebbe meglio utilizzare "unsigned int" a meno che non si vada negativi. Occorre anche assicurarsi che il compilatore utilizzi i char non segnati.
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 12.35.24   #8
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Nel mio compilatore "int" è di 8bit (ccs), "char" non lo so, dovrei controllare...
Quello che mi proponevi di fare con i due buffer è chiaro, quello di cui non ho la minima idea è come creare e gestire un buffer nel pic O magari si tratta semplicemente di un array? In C su un computer so come creare ad esempio un FIFO, ma sono almeno una 20ina di righe di codice, e se il mio scopo è quello di velocizzare il tutto non mi sembra che abbia molto senso...
Cahapo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 15.50.31   #9
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Quote:
Originariamente inviato da Cahapo Visualizza Messaggio
Nel mio compilatore "int" è di 8bit (ccs), "char" non lo so, dovrei controllare...
Quello che mi proponevi di fare con i due buffer è chiaro, quello di cui non ho la minima idea è come creare e gestire un buffer nel pic O magari si tratta semplicemente di un array? In C su un computer so come creare ad esempio un FIFO, ma sono almeno una 20ina di righe di codice, e se il mio scopo è quello di velocizzare il tutto non mi sembra che abbia molto senso...
Sei sicuro che l'int sia di 8 bit, non credo, sarebbe anomalo, ed al di fuori dei canoni del C.
Per buffer intendo array monodimensionale visto che deve contenere dei caratteri o dei byte.
Il FIFO è una buona idea a patto che sia abbastanza profondo da non mangiarsi la coda. Non penso che ci vogliano una 20ina di righe ma penso che mezza dozzina bastino. In C il concetto di riga è piuttosto labile, tutto un programma per il compilatore è una sola riga.
La velocità di esecuzione è legata anche all'efficienza di traduzione del compilatore per cui non sempre quello che potrebbe parere corto è anche più veloce. Per capirne qualcosa si deve analizzare il listato generato dal compilatore.
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 16.13.32   #10
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Quote:
Originariamente inviato da Camillo Visualizza Messaggio
Sei sicuro che l'int sia di 8 bit, non credo, sarebbe anomalo, ed al di fuori dei canoni del C.
Sicuro no, nel senso che non l'ho letto da nessuna parte... l'ho dedotto dal fatto che se una variabile supera 128 va in overflow... In effetti ho sempre usato il tipo long per i casi critici.
Oggi ho introdotto un intervallo di 10ms tra l'invio di un byte e l'altro nel mio programma nel pc per lasciare il tempo al pic di elaborare i dati in arrivo, ma va ancora tutto in tilt
Cahapo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 16.46.20   #11
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Quote:
Originariamente inviato da Cahapo Visualizza Messaggio
Sicuro no, nel senso che non l'ho letto da nessuna parte... l'ho dedotto dal fatto che se una variabile supera 128 va in overflow... In effetti ho sempre usato il tipo long per i casi critici.
Oggi ho introdotto un intervallo di 10ms tra l'invio di un byte e l'altro nel mio programma nel pc per lasciare il tempo al pic di elaborare i dati in arrivo, ma va ancora tutto in tilt
Ti assicuro che nella mia vita di programmi ne ho scritti tanti e con i PIC, dove uso l'assembly e il C18, ci sono delle cose che non ho mai fatto:
Non ho mai usato il tipo 'long' ma solo char e int segnato e non segnato.
Non ho mai utilizzato, finora, frequenze oltre i 4MHz.
Non ho mai utilizzato le routine di Delay() per tempi che ritengo troppo lunghi.

Come fai a dire che una variabile va in overflow?

Se 10ms non ti bastano (a 4MHz sono 10000 istruzioni) hai un problema profondo o nella tua logica o nel tuo compilatore.
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 17.23.53   #12
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Quote:
Originariamente inviato da Camillo Visualizza Messaggio
Come fai a dire che una variabile va in overflow?
Se la aumento sempre di uno a 128 diventa -127... (signed int)

Quote:
Originariamente inviato da Camillo Visualizza Messaggio
Se 10ms non ti bastano (a 4MHz sono 10000 istruzioni) hai un problema profondo o nella tua logica o nel tuo compilatore.
Evviva....
Cahapo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 18.07.28   #13
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Quote:
Originariamente inviato da Cahapo Visualizza Messaggio
Se la aumento sempre di uno a 128 diventa -127... (signed int)
Si ma dove (con che cosa) lo leggi che è -127.
Non penso di dar la colpa all'implementatore del compilatore, se è così sarebbe troppo!
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 18.17.20   #14
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
lo leggo con un printf sull'hyperterminal. Sono sicuro che pure il mio docente me l'aveva spiegato così. Non so se definirla "colpa del compilatore", se lo so faccio attenzione...

Un altro esempio è nel codice che ho postato nel primo post:
Codice:
#INT_TIMER0						// la funzione che segue è quella che viene chiamata dall'interrupt
interrupt(){
	set_timer0(TIMER_RELAOD);			// reinizializza il contatore a (65536-2500)
	counter++;
	if(counter == 200){				// 200 x 5ms = 1s
		printf("%d",RS232_ERRORS);
		counter = 0;
	}
}
Se "counter" lo definisco come int e non come long non entra mai nell'if...
Cahapo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 19.05.56   #15
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Quote:
Originariamente inviato da Cahapo Visualizza Messaggio
lo leggo con un printf sull'hyperterminal. Sono sicuro che pure il mio docente me l'aveva spiegato così. Non so se definirla "colpa del compilatore", se lo so faccio attenzione...

Un altro esempio è nel codice che ho postato nel primo post:
Codice:
#INT_TIMER0						// la funzione che segue è quella che viene chiamata dall'interrupt
interrupt(){
	set_timer0(TIMER_RELAOD);			// reinizializza il contatore a (65536-2500)
	counter++;
	if(counter == 200){				// 200 x 5ms = 1s
		printf("%d",RS232_ERRORS);
		counter = 0;
	}
}
Se "counter" lo definisco come int e non come long non entra mai nell'if...
Qualcosa ci sfugge!
Rimango convinto che l'int è da 16 bit.
Quel printf all'interno dell'interrupt ci sta proprio male. Negli interrupt bisogna starci il meno possibile.
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 19.54.59   #16
Registered User
 

Iscritto da: 29-10-2006
Messaggi: 1,613
Feedback: (0)
Il manuale del compilatore dice che char è unsigned 8 bit, int è 8bit e long 16bit
__________________
Paolo BB Conte - Utente PIC Dipendente
DEV - L'Elettronica Open Source
Le mie Foto
BitBerzerkir Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 19.56.49   #17
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Grazie BitBerzerkir per le delucidazioni
Cahapo Non in Linea   Rispondi Citando
Vecchio 17-12-2008, 20.17.22   #18
Registered User
 
L'avatar di  Camillo
 

Iscritto da: 31-01-2006
Locazione: Genova
Messaggi: 1,472
Feedback: (0)
Quote:
Originariamente inviato da BitBerzerkir Visualizza Messaggio
Il manuale del compilatore dice che char è unsigned 8 bit, int è 8bit e long 16bit
Penso che abbiano pensato anche ad un superlong e ad un iperlong per non parlare poi di float e short.

Con queste premesse non oso pensare all'ottimizzazione del codice.
Non dico ANSI ma almeno seguire K&R.
__________________
Camillo

Internet ti fa vedere tutto ma non ti fa toccare niente. (Camillo Ferrari)
Camillo Non in Linea   Rispondi Citando
Vecchio 18-12-2008, 08.17.15   #19
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Stamattina ho guardato il manuale... effettivamente è così!


Tornando al mio problema... ieri sera miracolosamente ha funzionato! Il problema è che non so come mai adesso funziona e prima no, il programma è praticamente ancora quello del primo post

Mi rimane solo il problema del RS232-converter, che proprio non c'è verso di risolvere...
Cahapo Non in Linea   Rispondi Citando
Vecchio 19-12-2008, 14.39.50   #20
Registered User
 

Iscritto da: 12-12-2008
Messaggi: 10
Feedback: (0)
Che neeervi

Adesso il pic non si blocca più, ma se dal computer invio 2 stringhe di fila, la seconda non viene letta correttamente, nonostante tra una stringa e l'eltro invio una stringa "xxx" che azzera la stringa ricevuta nel pic (per evitare che un errore si trascini all'infinito). Il motivo è che la variabile "string_ready" rimane a 1 fino a quando la stringa precedente non viene elaborata, e durante questo tempo tutto quello che arriva va perso...

Nella funzione in C++ sul computer che invia i segnali sulla COM ho modificato i parametri "sDcb.fDtrControl" e "sDcb.fRtsControl" impostandoli su "disabilitato", mentre il parametro "sTo.WriteTotalTimeoutMultiplier= 12000/Baud+1;" ho provato ad aumentarlo fino a "sTo.WriteTotalTimeoutMultiplier= 12000/Baud+100;", ma non cambia niente
Adesso sto pensando di inserire una funzione "wait()" nel mio programma in C, ma non mi sembra una soluzione molto pulita... Avete altre proposte o suggerimenti?

Adesso sto provando ad aumentare il quarzo da 4 a 20MHz...

Questo è il mio codice, migliorato rispetto all'originale:
Codice:
#include <18F452.h>
#include <string.h>
#use delay(clock=4000000)                                                              // prima di #use rs232!!
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7, ERRORS)  // imposta rs232
#include <lcd_new_20mhz.c>

#define MAX 7                                           // lunghezza massima della stringa (senza \0)

#use fast_io(B)
#byte portB = 0xF81

char string[MAX+1];                                     // stringa contenente i caratteri ricevuti
int index = 0;                                          // indice del prossimo carattere da ricevere
int string_ready = 0;                           // a 1 quando la stringa è completa con MAX caratteri

int char_old2 = 1;                                      // penultimo carattere letto
int char_old1 = 2;                                      // ultimo carattere letto
int char_old0 = 3;                                      // carattere attuale

#INT_RDA
receive(){
        string[index] = getc();
        char_old2 = char_old1;
        char_old1 = char_old0;
        char_old0 = string[index];
        if(index<(MAX-1) && string_ready == 0){
                index++;
        }
        else{
                string[index+1] = '\0';
                index = 0;
                string_ready = 1;
        }
}

main(){
        char string_received[8];
        char string_1[8] = {"sc00dir"};
        char string_2[8] = {"sc00dev"};
        char string_3[8] = {"sc01dir"};
        char string_4[8] = {"sc01dev"};
        int i;

        set_tris_B(0x00);
        portB = 0x00;
       
        lcd_init();
        enable_interrupts(INT_RDA);                                             // attiva l'interrupt RDA
        enable_interrupts(GLOBAL);                                              // abilita tutti gli interrupt, senza di questo non ne va neanche uno.
        printf(lcd_putc,"\fREADY...");
        printf("READY...");
        while(1){
                //--------------------------------------------------
                // reset con 3 caratteri uguali di seguito
                //--------------------------------------------------
                if(char_old0 == char_old1 && char_old0 == char_old2){
                        index = 0;
                        printf("READY...");
                        printf(lcd_putc,"\nREADY...");
                        char_old2 = 1;
                        char_old1 = 2;
                        char_old0 = 3;
                        string_ready = 0;
                }
                //--------------------------------------------------
                // comparazione stringa
                //--------------------------------------------------
                if(string_ready == 1){
                        strcpy(string_received,string);
                        printf(lcd_putc,"\f%s",string_received);
                        string_ready = 0;
                        if(strcmp(string_received, string_1)==0){               // scambio 00 diritto
                                output_bit(PIN_B0, 0x01);
                                output_bit(PIN_B1, 0x00);
                        }
                        else if(strcmp(string_received, string_2)==0){  // scambio 00 deviata
                                output_bit(PIN_B0, 0x00);
                                output_bit(PIN_B1, 0x01);
                        }
                        else if(strcmp(string_received, string_3)==0){  // scambio 01 diritto
                                output_bit(PIN_B2, 0x01);
                                output_bit(PIN_B3, 0x00);
                        }
                        else if(strcmp(string_received, string_4)==0){  // scambio 01 deviata
                                output_bit(PIN_B2, 0x00);
                                output_bit(PIN_B3, 0x01);
                        }
                }
        }
}
e queste sono le mie funzioni in C per il programma sul computer...

Codice:
//*****************************************************************************
//*
//*		ComOpen
//*
//*****************************************************************************
//	Öffnet eine serielle Verbindung
//	Nr			: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Baud		: Ist die Bautrate
//	Parity		: 0 = kein Parity Bit
//				  1 = gerade
//				  2 = ungerade
//				  3	= immer 0
//				  4 = immer 1
//	Stopbits	: 0 = Ein Stopbit
//				  1 = Ein/einhalb Stopbits
//				  2 = Zwei Stopbits
//	Bits		: 0 = 7 Datenbits
//				  1 = 8 Datenbits
//				  7 = 7 Datenbits
//				  8 = 8 Datenbits
//	Ergibt 1 wenn eine Schnittstelle geöffnet wurde

int ComOpen(unsigned Nr,int Baud,int Parity,int Stopbits,int Databits){
	static const int	iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
	static const int	iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
	char				cName[]="\\\\.\\COM1";
	HANDLE				hFile;
	COMMTIMEOUTS		sTo;
	DCB					sDcb;



	if(Nr>=MAX_COM_PORTS)return 0;
	if(bIsOpen[Nr])return 0;


	cName[7]='1'+Nr;

	   hFile= CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	if(hFile==INVALID_HANDLE_VALUE)
		{
		hFile=0;
		return 0;
		}

	if(Databits==7)Databits=0;


	memset(&sDcb,0,sizeof(sDcb));
	sDcb.DCBlength=sizeof(sDcb);
	sDcb.BaudRate     	= Baud;
	sDcb.fParity      	= (Parity!=0)? TRUE:FALSE;
	sDcb.fBinary      	= TRUE;
	sDcb.Parity       	= iPMode[Parity];
	sDcb.StopBits     	= iSMode[Stopbits&3];
	sDcb.fOutxCtsFlow 	= FALSE;
	sDcb.fOutxDsrFlow 	= FALSE;
	sDcb.fDtrControl	= DTR_CONTROL_ENABLE; //DTR_CONTROL_DISABLE ????????? (originale DTR_CONTROL_ENABLE)
	sDcb.fRtsControl	= DTR_CONTROL_ENABLE; //DTR_CONTROL_DISABLE ????????? (originale DTR_CONTROL_ENABLE)
	sDcb.fDsrSensitivity= FALSE;
	sDcb.fAbortOnError	= FALSE;
	sDcb.ByteSize     	= (Databits)? 8:7;

	if(!SetCommState(hFile,&sDcb))
		{
		CloseHandle(hFile);
		return 0;
		}


	sTo.ReadIntervalTimeout		   = MAXDWORD; 		// 0 ms Read-Timeout
	sTo.ReadTotalTimeoutMultiplier = 0;
	sTo.ReadTotalTimeoutConstant   = 0;
	//sTo.WriteTotalTimeoutMultiplier= 12000/Baud+1;	// ? ms Write timeout per byte
	sTo.WriteTotalTimeoutMultiplier= 12000/Baud+10;		// 10.25 ms Write timeout per byte
	sTo.WriteTotalTimeoutConstant  = sTo.WriteTotalTimeoutMultiplier+1;
	if(!SetCommTimeouts((HANDLE)hFile,&sTo))
		{
		CloseHandle(hFile);
		return 0;
		}


	hComFile[Nr]=hFile;
	bIsOpen [Nr]=TRUE;


return 1;
}
Codice:
//*****************************************************************************
//*
//*		ComWrite
//*
//*****************************************************************************
//	Mehrere Zeichen schreiben
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Buffer	: Buffer in dem die Zeichen gespeichert werden
//	Count	: Anzahl der zu sendenden Zeichen
//	Ergibt die Anzahl der gesendeten Zeichen

int	ComWrite(unsigned Nr,void *Buffer,int Count)
{
DWORD			dwCount;


	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	WriteFile(hComFile[Nr],Buffer,Count,&dwCount,0);

return dwCount;
}
Altra domandina: quando accendo il mio pic (o alimentandolo o premento "release from reset" in MPLAB, le mie uscite della porta B si accendono in maniera più o meno aleatoria, così a occhio riprendendo lo stato che avevano prima dello spegnimento. La cosa che non capisco è che ciò accade anche se all'inizio del main() ho "set_tris_B(0x00); portB = 0x00;". La funzione main() non viene eseguita ogni volta all'avvio??

Ultima Modifica di Cahapo : 19-12-2008 14.47.27.
Cahapo Non in Linea   Rispondi Citando
Rispondi Per le vostre immagini su questo forum potete usare PcTunerUp!
Iscriviti gratuitamente alla nostra newsletter.


Utenti attualmente attivi che stanno leggendo questa discussione: 1 (0 utenti e 1 visitatori)
 
Strumenti Discussione
Modalità Visualizzazione

Regole di scrittura
non Puoi inserire messaggi
non Puoi rispondere ai messaggi
non Puoi inviare allegati
non Puoi modificare i tuoi messaggi

codice vB è Attivo
Smilies è Attivo
[IMG] il codice è Attivo
Il codice HTML è Disattivato
Trackbacks are Disattivato
Pingbacks are Disattivato
Refbacks are Disattivato
Vai al Forum


Tutti gli Orari sono GMT +2. Attualmente sono le 22.04.03.


Powered by vBulletin Versione 3.6.12
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0
Copyright © 2010 - Master New Media S.r.l. a socio unico - P.I. 02947530784. Tutti i diritti di proprietà letteraria e artistica sono riservati- Privacy
www.pctuner.net è testata telematica registrata presso il Tribunale di Torino, n. 39 del 07.05.2008, Editore Master New Media S.r.l.