Vai al contenuto
PLC Forum


Sorgente C. - Chi sà spiegarmi il main?


surveyor

Messaggi consigliati

Ciao a tutti, vorrei sapere se potreste darmi una mano a capire il seguente Sorgente c., potreste ricavarmi un diagramma di flusso o commentare il c.? Basta dall'inizio alla fine del main, e se possibile sapere la frequenza del PWM e come effettua l'ADC dato che il piedino in ingresso riceve max 5V e il PWM a valle dei transistor è 25V, mi fareste un grosso piacere.

Grazie

//-------------------------- ALIM V3 ----------------------------------------
//    ALIMENTATION VARIABLE CONSTANT VOLTAGE, CONSTANT COURANT,  0 < 25V
 1-2-4-8A
//---------------------------------------------------------------------------
#include <16F876a.h>
#device ADC=16                      // i 10 bit sono validi a sinistra
#use delay(clock=20000000)
#fuses HS,NOWDT,PUT,BROWNOUT,NOPROTECT,NOLVP,NOCPD,NOWRT
//#rom 0x2100={0x00,0x00,0x00,0x00,0x00}   // Zero le prime 4 caselle di EEDATA
#use fast_io(A)
#use fast_io(B)
#use fast_io©

//------------------------- VARIABLES -------------------

INT8 i;                //  0 < + 255
int8 commande;         //  0 < + 255
int8 car;              //  0 < + 255
int8 nibble;           //  0 < + 255
int8 boutons;          //  0 < + 255
int8 bit_status;       //  0 < + 255
int16 disp_a;           //  gamma di display Amp
int8 disp_ma;          //  gamma di display mAmp

//-----------

signed int16 volt_moy[16];
signed int16 amp_moy[16];
signed int16 volt_set=0;   // -32768 < +32767
signed int16 volt_lue=0;     //    "        "
signed int16 amp_set=0;  //    "        "
signed int16 amp_lue=0;      //    "        "

//------------------------- FONCTIONS ---------------

void pic_ini(void);
void lcd_ini(void);
void write_cmd_lcd(int8);  // LCD
void write_car_lcd(INT8);  // LCD
void send_nibble(int8);    // LCD
void busy_status(void);        // LCD

void lire_voltage(void);   // leggere e visualizzare E
void lire_courant(void);   // leggere e visualizzare I
void lire_PB(void); // leggere i pulsanti, modificare le impostazioni di tensione e corrente
void set_range(void);
void comparer_Iset_Ilue(void); // stabilire chi è in controllo, E o I

//********************************* MAIN ***********************************

void main(void)
{
   pic_ini();
   lcd_ini();
   for(i=0;i<=15;i++) volt_moy[i]=0;
   for(i=0;i<=15;i++) amp_moy[i]=0;


//------- schermo di "benvenuto -------
   write_cmd_lcd(128);      // indirizzo di inizio della prima linea
   printf(write_car_lcd,"ALIMENTATION V3 ");
   write_cmd_lcd(192);      // indirizzo di inizio della fila 2 esima
   printf(write_car_lcd,"   PAR VE2EMM   ");
   for(i=0;i<4;i++) delay_ms(250); // lasciare display 1 1 / 2 secondi

//---- charger les valeurs du eedata
   for(i=0;i<2;i++) *(&volt_set+i)=read_eeprom(10+i); // prendere le istruzioni
   if((volt_set>1023)||(volt_set<0))volt_set=0;
   for(i=0;i<2;i++) *(&amp_set+i)=read_eeprom(12+i);  // utilizzato per ultimo
   if((amp_set>1023)||(amp_set<0))amp_set=0;

//---- programma principale
   while(true)
   {
      set_range();// scegliere l'intervallo di corrente, 1, 2, 4 o 8 Amp
      lire_PB(); // pulsanti e leggere le istruzioni mettere tensione e corrente

      write_cmd_lcd(128);      // indirizzo di inizio della prima linea
      printf(write_car_lcd,"%01ld,%03ldA SET %02ld,%01ldV",amp_set/disp_a,amp_set*disp_ma,volt_set/40,volt_set/4);
      SET_PWM1_duty(amp_set);  // amp_set
      SET_PWM2_duty(volt_set); // volt_set

      lire_voltage();       // leggere e visualizzare
      lire_courant();       // leggere e visualizzare
      comparer_Iset_Ilue(); // leggere e mostrare che è in controllo, E o I
   }
}

//********************************* FIN MAIN ******************************

//************************************ FONCTIONS *****************************

void pic_ini(void)
{
//-- PORTS
   output_A(0x00);
   output_B(0x00);
   output_C(0x00);
   set_tris_A(0b11011111);
   port_B_pullups(true);
   set_tris_B(0b11111111);
   set_tris_C(0b00000000);
//--- ADC
   setup_adc_ports(RA0_RA1_RA3_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
//--- PWM
   SET_PWM1_duty(0); // amp_set
   SET_PWM2_duty(0); // volt_set
   setup_timer_2(t2_div_by_16,255,1);
   setup_ccp1(CCP_PWM_PLUS_3);
   setup_ccp2(CCP_PWM_PLUS_3);
}

//-------------------------------------------------

void lcd_ini(void)
{
	delay_ms(100);        // attendre que le 5V soit stabilise
   output_bit(PIN_A5,0); // E clock
   output_bit(PIN_C0,0); // R/W  R=1,W=0
   output_bit(PIN_C3,0); // R/S 0 pour commande, 1 pour data
	for(i=1;i<=4;i++) {send_nibble(0x30); delay_ms(5);} // reset du LCD
   send_nibble(0x20);    // interface 4 bits
   delay_us(43);
	write_cmd_lcd(0x28);  // interface 4 bits, 5X7
   write_cmd_lcd(0x08);  // display off
	write_cmd_lcd(0x0C);  // display on
	write_cmd_lcd(0x06);  // increment no display shift
}

//*********************** Fonctions du LCD *****************************

void write_cmd_lcd(commande)
{
   busy_status();          // LCD pronto?
   output_bit(PIN_C3,0);   // R / S 0 per il controllo
	send_nibble(commande);  // controllo messa in LCD
   swap(commande);
   send_nibble(commande);  // placer commande dans LCD
}

//-------------- visualizzare un carattere sullo schermo LCD--------------------------

void write_car_lcd(car)
{
   busy_status();         // LCD pret?
   output_bit(PIN_C3,1);  // R/S 1 pour data
	send_nibble(car);      // placer commande dans LCD
   swap(car);
   send_nibble(car);      // placer commande dans LCD
}

//-------------------- Envoyer un nibble ----------------

void send_nibble(nibble)
{
   output_bit(PIN_C0,0);  // R/W  R=1, W=0
	output_bit(PIN_A5,0);  //  E line low
   delay_cycles(3);
	output_bit(PIN_A5,1);  // pulser E high
   nibble=nibble&0xF0;    // vider les 4 bits du bas de la byte
   nibble=nibble|(input_C()&0x0F); // charger C0-C3
   output_C(nibble);
   delay_cycles(3);
   output_bit(PIN_A5,0);  // E Basso
}

//-----------------------

void busy_status() // verificare se il display LCD è pronto ad accettare un dato
{
   do
   {
      set_tris_C(0b11110000);
      output_bit(PIN_A5,0); // E off
      output_bit(PIN_C0,1); // R/W  R=1,W=0
      output_bit(PIN_C3,0); // R/S 0 pour commande, 1 pour data
      delay_cycles(3);
      output_bit(PIN_A5,1); // pulser E high
      delay_cycles(3);
      bit_status=input_C()&0X80; // lire status
      delay_us(2);
      output_bit(PIN_A5,0); // E off
      delay_cycles(3);

      output_bit(PIN_A5,1); // pulser E high
      delay_us(1);          // faire semblant de lire les 4 bits de status du bas
      output_bit(PIN_A5,0); // E off
      delay_cycles(3);

   }
   while(bit_status==0x80);
   set_tris_C(0b00000000);
}

//***************************** Fin des fonctions LCD ********************************
//************************************************************************************

void lire_voltage()           // leggere e visualizzare
{
      SET_ADC_CHANNEL(0);
      delay_ms(1);
      for(i=15;i>=1;i--) volt_moy[i]=volt_moy[i-1];
      volt_moy[0]=READ_ADC()/64; // risolvere la lettura da destra a 2 byte, 6 bit
      volt_lue=0;
      for(i=0;i<=15;i++) volt_lue=volt_lue+volt_moy[i];
      volt_lue=volt_lue/16;
      volt_lue=volt_lue+2;//compensare il resto della divisione display
      //if(volt_lue<=7)volt_lue=0;
      write_cmd_lcd(203);     // Indirizzo 3 / 4 della 2ie online
      printf(write_car_lcd,"%02ld,%01ldV",volt_lue/40,volt_lue/4);
}

//----------------------------

void lire_courant() // leggere e visualizzare il test se ho superato il limite ed è in controllo
{
      SET_ADC_CHANNEL(1);
      delay_ms(1);
      for(i=15;i>=1;i--) amp_moy[i]=amp_moy[i-1];
      amp_moy[0]=READ_ADC()/64; // risolvere la lettura da destra a 2 byte, 6 bit
      amp_lue=0;
      for(i=0;i<=15;i++) amp_lue=amp_lue+amp_moy[i];
      amp_lue=amp_lue/16;
      amp_lue=amp_lue+1;
      write_cmd_lcd(192);    // indirizzo di inizio del 2ie linea
      printf(write_car_lcd,"%01ld,%03ldA",amp_lue/disp_a,amp_lue*disp_ma);
}

//----------------------------

void set_range()
{
   if((input(pin_A2)==1)&&(input(pin_A4)==1)){disp_a=1000;disp_ma=1;}
   if((input(pin_A2)==0)&&(input(pin_A4)==1)){disp_a=500;disp_ma=2;}
   if((input(pin_A2)==1)&&(input(pin_A4)==0)){disp_a=250;disp_ma=4;}
   if((input(pin_A2)==0)&&(input(pin_A4)==0)){disp_a=125;disp_ma=8;}
}

//--------------------------------------------------------------

void lire_PB() //pulsanti e leggere il setter di tensione e corrente
{
   boutons=input_b();
   if(boutons!=0xFF)
   {
      switch(boutons)
     {
         case 0b01111111:      // maggiore riduzione della tensione
            volt_set=volt_set-40;
            if(volt_set<=0) volt_set=0;
            break;
        case 0b10111111:      // grande riduzione della corrente
            amp_set=amp_set-50;
            if(amp_set<=0) amp_set=0;
            break;
         case 0b11011111:      // grande augmentation du voltage **********
            volt_set=volt_set+40;
            if(volt_set>=1000) volt_set=1000;
            break;
         case 0b11101111:      // grande augmentation du courant
            amp_set=amp_set+50;
            if(amp_set>=1000) amp_set=1000;
            break;
         case 0b11110111:      // piccolo aumento della tensione
            volt_set=volt_set+4;
            if(volt_set>=1000) volt_set=1000;
            break;
         case 0b11111011:      // petite augmentation du courant
            amp_set=amp_set+1;
            if(amp_set>=1000) amp_set=1000;
            break;
         case 0b11111101:      // petite reduction du voltage *************
            volt_set=volt_set-4;
            if(volt_set<=0) volt_set=0;
            break;
         case 0b11111110:      // petite reduction du courant
            amp_set=amp_set-1;
            if(amp_set<=0) amp_set=0;
            break;
         default:              //  pesa più di un pulsante
            break;
      }
      for(i=0;i<2;i++) write_eeprom(10+i,*(&volt_set+i));
      for(i=0;i<2;i++) write_eeprom(12+i,*(&amp_set+i));
      delay_ms(350);           // frequenza di ripetizione
   }
}

//-------------------------------

comparer_Iset_Ilue()
{
   write_cmd_lcd(198);  // centro della linea 2ie
   if (amp_lue<(amp_set-1)) printf(write_car_lcd," >>> ");
   else printf(write_car_lcd," <<< ");
}

//******************************** Fin des fonctions **************************************

Link al commento
Condividi su altri siti


condivido la risposta di Livio

Aggiungo una piccola spiegazione per surveyor per chiarire la posizione

Non si può chiedere in termini così generici.

Molte delle cose che chiedi le puoi ricavare dalla lettura della documentazione del micro

Fai un primo lavoro tu poi dove ti blocchi chiedi (Prima però studia la doc del micro e un minimo di C se non lo conosci)

Link al commento
Condividi su altri siti

Ciao a tutti e grazie per essere intervenuti.

Forse non mi rendo conto perche non conosco il c.,

E comunque non credo di aver chiesto molto!

Ci proveró io.

Link al commento
Condividi su altri siti

Provaci e vedi il tempo che impieghi. tongue.gif

Con una piccola differenza. Se lo fai direttamente tu sei costretto a capire quello che fai; se lo fa un altro per te è costretto a spiegarti quello che ha capito.

Link al commento
Condividi su altri siti

Capisco perfettamente, credevo che una persona che conosce il c Avrebbe saputo rispondere in poco tempo e magari più nel dettaglio.

Esempio:

//------- schermo di "benvenuto -------

1)write_cmd_lcd(128); // indirizzo di inizio della prima linea

2)printf(write_car_lcd,"ALIMENTATION V3 ");

3)write_cmd_lcd(192); // indirizzo di inizio della fila 2 esima

4)printf(write_car_lcd," PAR VE2EMM ");

5)for(i=0;i<4;i++) delay_ms(250); // lasciare display 1 1 / 2 secondi

1)chiamata funzione write_cmd_lcd (128)imdirizzamento cursore tipo (bit x,y)-->bit 0,0 ovvero cursore in posizione 0 prima linea.

Provo a fare una cosa del genere e poi proviamo a

correggere eventuali errori?

Grazie

Link al commento
Condividi su altri siti

A mio giudizio sarebbe più utile per te, ed anche più veloce, se tu spiegassi quale risultato vuoi ottenere. Se si tratta solo di capire, a grandi linee, come funziona quel programma, oppure se vuoi arrivare a programmare un dispositivo per fargli svolgere un determinato lavoro.

Link al commento
Condividi su altri siti

Si, effettivamente non ho spigato a cosa miro.

Questo programma è di un alimentatore microcontrollato, alla quale voglio apportare delle modifiche ma con un altro linguaggio.

Quello che fà il programma l'ho capito ho molta difficolta a capire istruzioni come questa:

if((volt_set>1023)||(volt_set<0))volt_set=0;

Se la condizione viene soddisfatta--> volt_set=0 fà un OR logico praticamente se risultano vere entranbe pone a 0 volt_set dico bene?

Oppure questa

printf(write_car_lcd,"%01ld,%03ldA SET %02ld,%01ldV",amp_set/disp_a,amp_set*disp_ma,volt_set/40,volt_set/4);

Qui apparte la chiamata della funzione per scrivere nel display non riesco a capire altro.

Insomma non capisco le operazioni compreso la lettura ADC e impostazione PWM.

Grazie

Link al commento
Condividi su altri siti

Solo a metà. E' un'operazione di OR, quindi è sufficiente che una sola delle due condizioni sia vera per porre l'uscita a zero.

Qui è questione di logica boolena il linguaggio non c'entra.

Qui c'è poco da spiegare; bisogna conoscere come funziona la funzione "printf" del "C".

Per spiegarla completamente, di solito è necessario un capitolo di un manuale. wink.gif

Link al commento
Condividi su altri siti

  • 4 weeks later...

Ciao a tutti!

Scusate ma non riesco a capire questa:

printf(write_car_lcd,"%01ld,%03ldA SET %02ld,%01ldV",amp_set/disp_a,amp_set*disp_ma,volt_set/40,volt_set/4);
Praticamente fà le conversioni per visualizzarle sul display, e dopo? Ad esempio nella variabile volt_set e amp_set che valore c'è considerando le variabili disp_a=125 disp_ma=8 e amp_set=50 e volt_set=40?
setup_timer_2(t2_div_by_16,255,1);
setup_ccp1(CCP_PWM_PLUS_3);
setup_ccp2(CCP_PWM_PLUS_3);

Anche in quezte due linee iniziali non riesco a capire,

Un aiutino?

Grazie

worthy.gif

Link al commento
Condividi su altri siti

Vale sempre la mia precedente risposta. Ti prendi un manuale come il Ritchie & Kernighan, che ogni programmatore in "C" dovrebbe aver letto almeno una volta, e ti studi bene come funziona la "ptintf" (sono almeno una decina di pagine).

Sono direttive al preprocessore, specifiche per il micro che stai usando. Devi leggere il manuale del compilatore che stai usando. Se usi CCS basta leggere l'help in linea.

Link al commento
Condividi su altri siti

Continuo a non capire, nonostante abbia già detto che non programmeró in c, mi viene suggerito di studiarlo ora addirittura di spendere soldi per comprare un manuale?!?

Allora non vedo l'utilità di questo forum e soprattutto la mia registrazione.......

Grazie comunque

Link al commento
Condividi su altri siti

Fulvio Persano

Ciao.

surveyor+19/03/2011, 18:52--> (surveyor @ 19/03/2011, 18:52)

Mah. rolleyes.gif

Preferisco non commentare ciò che hai scritto. Credimi, per educazione. Solo per educazione.

La Rete, offre innumerevoli possibilità per ciò che cerchi.

Basta un clik.

smile.gif

Link al commento
Condividi su altri siti

Che tu continui a non capire è chiaro.

Non si può spiegare una terzina della DIvina Commedia ad una persona che non conosce l'italiano.

Quindi o ti studi il "C" o continuerai a non capire.

La comunità del forum non può fare il alvoro al posto tuo, può consigliarti e aiutarti, ma tu devi fare la tua parte.

Anch'io non aggiungo altro solo per gentilezza ed educazione.

Modificato: da Livio Orsini
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...