cloe Inserito: 30 marzo 2006 Segnala Share Inserito: 30 marzo 2006 ciao a tuttisto interfacciano il mio pic 16F876 con labview per pilotare uno stepper.tra le varie opzioni c'è la rotazione continua del motore, che può essere arrestato tramite labview premendo un pulsante di stop.in pratica, per dare inizio alla rotazione continua labview invia il carattere 'r', e quando premo il pulsante, labview invia al pic via seriale il carattere 's'.il mio prob è far fermare il motore.inizialmente avevo risolto controllando periodicamente con una getch() se mi era arrivata una 's', ma Questo istruzione rallenta incredibilmente il flusso del programma per cui il motore non riesce ad accelerare e si ferma.ho quindi pensato di andare a controllare solo il bit 'RCIF' senza compiere la lettura in modo da non rallentare il flusso di esecuzione, ma forse compio qulache errore nell'accedere al bit perchè il motore non si ferma.qlc mi aiuta?vi allego il programmino (guardate solo la sezione del "case : 'r' ", il resto funziona bene)grazie 1000/* main per stepper_release3.vi*/#include <16f876.h>#use delay(clock=20000000)#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)#BIT RCIF=0x0b.5int16 ang_vel();int16 ang_vel(){ char cmd1, cmd2, cmd3; int16 d1, d2, d3, val; cmd1=getch(); //centinaia d1=(int16)cmd1-48; delay_ms(100); cmd2=getch(); //decine d2=(int16)cmd2-48; delay_ms(100); cmd3=getch(); //unità d3=(int16)cmd3-48; delay_ms(100); val=(d1*100)+(d2*10)+d3; return val;}void main(){ int16 step; int16 i, t, w; int16 angolo, ang_fin, num_step, step_rimanenti; int16 rpm, rpm_fin, duty, giri, num_giri; int q, r, d, riduzione; int16 q1,r1; int stop; char cmd; SET_TRIS_A(0b00001000); SET_TRIS_B(0x00); SET_TRIS_C(0x80); //led alimentazione output_high(PIN_B7); //accensione motore output_high(PIN_A2); //rotazione impostata in senso antiorario di default output_high(PIN_A1); delay_us(150); while(TRUE) { switch(getch()) { case 'c': output_high(PIN_A2); //rotazione in senso antiorario delay_us(150); output_high(PIN_A1); delay_us(150); break; case 'd': //rotazione in senso orario delay_us(150); output_low(PIN_A1); delay_us(150); break; case 'a': angolo=ang_vel(); ang_fin=angolo*2*riduzione; num_step=ang_fin/0.9; if (duty>=210) //velocità imponibile a motore fermo { for(i=0;i<num_step;i++) { output_high(PIN_A0); for (t=0;t<q;t++) delay_us(255); delay_us®; output_low(PIN_A0); for (t=0;t<q;t++) delay_us(255); delay_us®; } } else { d=210; step=0; while( d>duty & step<=num_step) { for (w=0;w<20;w++) { output_high(PIN_A0); delay_us(d); output_low(PIN_A0); delay_us(d); } step=step+20; d=d-1; } if (step<num_step) { step_rimanenti=num_step-step; for (i=0;i<step_rimanenti;i++) { output_high(PIN_A0); delay_us(duty); output_low(PIN_A0); delay_us(duty); } } } putc('y'); break; case 'v': rpm=ang_vel(); rpm_fin=rpm*2*riduzione; duty=3*1000000/(40*rpm_fin); q1=duty/256; q=(int)q1; r=(int)duty-q1*256; putc('w'); break; case 'r': //rotazione continua stop=1; if (duty>=210) //velocità imponibile a motore fermo { while (stop) { if (!RCIF) //buffer di ricezione vuoto { output_high(PIN_A0); for (t=0;t<q;t++) delay_us(255); delay_us®; output_low(PIN_A0); for (t=0;t<q;t++) delay_us(255); delay_us®; } else //buffer di ricezione pieno { cmd=getch(); if (cmd == 's') stop=0; } } } else { d=210; while( d>duty & stop) { if (!RCIF) //buffer di ricezione vuoto { for (w=0;w<20;w++) { output_high(PIN_A0); delay_us(d); output_low(PIN_A0); delay_us(d); } d=d-1; } else //buffer di ricezione pieno { cmd=getch(); if (cmd == 's') stop=0; } } if (d<=duty) { while (stop) { if (!RCIF) { output_high(PIN_A0); delay_us(duty); output_low(PIN_A0); delay_us(duty); } else { cmd=getch(); if (cmd == 's') stop=0; } } } } putc('y'); break; case 'b': riduzione=ang_vel(); putc('n'); break; } }} Link al commento Condividi su altri siti More sharing options...
ifachsoftware Inserita: 30 marzo 2006 Segnala Share Inserita: 30 marzo 2006 (modificato) Io ti consiglio di abilitare un interrupt alla ricezione del carattere.Quando entri nell'interrupt riconosci se start o stop e setti un bit che gestirai poi nel main loop per bloccare o far partire la corsa.La funzione getc() e' bloccante ...Ciao Modificato: 30 marzo 2006 da ifachsoftware Link al commento Condividi su altri siti More sharing options...
cloe Inserita: 30 marzo 2006 Autore Segnala Share Inserita: 30 marzo 2006 ti prego di perdonarmi, ma non ho mai programmato con le interruzioni...non sn tanto espertapotresti aiutarmi in qlche modo? magari hai già un programmino da cui posso prendere spunto per capire come muovermi?ti ringrazio infinitamente Link al commento Condividi su altri siti More sharing options...
cloe Inserita: 30 marzo 2006 Autore Segnala Share Inserita: 30 marzo 2006 lo so che è bloccante, infatti ho dimenticato di dirti che perdevo tempo anche perchè durante la rotazione mandavo una 't' e quando mi arrivava lo stop inviavo la 's'.non sapevo proprio come fare.ma perchè così non funziona?uso male RCIF? Link al commento Condividi su altri siti More sharing options...
ifachsoftware Inserita: 30 marzo 2006 Segnala Share Inserita: 30 marzo 2006 (modificato) #include <16f876.h> #FUSES HS , WDT , NOPUT , PROTECT , NOBROWNOUT , NOLVP#use delay(clock=20000000,restart_wdt) // Clock 20Mhz con Reset del WatchDog nei Timers#use fast_io( A ) // Gestione delle porte predefinita tramite Tris#USE fast_io( B )#USE fast_io( )#priority rda , timer1 // Da la priorita' all'interrupt della serialebyte Run; // 1 = Run / 0 = Stop// Impostazione seriale per Dialogo con PC#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,parity=N,bits=8)#INT_RDA // Timer Ricezione Seriale void serial_isr(){ char c; c = getc(); // Legge il carattere Run = (c == 'r') ? 1 : 0;}main(){ // ............ devi metterci il codice di inizializzazione // Azzera il Buffer di ricezione BuffLen = 0; Run = 0; disable_interrupts(GLOBAL); // Disabilita tutti gli interrupt enable_interrupts(INT_RDA); // Abilita Interrupt Seriale enable_interrupts(GLOBAL); // Riabilita tutti gli interrupt while(1) // ******* MAIN LOOP ******** { restart_wdt(); // Resetta Watchdog if(Run) { } else { } }} Modificato: 30 marzo 2006 da ifachsoftware Link al commento Condividi su altri siti More sharing options...
cloe Inserita: 31 marzo 2006 Autore Segnala Share Inserita: 31 marzo 2006 prima di tutto ti ringrazio per l'aiuto...ieri mi sn cimentata con le interruzioni e ho fatto una routine di interrupt molto simile alla tua...ho riscontrato una cosa strana: se non metto le istruzioni di abilitazione nel case'r' il motore non parte.un'altra cosa:pensavo che bufflen fosse uan parola codice invece è una variabile creata da te (o almeno immagino). come si fa ad azzerare il buffer di ricezione? e cosa succede se non lo faccio?grazie ancora Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora