Vai al contenuto
PLC Forum


ripetere il ciclo una sola volta pic 16f629


vergalabs

Messaggi consigliati

ciao ragazzi

devo fare una cosa banalissima utilizzando un pic 16f629 e cioè attivare in sequenza 2 uscite dopo un certo tempo per un certo tempo all'accensione del pic ( tempo>out 1 on>tempo>out 1 off>tempo>out 2 on>tempo>out 2 off ).

fino ad ora per fare quei 4 progetti dove ho utilizzato i pic ho usato parsic ma ora visto che parsic non supporta quel tipo di pic sto provando a utilizzare mplab-x-ide.

ho rispolverato le mie poche conoscenze di C (troppo arrugginite) e ho partorito questo codice 

 

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <time.h>
#define _XTAL_FREQ 4000000
/*
 * 
 */
#define _XTAL_FREQ 4000000
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))


#pragma config FOSC = INTRCIO 
#pragma config WDTE = OFF      
#pragma config PWRTE = ON     

#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF        
#pragma config CPD = OFF        

void main() {

    TRISIO = 0;
    GPIO = 0;
    int i = 0;
    while (i < 5) {
        __delay_ms(2500);
        GP0 = 1;
        __delay_ms(500);
        GP0 = 0;
        __delay_ms(500);
        GP1 = 1;
        __delay_ms(500);
        GP1 = 0;
        i = i + 1;

    }
}

 

il ciclo funziona ma non si interrompe mai sembra che la variabile "i" che dovrebbe inerrompere il "while" una volta arrivata a 5 o non si incrementa mai o viene azzerata.

in questo esempio il ciclo dovrebbe ripetersi 5 volte e poi fermarsi solo per prova, a me interesserebbe ripeterlo una volta sola all'accensione del circuito.

 

grazie per l'aiuto

Link al commento
Condividi su altri siti


Invece di "i = i +1" scrivi "i++;" che lasintassi corretta in "C"

Per fare quello che desideri scrivi qualche cosa del genere

int flg_1ciclo = 0;

........
 if flg_1ciclo > 0 
  ......
 else
  qui scrivi quello che vuoi eseguire la prima volta
 flg_1ciclo = 1;

 

Questo è un modo ma ne esistono molti altri

Link al commento
Condividi su altri siti

grazie livio

con i++ ho già provato ma non funziona lo stesso, il ciclo non si interrompe ma continua all'infinito. 

proverò come mi hai suggerito.

l'istruzione void main è scritta giusta? viene proposta direttamente dal compilatore appena si apre il programma

Link al commento
Condividi su altri siti

Premetto che non conosco i PIC,e non li ho mai usati, ma come regola generica su piattaforme MCU credo il programma non dovrebbe mai raggiungere la fine del main(), o perlomeno non mi è chiaro cosa accada in quel caso. l'MCU si blocca? Riprende dall'inizio? Se è vera la seconda è quello che accade nel tuo caso. Prova a racchiudere il tuo while(i<5) dentro un altro loop infinito (tipo while(1) o for(;;) ) e vedi cosa accade. Peraltro i (pochi) programmi per PIC che mi è capitato di vedere funzionano tutti così.

 

Ciao, Ale.

Link al commento
Condividi su altri siti

1 ora fa, ilguargua ha scritto:

ma come regola generica su piattaforme MCU credo il programma non dovrebbe mai raggiungere la fine del main(),

 

No Ale, non è corretta la tua ipotesi ,c'è una cosa che mi è sfuggita alla prima lettura: lui scrive "int i = 0;" subito prima del "while"; questo fatto comporta che ad ogni ciclo di main la variabile si riazzera e ripete il ciclo di while.

Basta dichiarare la variabile prima dell'inizioo del loop di main ed il ciclo di while sarà eseguito una sola volta. In pratica la variabile "i" va trattata come se fosse piubblica.

Ci sono altri metodi ma per non sconvolgere troppo quello che ha fatto vergablas, questa è la soluzione più pratica.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

grazie ancora livio, adesso non posso fare delle prove ma tra i tanti tentativi mi sembra di aver già messo "int i = 0;" prima del while ma il ciclo non si interrompeva lo stesso, se invece mettevo "int i = 6;" ,ad esempio, il ciclo non veniva eseguito.

è da qui che mi sono perso perchè ,se con "int i = 6;", il ciclo non viene eseguito vuol dire che la condizione while "funziona" ed è per questo che ho scritto che mi sembrava fosse la variabile "i" a non essere incrementata o a essere azzerata ad ogni ciclo.

ho provato a scrivere per la somma i++, i = (i+1), i = i+1 ma senza successo.

non può essere un problema di configurazione dei "fuses" della mcu ?

nella vita mi occupo di programmazione plc ma purtroppo in scl non ho scritto dei gran programmi più che altro awl o kop, sicuramente mi sfugge qualcosa magari legato proprio ai pic

Link al commento
Condividi su altri siti

Sotto al primo while ne metti un altro

While (I=>5){

I=I;

}

Così va in loop all'infinito perché nel primo non entrerà e resterà sempre a 5

 

.ovviamente con le varianti già spiegate sopra per la dichiarazione public delle variabili esterne al main

Modificato: da drn5
Link al commento
Condividi su altri siti

11 ore fa, vergalabs ha scritto:

ma tra i tanti tentativi mi sembra di aver già messo "int i = 0;" prima del while

 

Noo!

Leggi bene quello che ho scritto!

L'azzeramento deve essere fatto nella dichiarazione e la dichiarazione deve essere esterna al loop di main, altrimenti ogni volta che ripete il ciclo di main si ripete il ciclo di while

 

11 ore fa, vergalabs ha scritto:

non può essere un problema di configurazione dei "fuses" della mcu ?

 

ma no!

E solo questione di logica! Nemmeno di sintassi del "C" o altro.

Purtroppo i PLC son stati progettati per per permetterne la programmazione anche a chi è completamente digiuno dei rudimenti elementari di programmazione.

Gli yankees sempre pronti a creare acronimi chiamano questi casi "GIGO" ==> Garbage In, Garbage Out; ovvero se nella macchina entrano rifiuti dalla macchina escono rifiuti. La macchina è stupida, fa quello che il programmatore gli dice.

Anche se tu avessi scritto in AWL o in KOP farebbe la stessa cosa.

Pensa di aver scritto in OB1, usando AWL la medesima sequenza. Inizia l'OB e azzeri un merker, poi testi il merker e, se è zero, chiami un FB che scrive le condizioni iniziali del programma e al termine mette a 1 quel merker. Il programma eseguirà ilmciclo di OB1 sino al termine, per poi ripartire dall'inizio, quindi ripeterai lo FB di inizializzazione ad ogni ciclo di OB1.

Però nella realtà tu andrai a chiamare lo FB di inizializzazione testando lo SM che sta alto solo al primo ciclo, perchè il firmware del sistema operativo del PLC, che tu non vedi e non conosci, pensa a tutto. Quindi per te è impossiible che il ciclo possa ripetersi dopo il prio ciclo.

Qui non hai un SO che esegue tutte queste operazioni ma le devi predisporre da te.

Che tu scriva in assembler o in "C" le cose non cambiano, la prima fase di progettazione è sempre la progettazione della logica con cui deve evolvere il programma.

Bisogba sempre mettere su carta, inizialmente, o il digramma di flusso o, meglio se si usano linguaggi strutturati, le specifiche dettagliate.

Se tu scrivi il diagramma di flusso, in modo corretto, ti accrgi subito che quel ciclio di while si ripete all'infinito.

 

Link al commento
Condividi su altri siti

THIS PIC MAKE ME CRAZY !!!

livio è chiarissimo quello che hai detto e infatti mi era già venuto quel dubbio e avevo spostato int=0 prima dell'inizio del main subito dopo la dichiarazione dei fuses (nel messaggio precedente non lo avevo specificato) ma non ne vuole sapere di funzionare ho provato come mi hai suggerito a utilizzare if/else ma anche così il ciclo si ripete all'infinito.

Ora il mio dubbio è non è che la formattazione o l'uso di parentesi, punteggiature, e spazi vari l'ho scritta sbagliata ? 

Prima di chiedere qui ho cercato esempi , "corsi" online e guardato programmi scritti da me tempo fa sia in scl che in c ma proprio non riesco a capire dove sbaglio.

DRn5 non ho ben capito quello che vuoi dire chi e quando la variabile "i" viene messa a zero.

Qui sotto vi ho messo due screen di quello che ho scritto in base ai vostri suggerimenti ma come già anticipato anche così il ciclo si ripete all'infinito

image.thumb.png.9bb100659f0bc38781adbf654b4f01dc.pngimage.png.4166ed847b03d9107742e14bea16186d.png

Link al commento
Condividi su altri siti

Mah, io rimango della mia opinione, non dovresti uscire dal main(). Prova a mettere un while(1){}; subito dopo il tuo ciclo while, prima del termine del main(), vedrai funziona.

 

Ciao, Ale.

 

EDIT : Qui una spiegazione dettagliata di cosa accade quando si esce dal main(), con un esempio proprio sui PIC.

Modificato: da ilguargua
Link al commento
Condividi su altri siti

19 minuti fa, ilguargua ha scritto:

io rimango della mia opinione, non dovresti uscire dal main().

 

Ma non esce dal main, non può uscire non c'è alcun interrupt o chiamata a funzioni esterne.

 

Se mette il "while (1) {} dopo il ciclo di while rimarrà bloccato li sino a quando non interviene un eventualeinterrupt a cavarlo fuori!

Semmai, se proprio si vuole che cicli sempre nel main, cosa pleonastica, è meglio fare

void main()

{
  int i = 0;
  while (1)
   {
     while (i < 5)
       {
          ....... 
         i++;
       }
  }
}

 Questa è la sintassi corretta, anche se pleonastica, affinchè il ciclo di while più interno venga eseguito coiìn i da 0 a 4; con i = 5 il programma ciclerà a tempo indefinito del primo loop di while.

 

Link al commento
Condividi su altri siti

19 minuti fa, Livio Orsini ha scritto:

Ma non esce dal main

Perchè no? quando il suo while finisce, termina anche il main(), e li esce. Cosa accade a quel punto dipende dalla piattaforma, sui PIC a quanto pare viene riavviata l'MCU (n.b. non viene richiamato il main(), ma viene eseguito anche tutto quello che c'è prima), gli ARM invece entrano in un loop infinito e li rimangono.

E comunque nell'embedded non ha molto senso uscire dal main(), perchè il comportamento è indefinito (perlomeno dallo standard, ogni piattaforma può fare quello che vuole.).

 

Ciao, Ale.

Link al commento
Condividi su altri siti

1 ora fa, vergalabs ha scritto:

THIS PIC MAKE ME CRAZY !!!

 

Quello che ti succede non è ammissibile, è fuori da ogni regola.

Scrivi qual compliatore "C" stai usando ed in quale ambiente stai lavorando.

Potrebbe anche essere un problema di compilatore mal settato.

 

Sono alcuni anni che non lavoro con i PIC ma un compilatore "C" è un compilatore "C", punto

 

tanto per darti un esempio, il primo che ho ritrovato in un CD che avevo a portata di mano

/*-------------------------------01-05-2001 18.05--------------------------------------*
 *                                                                                     *
 *                                       MAIN                                          *
 * ------------------------------------------------------------------------------------*/

void calib ()
{

    int i = 0;
    char c;
    short a;

    vis_cal_mes(1);
    #asm
         bcf      flg_key_pres
         bcf      flg_mesure
         bcf      flg_up
         bcf      flg_cal
      loop:
    #endasm
/*-----------------------------------------01-06-2001 16.55----------------------------*
 *                                   Eseguo calibrazioni di base                       *
 ------------------------------------------------------------------------------------*/
        if(flg_i  == true)
                     calib_i();
        if(flg_mv  == true)
                     calib_mv();
        if(flg_th  == true)
                     calib_th();
        if(flg_ph  == true)
                     calib_ph();
    #asm
         bcf     flg_2_sec
      loop0:
         btfss   flg_2_sec
         goto    loop0
         btfsc    flg_mesure
         goto     end
	 btfss    flg_Up
	 goto     loop
      end:
         bcf      flg_key_pres
         bcf      flg_up
         bcf      flg_mesure
    #endasm

}



 

E il main che esegue un programma di test e che richiama funzioni esterne specifiche. Il programma cicla a tempo indefinito si o a quando non viene premuto un certo tasto. Il programma è sicuramente funzionante visto che è servito a collaudare una certa quantità di un tipo di strumento.

Link al commento
Condividi su altri siti

17 minuti fa, ilguargua ha scritto:

Perchè no? quando il suo while finisce, termina anche il main(), e li esce.

 

E perchè mai dovrebbe uscire?

Dipende dal tipo compilatore ma, che io ricordi, andando a vedere l'assembler generato dal compilatore alla fine c'è un bel salto all'inizio, almeno sui compilatori HiTech e sui comnpilatori CCSC, che sono i due compliatori che ho sempre usato per i PIC.

Non è questione di Hw, ma esclusivamente questione di compilatore.

 

Comunque, come ti ho scritto prima, mettere il secondo while come hai indicato blocca in loop il programma. Guarda l'esempio main che ho riportato, per uscire dal main devo dare un'apposito comando.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

lo so che è strano, sto utilizzando l'ambiente di sviluppo proposto da microchip mplab x ide con installato il compilatore xc8 per programmare il pic utilizzo un clone del pickit 2 andando a pescare il file hex dalla cartella creata da mplab x ide.

Una volta finito il while quando i>5 il ciclo non dovrebbe "ciclare" all'interno del void main e quindi scrivere una sola volta all'avvio del pic 0 nella variabile i ?

ora provo a inserire il secondo while, in un modo o nell'altro 

 

 

 

Link al commento
Condividi su altri siti

25 minuti fa, vergalabs ha scritto:

Una volta finito il while quando i>5 il ciclo non dovrebbe "ciclare" all'interno del void main e quindi scrivere una sola volta all'avvio del pic 0 nella variabile i ?

No, non c'è niente che lo faccia ciclare, quindi il main() esce quando terminano le istruzioni al suo interno, come qualunque altra funzione, e il programma riparte dall'inizio, compresa l'inizializzazione a 0 della variabile fuori dal main().

 

25 minuti fa, vergalabs ha scritto:

ora provo a inserire il secondo while, in un modo o nell'altro 

Funziona in entrambi i modi, tra l'altro la soluzione proposta da Livio è quella che avevo messo anch'io nel mia prima risposta, se lo scopo è bloccare completamente il micro dopo la sequenza fino al successivo reset entrambe le soluzioni sono equivalenti.

 

Ciao, Ale.

Modificato: da ilguargua
Link al commento
Condividi su altri siti

28 minuti fa, vergalabs ha scritto:

ora provo a inserire il secondo while, in un modo o nell'altro 

 

No, non in un modo o nell'altro, ma come l'ho scritto io nella risposta ad Ale; se lo scrivi come proposto da lui esegue si una sola volta il ciclo while (i<5) perchè poi si blocca nel secondo ciclo di while.

 

Questo è il compilatore in versione gratuita fornito da microchip?

Se si dovrebbe avere l'opzione, nel faile listi, di mostrare anche lo asm, quindi si potrebbe vedere bene come risolve.

 

 

Link al commento
Condividi su altri siti

AND THE WINNER IS...........................................

LIVIO !!!!!!!!!!!!!!

finalmente funziona, ho provato ad inserire i due cicli while come suggerito da ilguargua e livio e il modo proposto da livio funziona correttamente, il ciclo vien ripetuto 5 volte all'accensione del pic.

come ragionamento ci sta si esegue prima il while più interno incrementando "i" e una volta raggiunto i=5

si rimane bloccati nel primo while (1) a tempo indefinito.

 

ora sotto con il saldatore che il pic va inserito al suo posto

 

grazie come sempre a tutte le persone che su questo sito sono sempre pronte a darti una mano

 

 image.png.3064c2c3afb52373e748e6e20564e906.pngimage.png.2df214193a6fa91fd2d97fc6372203e4.png

Link al commento
Condividi su altri siti

6 minuti fa, ilguargua ha scritto:

No, non c'è niente che lo faccia ciclare, quindi il main() esce quando terminano le istruzioni al suo interno, come qualunque altra funzione, e il programma riparte dall'inizio, compresa l'inizializzazione a 0 della variabile fuori dal main().

 

No riparte da sotto l'apertura della grafa.

Questo l'ho osservato parecchie volte qaundo vado a vedere l'espansione in ASM per apportare ottimizzazioni. Dove c'è la grafa il compilatore risolve con una label e quando arriva all chiusura della grafa del main mette un salto alla prima label.

Se così non fossse il PC proseguirebbe con quello che trova scritto in  memoria.

 

10 minuti fa, ilguargua ha scritto:

se lo scopo è bloccare completamente il micro dopo la sequenza fino al successivo reset entrambe le soluzioni sono equivalenti.

 

No la tua blocca, la mia cicla senza eseguire alcuna operazione se non il salto.🙂

Link al commento
Condividi su altri siti

11 minuti fa, Livio Orsini ha scritto:

No riparte da sotto l'apertura della grafa.

Questo l'ho osservato parecchie volte qaundo vado a vedere l'espansione in ASM per apportare ottimizzazioni. Dove c'è la grafa il compilatore risolve con una label e quando arriva all chiusura della grafa del main mette un salto alla prima label.

appunto allora con int=0 scritto prima del main avrebbe dovuto funzionare

 

21 minuti fa, Livio Orsini ha scritto:

 

No, non in un modo o nell'altro, ma come l'ho scritto io nella risposta ad Ale; se lo scrivi come proposto da lui esegue si una sola volta il ciclo while (i<5) perchè poi si blocca nel secondo ciclo di while.

avrei dovuto scrivere: nei due modi proposti

Link al commento
Condividi su altri siti

L'importante è che tu abbia risolto.

Però se pubblicassi il listato con l'opzione asm sarei curioso di capire come il tuo complitaore risolve.

Link al commento
Condividi su altri siti

Hai 2 opzioni metti il programma su un sito di hosting e poi metti il link nel messaggio.

Oppure, se è non molto lungo, usa il tasto "code" che è quello con l'icona "<>", si apre una finestra dove tu incolli il testo del listato, come ho fatto io con il programma che ho inserito.

Link al commento
Condividi su altri siti

1 minuto fa, giacomo56 ha scritto:

Ho compilato il programma originale. Il compilatore inserisce alla fine del main un goto 0x00, per questo non termina mai.

 

Sicuro che sia alla locazione 0x00 e non ad una label?

Mi sembra strano perchè così facendo riparte anche l'inizializzazione.

Potresti copiare il codice e riportarlo qui?

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