Jump to content
PLC Forum


Sign in to follow this  
elektrobeam

Rework Station: Pic16F675 Start/stop Interrupt Main()

Recommended Posts

elektrobeam

Salve a tutti,

Sto progettando una rework station semplice per saldature BGA; il programma dovrà effettuare le seguenti operazioni:

-tramite push-button viene avviata la procedura di saldatura su pin GP2

-viene gerata la funzione di reflow "ideale" tramite la variabile a in funzione del tempo

-viene misurata la temperatura sul pin AN0 e convertita dall'adc

-vengono confrontate a(t) e la temperatura T(adresh,adresl), se a(t)-T=D>0 allora pwm = D altrimenti PWM = 0

-PWM = D * 1 dove 1 è un coefficiente empirico da cambiare dopo effettuate le prove

-lampeggierà il led GP5 dall'inizio della 2° temperatura stabile (guarda funzione.png) per 20 secondi

-terminati i 20 s il led diventerà fisso on= fase raffreddamento PWM bottom=PWM top =0

-se viene ripremuto il push-button GP2 tutto il processo deve esser stoppato: PWM bottom=PWM top =0

funzione pins micro:

ANO: ingresso analogico temperatura

GP1: uscita PWM bottom preheater

GP2: ingresso push-button (start/stop) con debouncing RC

GP3: ingresso switch lead free =0 o leaded = 1

GP4: output PWM top (si attiva solo nella seconda fase: 2° rampa e 2° temperatura stabile cioè reflow)

GP5: led

Programmazione: MPlab con compilatore xc8 e simulatore finale proteus

/* 
 * File:   rework.c
 * Author: x
 *
 * Created on 15 giugno 2015, 11.42
 */
// PIC12F675 Configuration Bit Settings
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <pic12f675.h>
#include <adc.h>
#include <delays.h>
#include <stdlib.h>
#include <plib/timers.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-Up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)



unsigned  T=0;//variabile temperatura binario
int D=0;       //differenza temperatura funzione reflow ideale rispetto quella campionata da adc
int PWM=0;
int enable_top=0;
int duty=0;
int flag=1;

//int adc();
//void interrupt ISR(void);

int main(int adc(),int flag)
{
  while(1)
    {
       while(flag)
       {//impostazione dei registri
             TRISIO = 0b001101; //ob=binario  e valore binario riferito ai pin 0 = out 1= in
             GPIO=0; // clear GPIO pins sarebbe PORT
             CMCON = 0b00000111;//disabilita comparatore analogico
             ANSEL = 0b0010001;//setta i bits <0:3>AN: 1=analogico, 0=digitale bits<4:6> freq ADC 2us
             ADCON0bits.VCFG = 0; //imposta VDD all'alimentazione dell'ADC
             ADCON0bits.ADFM = 1;//sposta i 10 bits verso destra su ADRESH_ADRESL
             ADCON0bits.CHS = 0b00; //muxa ingresso ADC su AN0
             INTCONbits.GIE = 1;//abilita interrupt generale
             INTCONbits.GPIE = 0;//disabilita interrupt dei pin GPIO
             INTCONbits.T0IE = 1;//abilita interrupt timer
             INTCONbits.PEIE = 0; //disabilita interrupt interni(timer, ADC, comparatore,etc)
             INTCONbits.INTE = 1; //abilita interrupt GP2
             INTCONbits.TMR0IE = 0;//disabilita interrupt TMR0
             IOC = 0b000100; //abilita interrupt su GP2 e disabilita tutti gli altri
             OPTION_REGbits.nGPPU =0; //pull-ups abilitati su GPIO
             OPTION_REGbits.INTEDG = 0;//interrupt GP2/INT falling edge
             OPTION_REGbits.T0CS =1; //interrupt hardware e non soft su GP2
             OPTION_REGbits.T0SE =1; //interrupt GP2 fronte negativo
             OPTION_REGbits.PSA =1; //prescaler assegnato a WDT
             OPTION_REGbits.PS = 0b000;//prescaler settato a 1:1

             int a= adc();
             int b=0;//b=240 °C lead free o b=200 °C leaded
                if (GP3==0)
                    b=240;
                else b=200;
                if (a<150)  //inizio funzione reflow
                {a++;              //prima rampa
                _delay(7*400000);//ritardo di 0.7s=0.7*4000000 cicli al secondo
                D= a-adc();  //D differenza temperature
                    if(D>0)   //condizione per incrementare PWM o no
                      {PWM=D*1;//1=valore da cambiare empiricamente
                      }
                 else
                 PWM = 0;
                }
                else if (a == 150) //prima temperatura costante
                {
                int d;
                   for (d = 0; d < 160; d++) //ritardo di 80s fatti col ciclo for
                   {
                   _delay(2000000);
                    D = a - adc();
                    if (D > 0)
                       {
                       PWM = D * 1;
                       } else
                    PWM = 0;
                   }
                   a++;
                }
                else if (150 < a <  //seconda rampa
                {
                enable_top = 1; //abilita pwm riscaldatore top
                a++;
                _delay(5 * 400000); //ritardo 0.5s ad ogni incremento di a
                D = a - adc();
                if (D > 0)
                   {
                   PWM = D * 1;
                   }
                else
                PWM = 0;
                }
                else if (a ==  //seconda temperatura costante
                {
                enable_top = 1;
                int i;
                     for (i = 0; i < 100; i++)//lampeggia per 20s e contemporaneamente si ha il ritardo
                         {
                         GP5 = 1;
                         _delay(400000);
                         GP5 = 0;
                         _delay(400000);
                         D = a - adc();
                              if (D > 0)
                                  {
                                  PWM = D * 1;
                                  }
                                  else
                         PWM = 0;
                        }
               GP5 = 1; //led on
            //fine funzione reflow
                }          
            }
        _delay(10);//ritardo 10 colpi clock
       }
  return 0;
    }


int adc()//funzione di ADC continua
{
    ADCON0bits.ADON = 1; //accende ADC
    while (ADCON0bits.GO); //aspetta che la conversione sia finita
    T = (ADRESH << 8) + ADRESL; //legge il valore in binario
    char deci[4];
    utoa(deci, T, 10); //bin to decimal conversion
    int temp_dec = (int) deci; //char to int
    return temp_dec;
}

int interrupt ISR(void)
{
    //routine start stop
    if (INTF == 0 && flag == 0) //se GP2 è low la 1° volta= START; INTF è interrupt esterno su GP2
    {
        flag = 1;//esegue corpo del main
        if (T0IF) //interrupt di timer0
        {
            if (enable_top == 1) //se abilitato PWM2 manda segnale su GP1 e GP4
            {
                if (GP1)//se GP1=1
                {
                    TMR0 = PWM; //conta fino al valore di PWM
                    GP1 = GP4 = 0;
                } else
                {
                    TMR0 = 255 - PWM; //duty cycle complementare
                    GP1 = GP4 = 1;
                }
            } 
            else
            {
                if (GP1)
                {
                    TMR0 = PWM;
                    GP1 = 0;
                } 
                else
                {
                    TMR0 = 255 - PWM;
                    GP1 = 1;
                }
            }
            T0IF = 0;
        }
        INTF = 1;//resetta INTF
    } 
    else if (INTF == 0 && flag == 1) //se avviene x la 2° volta GP2 low= STOP
        {
        flag = 0;
        GP1 = GP4 = 0;//spegni l'uscita pwm
        INTF = 1;    //resetta INTF
        }
    return flag;// errato!!!!!!
}

Problema da risolvere:

la variabile flag deve cambiare valore sotto interrupt di GP2 (start/stop) invece flag rimane sempre a zero, ho sicuramente commesso gravi errori di programmazione soprattutto il fatto di far ritornare alla ISR la variabile flag: errore gravissimo: come risolvo?

Scusate se le miniature fatte a mano fanno schifo.

Grazie in anticipo

post-222068-0-15154900-1437298382_thumb.

post-222068-0-51928900-1437298392_thumb.

Edited by elektrobeam

Share this post


Link to post
Share on other sites

Ctec

Dovrebbe essere perchè, avendo te messo due argomenti nella definizione del main() (ma perchè? Mica gli arrivano da nessuna parte...), il secondo definisce una variabile interna al main() che si chiama flag. Le locali hanno priorità sulle globali, per cui dentro il main() la variabile flag avrà il valore che gli viene passato dal chiamante (che non essendoci sarà un valore a caso o dipendente dal compilatore).

Pertanto, la flag esterna definita fuori dal main() l'hai resa invisibile al suo interno.

Prova a levarla e definisci la main come main() e basta.

Poi non ho guardato se c'è qualche altro inghippo software.

Share this post


Link to post
Share on other sites
Livio Orsini
Prova a levarla e definisci la main come main() e basta.

Anche se la sintassi non lo vieta, è buona norma di buona programmazione definire sempre "main ()", come è sempre buona programamzione definire nelle variabili globali tutte le variabili a cui hanno accesso più funzioni.

Se proprio si vuol risparmiare memoria è meglio definire le variabili flag come booleane, così nello spazio di un int ce ne stanno 8 o 16 8dipende dal compilatore se assegna un byte o due bytes alle int)

Tra l'altro è sempre bene specificare ill tipo di compilatore in uso.

Edited by Livio Orsini

Share this post


Link to post
Share on other sites
giacomo56

Oltre agli argomenti della funzione main da togliere ad una prima occhiata ci sono delle cose che non vanno.

Le variabili se il segno non interessa e contengono un numero minore di 256, come quelle che usi mi pare, è meglio dichiararle unsigned char.

Il flag INTF va usato al contrario, l'interruzione scatta quando vale 1 e non zero e se il caso va resettato.

E' meglio controllare i flag d'interruzione singolarmente mentre tu controlli l'int del timer dentro l'int dell'ingresso.

In adc controlli il bit GO ma chi lo mette a 1?

La funzione ISR non può ritornare un valore e deve essere dichiarata void, quindi return flag oltre a non servire non è corretto.

Ciao.

Edited by giacomo56

Share this post


Link to post
Share on other sites
elektrobeam

Premetto che a programmazione sono una frana:

Quindi ho tolto gli argomenti dal main() e non ha dato errori.

Rimane il problema start/stop che non ho capito quali escamotage fare per far partire o stoppare(in qualsiasi punto si trovi il programma) tramite push-buttton.

@giacomo56 INTF==0 cioè dal circuito che ho fatto MINIATURE quando premo push-button cioè GP2==0

grazie infinite dei consigli.

Share this post


Link to post
Share on other sites
giacomo56

La compilazione non da errori ma il programma non credo funzioni.
Dovresti procedere per gradi partendo da un programma semplice testandolo e aggiungendo man mano le altre parti.
Per INTF, quando premi il pulsante GP2 va a zero, scatta l'interruzione ed il flag INTF viene messo a 1. Per tutti gli interrupts i flags relativi vengono messi a 1.
Aggiungo che ho dei dubbi che l'istruzione
int temp_dec = (int) deci; //char to int

faccia quello che vuoi, deci è un puntatore. Controlla.

Altra cosa le istruzioni di inizializzazione non le mettere nel ciclo while, ma inseriscile prima.

Per lo start/stop dai un altro valore alla variabile flag. Es: inizialmente vale zero, premendo il pulsante va a 1, la seconda volta a 2, la terza torna a zero o qualcosa di simile.

Ciao.

Share this post


Link to post
Share on other sites
Livio Orsini

Dovresti anche specificare il tipo di compilatore usato (CSC?, HigTech?, altro?). Non tutti i compilatori hanno le medesime direttive.

Share this post


Link to post
Share on other sites
giacomo56

Usa il compilatore xc8 della Microchip.

Share this post


Link to post
Share on other sites
elektrobeam

@ LIvio Orsini :

Utilizzo il compilatore XC8

@giacomo56:

quindi metto

if(INTF==1)

...INTF=0; //reset INTF

le istruzioni di inizializzazione le metterò subito dopo il main

deci un puntatore?non è un semplice vettore?(non ricordo bene)

flag quindi sempre nel ciclo ISR e qual'è il modo di far partire tutto il main()?

Share this post


Link to post
Share on other sites
Livio Orsini
Utilizzo il compilatore XC8

Fortunatamente io uso CSC che è molto più simile allo standard "C".

A parte uesto, tutto quello chai scritto nelle prime righe del main, ovvero le impostazioni dei registri, dovrebbe essere esterno ai 2 cicli "while", uelle sono istruzioni che si eseguono una volta sola, alla partenza.

Io ti consiglierei di studiarti bene il linguaggio "C", anzi forse dovresti iniziare ancora dai fondamenti di programamzione, fonndamenti che sono indipendenti dal linguaggio e dalla macchina.

Share this post


Link to post
Share on other sites
giacomo56

In effetti la sintassi è corretta ed è già qualcosa ma ci sono degli errori nella logica del programma.
Una svista: abiliti l'interrupt del timer0 e poi la disabiliti.

La struttura sarebbe simile a questa:

uint8_t flag = 0;

void main()
{
    //Inizializzazione
    
    while(1)
    {
        if(flag == 0) // Condizione iniziale o è stato premuto il pulsante di start/stop una seconda volta
        {
            //
        }
        else // E' stato premuto il pulsante di start/stop
        {
            //
        }
    }
}

void interrupt ISR()
{
    if(INTF == 1)
    {
        flag = !flag; //Inverto il valore di flag
        INTF = 0;
    }
    if(T0IF == 1)
    {
        //Istruzioni
        T0IF = 0;
    }
}

Un problema è che per i ritardi che ci sono nel programma l'effetto del tasto premuto lo vedi dopo parecchi secondi.

Al nome di un vettore è associato l'indirizzo di inizio dello stesso, infatti scrivere deci[0] è uguale a scrivere *deci, deci[1] è uguale a *(deci+1), ecc..

Ciao.

Share this post


Link to post
Share on other sites
elektrobeam

@giacomo56:

Grazie mille col codice sei stato molto chiaro.

Ritardo:

cioè se ad esempio il programma si trova nel ciclo for e lo stoppo lui di sicuro si finisce il ciclo se non addirittura fa altre funzioni?

Riguardo :

char deci[4];
utoa(deci, T, 10); //bin to decimal conversion
int temp_dec = (int) deci; //char to int

pensi che sia errato?

Share this post


Link to post
Share on other sites
Livio Orsini

Così come ha scritto il programma Giacomo, alla pressione del tasto dovrebbe corrispondere l'interrupt che immediatamente cambia lo stato del flag.

Non appena termina la routine di interrupt il programma riprende da dove era stato interrotto.

Se le due condizioni del main non sono lunghe da elaborare la condizione del tasto è percepita quasi immediatamente.

Share this post


Link to post
Share on other sites
giacomo56

Si per tutte e due le domande.

Ma i'adc ti da già la temperatura in gradi? Se è così non devi fare nessuna conversione.

La funzione utoa converte un intero in stringa usando il corrispondente codice ASCII per ogni cifra e non è possibile riconvertirlo in intero con un semplice casting.

Ammesso che il codice funzionasse non farebbe altro che convertire int a stringa e poi di nuovo a int.

Ciao.

Share this post


Link to post
Share on other sites
elektrobeam

Allora gli ho settato il pin per l'ingresso analogico AN0 poi da come ho visto da datasheet l'adc converte il valore analogico in binario (10 bits) nei registri ADRESH-ADRESL:

andate al datasheet pic12f675 pag 43

Quinidi la conversione è obbligatoria, oppure potrei eliminare la conversione modificando i valori nel programma tutti in binario, ma dopo è più difficile da leggere al volo.

Ciao.

Share this post


Link to post
Share on other sites
giacomo56

Mi sa che confondi il tipo di una variabile con la sua rappresentazione.

255 è un numero intero. 0xff, 0b11111111 rappresentano lo stesso numero intero in esadecimale e in binario.

Tu nel programma puoi scrivere il numero come vuoi in decimale, in binario, in esadecimale, in ottale poi internamente alla macchina

viene memorizzato sempre in binaio.

Ciao.

Share this post


Link to post
Share on other sites
elektrobeam

Ciao Giacomo,

Grazie mille hai pienamente ragione, non ci avevo pensato.

Share this post


Link to post
Share on other sites
elektrobeam

La funzione di conversione quindi è diventata:

int adc()//funzione di ADC continua
{
    ADCON0bits.ADON = 1; //accende ADC
    while (ADCON0bits.GO); //aspetta che la conversione sia finita
    T = (ADRESH << 8) + ADRESL; //legge il valore in binario
    //char deci[4];
   // utoa(deci, T, 10); //bin to decimal conversion
   // int temp_dec = (int) deci; //char to int
   // return temp_dec;
    return T;
}

Share this post


Link to post
Share on other sites
giacomo56

La conversione parte con l'istruzione ADCON0bits.GO = 1 quindi devi aggiungerla.

L'accensione dell'ADC se non hai problemi di risparmio energetico, non credo, mettila tra le istruzioni di inizializzazione.

Un'altra cosa. La variabile T è una variabile globale (dichiarata fuori delle funzioni) quindi return T non servirebbe.

Togli la dichiarazione di T all'inizio del programma e mettila all'inizio di adc() (variabile locale).

uint16_t adc()//funzione di ADC continua
{
    uint16_t T; // intero senza segno
    ADCON0bits.GO = 1; // Avvio conversione
    while (ADCON0bits.GO); //aspetta che la conversione sia finita
    T = (ADRESH << 8) + ADRESL; //legge il valore in binario
    return T;
}

Ciao.

Edited by giacomo56

Share this post


Link to post
Share on other sites
elektrobeam

@giacomo #11

uint8_t flag = 0;

perchè questo tipo? comunque l'ho messo.

Inoltre ho integrato flag sia nel corpo generico di tutto il processo (poco utile) e soprattutto nei cicli che generano maggior ritardo tranne che nel ciclo for del periodo di reflow.

Ecco il codice poi lo testerò su proteus e vi farò sapere.

/* 
 * File:   rework.c
 * Author: x
 *
 * Created on 15 giugno 2015, 11.42
 */
// PIC12F675 Configuration Bit Settings
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <pic12f675.h>
#include <adc.h>
#include <delays.h>
#include <stdlib.h>
#include <plib/timers.h>
#include <stdint.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-Up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)



unsigned  T=0;//variabile temperatura binario
int D=0;       //differenza temperatura funzione reflow ideale rispetto quella campionata da adc
int PWM=0;
int enable_top=0;
int duty=0;
uint8_t flag = 0;

//int adc();
//void interrupt ISR(void);

void main()
{//impostazione dei registri
             TRISIO = 0b001101; //ob=binario  e valore binario riferito ai pin 0 = out 1= in
             GPIO=0; // clear GPIO pins sarebbe PORT
             CMCON = 0b00000111;//disabilita comparatore analogico
             ANSEL = 0b0010001;//setta i bits <0:3>AN: 1=analogico, 0=digitale bits<4:6> freq ADC 2us
             ADCON0bits.VCFG = 0; //imposta VDD all'alimentazione dell'ADC
             ADCON0bits.ADFM = 1;//sposta i 10 bits verso destra su ADRESH_ADRESL
             ADCON0bits.CHS = 0b00; //muxa ingresso ADC su AN0
             INTCONbits.GIE = 1;//abilita interrupt generale
             INTCONbits.GPIE = 0;//disabilita interrupt dei pin GPIO
             INTCONbits.T0IE = 1;//abilita interrupt timer
             INTCONbits.PEIE = 0; //disabilita interrupt interni(timer, ADC, comparatore,etc)
             INTCONbits.INTE = 1; //abilita interrupt GP2
             INTCONbits.TMR0IE = 0;//disabilita interrupt TMR0
             IOC = 0b000100; //abilita interrupt su GP2 e disabilita tutti gli altri
             OPTION_REGbits.nGPPU =0; //pull-ups abilitati su GPIO
             OPTION_REGbits.INTEDG = 0;//interrupt GP2/INT falling edge
             OPTION_REGbits.T0CS =1; //interrupt hardware e non soft su GP2
             OPTION_REGbits.T0SE =1; //interrupt GP2 fronte negativo
             OPTION_REGbits.PSA =1; //prescaler assegnato a WDT
             OPTION_REGbits.PS = 0b000;//prescaler settato a 1:1

  while(1)
  {
       if(flag == 1 )//inzialmente flag=0 poi con lo start in ISR viene negato => flag = 1
       {
             int a= adc();
             int b=0;//b=240 °C lead free o b=200 °C leaded
                if (GP3==0)
                    b=240;
                else b=200;
                if (a<150 && flag == 1)  //inizio funzione reflow
                {a++;              //prima rampa
                _delay(7*400000);//ritardo di 0.7s=0.7*4000000 cicli al secondo
                D= a-adc();  //D differenza temperature
                    if(D>0)   //condizione per incrementare PWM o no
                      {PWM=D*1;//1=valore da cambiare empiricamente
                      }
                 else
                 PWM = 0;
                }
                else if (a == 150 && flag == 1) //prima temperatura costante
                {
                int d;
                   for (d = 0; d < 160; d++) //ritardo di 80s fatti col ciclo for
                   { if (flag == 1)
                   {
                   _delay(2000000);
                    D = a - adc();
                    if (D > 0)
                    {
                     PWM = D * 1;
                     }
                    else
                    PWM = 0;
                   }
                   else
                       PWM=0;
                   }
                   a++;
                }
                else if (150 < a < b && flag == 1) //seconda rampa
                {
                enable_top = 1; //abilita pwm riscaldatore top
                a++;
                _delay(5 * 400000); //ritardo 0.5s ad ogni incremento di a
                D = a - adc();
                if (D > 0)
                   {
                   PWM = D * 1;
                   }
                else
                PWM = 0;
                }
                else if (a == b && flag == 1) //seconda temperatura costante
                {
                enable_top = 1;
                int i;
                     for (i = 0; i < 100; i++)//lampeggia per 20s e contemporaneamente si ha il ritardo
                     {                        //per questi 20 s flag non lo faccio intervevire
                         GP5 = 1;
                         _delay(400000);  //lampeggio a 10 Hz
                         GP5 = 0;
                         _delay(400000);
                         D = a - adc();
                              if (D > 0)
                              {
                              PWM = D * 1;
                              }
                     }
                }
                else if (a>b && flag == 1) //processo terminato con successo
                {PWM = 0;
                      GP5 = 1; //led on
            //fine funzione reflow
        _delay(10);//ritardo 10 colpi clock
                }
                else      //processo terminato per problemi
                {PWM=0;
                }
       }
       else   //processo terminato da incipit (poco utile)
       {
       PWM = 0;
       }
  }
}


int adc()//funzione di ADC continua
{
    ADCON0bits.ADON = 1; //accende ADC
    while (ADCON0bits.GO); //aspetta che la conversione sia finita
    T = (ADRESH << 8) + ADRESL; //legge il valore in binario
    //char deci[4];
   // utoa(deci, T, 10); //bin to decimal conversion
   // int temp_dec = (int) deci; //char to int
   // return temp_dec;
    return T;
}

void interrupt ISR(void)
{ if (INTF)
   {flag=!flag;
   INTF=0;
   }
  
        if (T0IF) //interrupt di timer0
        {
            if (enable_top == 1) //se abilitato PWM2 manda segnale su GP1 e GP4
            {
                if (GP1)//se GP1=1
                {
                    TMR0 = PWM; //conta fino al valore di PWM
                    GP1 = GP4 = 0;
                } else
                {
                    TMR0 = 255 - PWM; //duty cycle complementare
                    GP1 = GP4 = 1;
                }
            } 
            else
            {
                if (GP1)
                {
                    TMR0 = PWM;
                    GP1 = 0;
                } 
                else
                {
                    TMR0 = 255 - PWM;
                    GP1 = 1;
                }
            }
            T0IF = 0;
        }
  
  
}

Share this post


Link to post
Share on other sites
giacomo56

uint8_t equivale a unsigned char (8 bit senza segno), int occupa 16 bit e sarebbe uno spreco in questo caso.

Share this post


Link to post
Share on other sites
elektrobeam

Ho simulato ma pwm non si vede:

secondo voi ISR prende il valore di PWM dal programma pricipale?

Ho fatto debug e dopo vari step-into si blocca ad if(flag == 1) forse perchè dovrei dargli gli stimoli su GP2 che mi sembrano non funzionino (MPLab su linux)

Share this post


Link to post
Share on other sites
giacomo56

GP2 lo devi mettere a 1 e poi a zero.
Si, ISR prende il valore dal programma principale.

Hai corretto la funzione adc()? Nell'ultimo listato no.

Ciao.

Share this post


Link to post
Share on other sites
elektrobeam

Ciao Giacomo,

Allora ho cambiato la funzione di adc() che hai detto, ma mi dà errore fra tipi per quanto riguarda T:

inizialmente è binario poi lo forzerebbe ad essere uint16_t: forse questo il problema.

Grazie infinite del supporto.

Share this post


Link to post
Share on other sites
giacomo56

Se hai cambiato la funzione adc() come l'ho scritta io controlla di aver tolto la dichiarazione di T all'inizio del programma.

Puoi mettere int al posto di tutti gli uint16_t che ho messo io.

Come ho detto prima binario è la rappresentazione uint16_t è il tipo, cioè uint16_t indica un intero a 16 bit senza segno (unsigned int).

Ciao.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...