Vai al contenuto
PLC Forum


Utilizzare Direttamente Il Bit Rcif


cloe

Messaggi consigliati

ciao a tutti

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

int16 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


ifachsoftware

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: da ifachsoftware
Link al commento
Condividi su altri siti

ti prego di perdonarmi, ma non ho mai programmato con le interruzioni...

non sn tanto esperta

potresti 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

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

ifachsoftware
#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 seriale

byte 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: da ifachsoftware
Link al commento
Condividi su altri siti

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

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 account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...