Vai al contenuto
PLC Forum


Interrupt E Seriale


cloe

Messaggi consigliati

ciao a tutti, ho un problema con la seriale gestita tramite interruzioni che mi sta mandando al manicomio...

premetto che interfaccio il pic con labview per la gestione di un motore passo-passo.

il codice è Questo:

#include <16f876.h>

#FUSES HS, WDT

//clock 20Mhz con reset del watchdog nei timers

#use delay(clock=20000000, restart_wdt)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)

#priority rda, timer1 //dà la priorità all'interrupt della seriale

BYTE stop;

#int_rda

void serial_isr()

{ char cmd;

int i;

for (i=0;i<5;i++)

{ output_high(PIN_B7);

delay_ms(200);

output_low(PIN_B7);

delay_ms(200);

}

cmd=getch();

if (cmd == 's')

stop=0;

}

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;

SET_TRIS_A(0b00001000);

SET_TRIS_B(0x00);

SET_TRIS_C(0x80);

stop = 1;

//azzera il buffer di ricezione

// BuffLen=0;

//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)

{ //restart_wdt(); //resetta il watchdog

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 '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

//disable_interrupts(global); //disabilita tutti gli interrupt

enable_interrupts(int_rda); //abilita gli interrupt della seriale

enable_interrupts(global); //riabilita tutti gli interrupt

if (duty>=210) //velocità imponibile a motore fermo

{

while (stop)

{ 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;

while( d>duty & stop)

{ //buffer di ricezione vuoto

for (w=0;w<50;w++)

{ output_high(PIN_A0);

delay_us(d);

output_low(PIN_A0);

delay_us(d);

}

d=d-1;

}

if (d<=duty)

{ while (stop)

{ output_high(PIN_A0);

delay_us(duty);

output_low(PIN_A0);

delay_us(duty);

}

}

}

putc('y');

break;

case 'b':

riduzione=ang_vel();

putc('n');

break;

}

}

}

la prima domanda è Questo: ho notato che se non metto le istruzioni di abilitazione all'interno del "case'r' " il motore non si muove (il motore si muove con la sequenza di impulsi sul pinA0).

seconda domanda: mettendo le istruzioni nel case 'r' il motore ruota la prima volta, ma quando vado a riavviarlo esegue tutte le istruzioni ma non manda tensione su A0 quindi il motore non si muove. la domanda sorge spontanea: non è che le interruzioni in qulache modo interferiscono col PIN A0?

per favore aiutatemi perchè non ce la faccio +

grazie

Link al commento
Condividi su altri siti


ifachsoftware

Un interrupt va processato ed abbandonato il prima possibile.

Il metterci un ritardo di 200 ms per di piu' bloccante nella funzione che processa un interrupt e' una cosa senza capo ne' coda.

Nell'interrupt si acquisisce su di un bit il comando di start o stop ; poi nel main loop lo si puo' andare a processare.

Ciao :)

Link al commento
Condividi su altri siti

effettivamente mettere il for nella routine di servizio dell'interrupt non è una cosa proprio carina, ma l'avevo aggiunta per motivi di debug. comunque anche togliendo il for il motore non riparte.

putroppo il controllo sul carattere ricevuto non posso metterlo fuori dalla routine di interrupt altrimenti non riesco a dare la coppia di spunto necessaria al motore per accelerare.

hai altri suggerimenti?

grazie ancora

Link al commento
Condividi su altri siti

ifachsoftware

La lettura del carattere VA FATTA nell'interrupt (se no a cosa serve l'interrupt ?).

Quando viene ricevuto l'interrupt la funzione getch() non aspetta nulla perche' il carattere e' gia' presente (e' il motivo per cui ti viene alzato l'interrupt) e a quel punto puoi o mettere il valore in un buffer globale che processi nel main loop quando hai ricevuto tutti i dati della tua scritta oppure decodificare la stringa direttamente nell'interrupt (a patto di non metterci troppo tempo e per capire quanto ci mette puoi usare il debugger dell'MPLAB con un paio di break point all'entrata ed all'uscita dell'interrupt e misurare il tempo che ci mette che naturalmente dovra' essere inferiore al tempo di arrivo tra un carattere e l'altro altrimenti rischi di perdere dei dati della seriale).

Per quello che non ti funziona sarebbe una bella cosa spiegare esattamente che cosa non va e magari ti si puo' dare una mano ...

Ciao :)

Link al commento
Condividi su altri siti

ti spiego...in base al carttere che il pic riceve via seriale si entra in un ramo del case. quindi prima gli faccio settare il verso di rotazione, poi la velocità e il rapporto di riduzione ed infine, quando mi arriva il carattere 'r' faccio partire il motore mandandogli degli mpulsi sul pin A0. a Questo punto il motore si mette in rotazione fino a quando non gli invio il carattere 's' che determina stop=0 quindi il motore si ferma.

il problema è Questo: la prima volta che metto il moore in rotazione non ci sn problemi. io però vorrei poter far rimettere il motore in movimento magari con un'altra velocità di rotazione (infatti c'è il while (true)) ma il pic esegue il main correttamente senza però mandare tensione su A0 quindi non riesco ad avere successive rotazioni. so per certo che il pic esegue il codice perchè invia a labview correttamente tutti i caratteri di sincronizzazione.

spero di essere stata il + chiaro possibile, così almeno potete aiutarmi

grazie 1000 per l'aiuto

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