Sari la conținut
ELFORUM - Forumul electronistilor

Invatat programare de la zero


Postări Recomandate

Cand esti in dubii cu privire la cum sa programezi ceva in C, da un search dupa cuvintele cheie adaugand dupa ele cuvantul cheie "Arduino".

Sansele sunt foarte mari ca un Arduino-guy sa se fi izbit de problema si o solutie este deja disponibila.

 

Gen asa.

 

Solutia este ca sa introduci o variabila globala de tip LONG (cu atributul volatile in fata) care se incrementeaza in functia de intrerupere. Apoi privesti acea variabila ca si cum ar fi functia millis() in Arduino si procedezi similar ca aici.

Editat de mars01
Link spre comentariu

Am incercat sa folosesc cu timer 0...insa nu mai imi da start la pompa :tryre


#define pompa_dir TRISC.F1      //pompa pe iesirea RC1
#define pompa PORTC.F1
#define hidro_dir TRISC.F3      //hidrofor pe iesirea RC3
#define hidro PORTC.F3
#define LED_dir TRISC.F6      //hidrofor pe iesirea RC3
#define LED PORTC.F6

#define buton_dir TRISB.F0       //butonul pe intrarea RB00
#define buton PORTB.F0

#define INPUT        1;
#define OUTPUT       0;

// enumeratie anonime pentru a salva diferite stari
enum
{
   OFF = 0,
   ON  = 1
};

//enumeratie pentru salvarea starilor din FSM
typedef enum States
{
   IDLE ,
   RUN,
   HIDRO_OFF
} state_t;

state_t state;                            // variable of type state_t
volatile unsigned long timer_cnt = 0;     // variable to store time in multiples of 0.1sec
unsigned long initial_time;               // var to store the initial time
unsigned volatile long cnt=0;
//LCD setare porturi iesire
sbit LCD_RS at RC4_bit;
sbit LCD_EN at RB2_bit;
sbit LCD_D7 at RB6_bit;
sbit LCD_D6 at RB5_bit;
sbit LCD_D5 at RB4_bit;
sbit LCD_D4 at RB3_bit;
//Sfarsit LCD conect

// pini catre porturi
sbit LCD_RS_Direction at TRISC4_bit;
sbit LCD_EN_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB6_bit;
sbit LCD_D6_Direction at TRISB5_bit;
sbit LCD_D5_Direction at TRISB4_bit;
sbit LCD_D4_Direction at TRISB3_bit;
//terminare setare pentru lcd

// clear the watchdog timer
void clrwdt() {
   asm CLRWDT;
}

void hw_init(void)
{
   clrwdt();
   // make sure that the oscillator is running at 8MHz cred ca doar cu oscilator intern
   //IRCF2_bit = 1;
   //IRCF1_bit = 1;
   //IRCF0_bit = 1;

   ADON_bit = 0x00;           // disable ADC
   ADCON1 = 0xFF;             // set all ADC pins as digital

   Lcd_Init();                // Initialize LCD
   Lcd_Cmd(_LCD_CLEAR);       // Clear display
   Lcd_Cmd(_LCD_CURSOR_OFF);  // Cursor off

   pompa_dir = OUTPUT;        //pompa ca iesire
   hidro_dir = OUTPUT;        //hidro ca iesire
   buton_dir = INPUT;         //buton ca intrare

   pompa = OFF;               //pompa stare initiala off
   hidro = ON;                //hidrofor stare initiala on

   //initializare timer
   T1CKPS1_bit = 1;          //Pre-scaler 1:1
   T1CKPS0_bit = 0;
   TMR1ON_bit = 1;           // start Timer1
   TMR1IF_bit = 0;           // clear Timer1 interrupt flag
   TMR1H         = 0x3C;     // Clear High byte
   TMR1L         = 0xB0;     // Clear Low byte
   TMR1IE_bit  = 1;          // Disables Enables the TMR1 overflow interrupt
   PEIE_bit = 1;             // Enable Peripheral Interrupt
   GIE_bit = 1;              // start interrupts

  // SWDTEN_bit = 1;         // enable watchdog; the watchdog postscaler was set at 1:256 that means an reset interval of 4ms x 256 = 1024ms = 1.024sec

}

void Interrupt()
{
   // Timer1 one Interrupt rate is 100ms = 0.1s
   if (TMR1IF_bit && TMR1ON_bit)
   {
      TMR1IF_bit = 0;           // clear Timer1 interrupt flag
      TMR1H         = 0x3C;     // Clear High byte
      TMR1L         = 0xB0;     // Clear Low byte
      timer_cnt++;
   }
}

// VERIFICARE STARI BUTON
unsigned char check_button (void)
 {
   static unsigned char anterior_buton = 1; // starea initiala a butonului este OFF
   clrwdt();
   if (buton == 1) 
   {
   anterior_buton = 1;
   }
   if (buton == 0 && anterior_buton == 1)
   {
      delay_ms(200);
      if (buton == 0)
       {
         anterior_buton = 0;
         return 1;
      }
   }
   else return 0;
}

// initialize the timer_cnt variable
void init_timer() 
{
   timer_cnt = 0;
}

void InitTimer0() //initializare timer 0
{
  OPTION_REG	 = 0x81;
  TMR0		 = 6;
  INTCON	 = 0xA0;
}

void Interrupt0()
{
  if (TMR0IF_bit && pompa==ON)
  {
    TMR0IF_bit	 = 0;
    TMR0	 = 6;
    //Enter your code here
     if (cnt >= 500)
      {
      cnt=0;
      LED=!LED;
      }
      else
      {
      cnt++ ;
      }
  }
}

void bec_delay()
{
LED_dir=OUTPUT;
InitTimer0();
}

// return the timer_cnt variable value
unsigned long timer_func () 
{
   volatile unsigned long temp;           // declared as volatile so it will not be optimized
   clrwdt();                              //clear watchdog
   GIE_bit = 0;                           // disable interrupts
   temp = timer_cnt;                      // copy the value of timer variable into the shadow variable named temp
   GIE_bit = 1;                           // enable interrupts

   return timer_cnt;                      // return the timer variable
}

void idle_func ()
 {
   hidro = ON;
   pompa = OFF;
   clrwdt();
   if (check_button() == ON)
   {
      state = RUN;
      init_timer();
      initial_time = timer_func();
   }
}

void run_func() 
{
   pompa = ON;
   clrwdt();
   // if time is less than 15'
   if ((timer_func() - initial_time) < 4000)
   {
      if (check_button() == ON) 
      {
         state = IDLE;
      }
   }
   else {
      state = HIDRO_OFF;
   }
}

void hidro_off_func() 
{
   hidro = OFF;
   clrwdt();
    // if the time is less than 30'
   if ((timer_func() - initial_time) < 9000)
    {
      if (check_button() == ON) 
      {
         pompa = !pompa;
      }
   }
   else pompa = OFF; 
    // if the time is more than 45'
   if ((timer_func() - initial_time) >= 13500)
    {
      state = IDLE;
    }
}
void display()
{
  if(hidro==ON && pompa == OFF)
  {
   Lcd_Out(1,3, "POMPA  OPRITA");
   Lcd_Out(2,2, "HIDROFOR  ACTIV");
   }
   else if(hidro==ON && pompa == ON)
   {
   Lcd_Out(1,3, "POMPA PORNITA");
   Lcd_Out(2,2, "HIDROFOR  ACTIV");
   }
   else if(hidro==OFF && pompa == ON)
   {
   Lcd_Out(1,3, "POMPA PORNITA");
   Lcd_Out(2,2, "HIDROFOR  ST-BY");
   }
   else if(hidro == OFF && pompa == OFF)
   {
   Lcd_Out(1,3, "POMPA  OPRITA");
   Lcd_Out(2,2, "HIDROFOR  OPRIT");
   }
}

void main()
 {
   hw_init();
   state = IDLE;
   clrwdt();
   while (1)
    {
      clrwdt();
      display();
      bec_delay();
      switch (state)
       {
         case IDLE:
            idle_func();
            break;
         case RUN:
            run_func();
            break;
         case HIDRO_OFF:
            hidro_off_func();
            break;
      }
   }
}
Link spre comentariu

Ma grabesc asa ca scriu rapid:

 

1. Exista o singura functie apelata de intreruperi. Cuvantul cheie pentru aceasta in mikroC este interrupt() La PIC18 sunt doua (prioritati) dar e alta mancare de peste, vorba vine.

2. Cand ai mai multe timere active, cum este cazul la tine, testezi flag-urile lor in functia unica interrupt()

3. Initializarea timerelor este bine sa o pui in aceasi functie, pentru ca sunt unii biti care afecteaza pe toti. In cazul de fata in hw_init().

4. Incearca sa intelegi ce ai pus in functia InitTimer0(). Te folosesti de registri dar nu stii ce faci acolo. Foloseste alias-urile pentru biti asa cum am facut eu in hw_init() pentru Timer-ul 1.

Editat de mars01
Link spre comentariu

Pffff...imi ine sa dau cu calculatorul de pamant...ajung tot de unde am plecat...nu stiu nimic din timere....nu am nici unde sa studiez...ma mai duc peste un coleg sa vad ce zice...am cautat si pe gogu programe cu timere, dar nu prea sunt...ma refer asa detaliate


ma pot folosi din aceste exemple?

https://forum.mikroe.com/viewtopic.php?f=88&t=58169&hilit=timer0&start=15

Editat de catalin004
Link spre comentariu

Gasesti ajutor aici.

 

LE: Programul, probabil, ar trebui sa arate cam asa (se putea si mai bine dar acum nu am chef de scris mai mult - vin de la o inmormantare ...)

#define pompa_dir TRISC1_bit      //pompa pe iesirea RC1
#define pompa PORTC1_bit

#define hidro_dir TRISC3_bit      //hidrofor pe iesirea RC3
#define hidro PORTC3_bit

#define LED_dir TRISC6_bit        //hidrofor pe iesirea RC3
#define LED PORTC6_bit

#define buton_dir TRISB0_bit      //butonul pe intrarea RB00
#define buton PORTB0_bit

#define INPUT        1
#define OUTPUT       0

// enumeratie anonime pentru a salva diferite stari
enum
{
   OFF = 0,
   ON  = 1
};

//enumeratie pentru salvarea starilor din FSM
typedef enum States
{
   IDLE ,
   RUN,
   HIDRO_OFF
} state_t;

state_t state;                                // variable of type state_t
volatile unsigned long timer_cnt = 0;         // variable to store time in multiples of 0.1sec
unsigned long initial_time;                   // var to store the initial time
volatile unsigned char sec_timer_cnt = 0;     // variable to store time in multiples of 0.1sec for LED blink

//LCD setare porturi iesire
sbit LCD_RS at RC4_bit;
sbit LCD_EN at RB2_bit;
sbit LCD_D7 at RB6_bit;
sbit LCD_D6 at RB5_bit;
sbit LCD_D5 at RB4_bit;
sbit LCD_D4 at RB3_bit;
//Sfarsit LCD conect

// pini catre porturi
sbit LCD_RS_Direction at TRISC4_bit;
sbit LCD_EN_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB6_bit;
sbit LCD_D6_Direction at TRISB5_bit;
sbit LCD_D5_Direction at TRISB4_bit;
sbit LCD_D4_Direction at TRISB3_bit;
//terminare setare pentru lcd

// clear the watchdog timer
void clrwdt() {
   asm CLRWDT;
}

void hw_init(void)
{
   clrwdt();
   // make sure that the oscillator is running at 8MHz cred ca doar cu oscilator intern
   //IRCF2_bit = 1;
   //IRCF1_bit = 1;
   //IRCF0_bit = 1;

   ADON_bit = 0x00;           // disable ADC
   ADCON1 = 0xFF;             // set all ADC pins as digital

   Lcd_Init();                // Initialize LCD
   Lcd_Cmd(_LCD_CLEAR);       // Clear display
   Lcd_Cmd(_LCD_CURSOR_OFF);  // Cursor off

   pompa_dir = OUTPUT;        //pompa ca iesire
   hidro_dir = OUTPUT;        //hidro ca iesire
   buton_dir = INPUT;         //buton ca intrare
   
   LED_dir = OUTPUT;

   pompa = OFF;               //pompa stare initiala off
   hidro = ON;                //hidrofor stare initiala on

   //initializare timer
   T1CKPS1_bit = 1;          //Pre-scaler 1:1
   T1CKPS0_bit = 0;
   TMR1ON_bit = 1;           // start Timer1
   TMR1IF_bit = 0;           // clear Timer1 interrupt flag
   TMR1H         = 0x3C;     // Clear High byte
   TMR1L         = 0xB0;     // Clear Low byte
   TMR1IE_bit  = 1;          // Disables Enables the TMR1 overflow interrupt
   PEIE_bit = 1;             // Enable Peripheral Interrupt
   GIE_bit = 1;              // start interrupts

  // SWDTEN_bit = 1;         // enable watchdog; the watchdog postscaler was set at 1:256 that means an reset interval of 4ms x 256 = 1024ms = 1.024sec

}

void Interrupt()
{
   // Timer1 one Interrupt rate is 100ms = 0.1s
   if (TMR1IF_bit && TMR1ON_bit)
   {
      TMR1IF_bit = 0;           // clear Timer1 interrupt flag
      TMR1H         = 0x3C;     // Clear High byte
      TMR1L         = 0xB0;     // Clear Low byte
      
      timer_cnt++;
	  
      if (pompa == ON)
      {
	 if (sec_timer_cnt == 5)
	 {
	     sec_timer_cnt = 0;
	     LED = !LED;
	 }
	 else
	 {
	     sec_timer_cnt++;
	 }
      }
      else
      {
	 LED = OFF;
      }
   }
}

// VERIFICARE STARI BUTON
unsigned char check_button (void)
 {
   static unsigned char anterior_buton = 1; // starea initiala a butonului este OFF
   clrwdt();
   if (buton == 1) 
   {
   anterior_buton = 1;
   }
   if (buton == 0 && anterior_buton == 1)
   {
      delay_ms(200);
      if (buton == 0)
       {
         anterior_buton = 0;
         return 1;
      }
   }
   else return 0;
}

// initialize the timer_cnt variable
void init_timer() 
{
   timer_cnt = 0;
}


// return the timer_cnt variable value
unsigned long timer_func () 
{
   volatile unsigned long temp;           // declared as volatile so it will not be optimized
   clrwdt();                              // clear watchdog
   GIE_bit = 0;                           // disable interrupts
   temp = timer_cnt;                      // copy the value of timer variable into the shadow variable named temp
   GIE_bit = 1;                           // enable interrupts

   return timer_cnt;                      // return the timer variable
}

void idle_func ()
 {
   hidro = ON;
   pompa = OFF;
   clrwdt();
   if (check_button() == ON)
   {
      state = RUN;
      init_timer();
      initial_time = timer_func();
   }
}

void run_func() 
{
   pompa = ON;
   clrwdt();
   // if time is less than 15'
   if ((timer_func() - initial_time) < 4000)
   {
      if (check_button() == ON) 
      {
         state = IDLE;
      }
   }
   else {
      state = HIDRO_OFF;
   }
}

void hidro_off_func() 
{
   hidro = OFF;
   clrwdt();
    // if the time is less than 30'
   if ((timer_func() - initial_time) < 9000)
    {
      if (check_button() == ON) 
      {
         pompa = !pompa;
      }
   }
   else pompa = OFF; 
    // if the time is more than 45'
   if ((timer_func() - initial_time) >= 13500)
    {
      state = IDLE;
    }
}
void display()
{
  if(hidro==ON && pompa == OFF)
  {
   Lcd_Out(1,3, "POMPA  OPRITA");
   Lcd_Out(2,2, "HIDROFOR  ACTIV");
   }
   else if(hidro==ON && pompa == ON)
   {
   Lcd_Out(1,3, "POMPA PORNITA");
   Lcd_Out(2,2, "HIDROFOR  ACTIV");
   }
   else if(hidro==OFF && pompa == ON)
   {
   Lcd_Out(1,3, "POMPA PORNITA");
   Lcd_Out(2,2, "HIDROFOR  ST-BY");
   }
   else if(hidro == OFF && pompa == OFF)
   {
   Lcd_Out(1,3, "POMPA  OPRITA");
   Lcd_Out(2,2, "HIDROFOR  OPRIT");
   }
}

void main()
 {
   hw_init();
   state = IDLE;
   clrwdt();
   
   while (1)
    {
      clrwdt();
      display();
	  
      switch (state)
       {
         case IDLE:
            idle_func();
            break;
         case RUN:
            run_func();
            break;
         case HIDRO_OFF:
            hidro_off_func();
            break;
      }
   }
}
Editat de mars01
Link spre comentariu

Condoleante si multumiri ...Sanatate

sincer ma chiunuiam si eu , dar incepusem sa vad cum sta treaba...insa eu facusem functie, dar cred ca iar aparea delay-ul...atasez mai jos inecrcarea mea....sincer ma bucur ca depistasem ce vreti sa imi transmiteti

void bec()
{
LED_dir = OUTPUT;
if ( pompa==ON)
    {
     cnt++;
     if(cnt=200);
       {
       LED=!LED;
       cnt=0;
       }
     }
 else
     {
     LED=OFF;
     }
 }
Editat de catalin004
Link spre comentariu

Nu merge...am incercat mai multe modificari prin interupt dar imi bruiaza imaginea displayului, imi face mai multe probleme...


este ok.mai trebuia un sec_timer_cnt++; inainte de

 

if (sec_timer_cnt == 5)

{
sec_timer_cnt = 0;
LED = !LED;
}
else
{
sec_timer_cnt++;
}
}
else


Tot bruiaza display-ul...o ia razna...fara el nu face figuri

Link spre comentariu

Nu stiu ce sa iti spun decat ca dpdv al secventei introduse in functia interrupt() din codul postat de mine mai sus, nu are cum sa apara problema pe care tu o reclami.

Inreruperea apare foarte lent, o data la 100ms, nu face dacat sa incremementeze o variabila pe 8 biti, si odata la 5 iteratii face flip la pinul unde este pus LED-ul.

 

Vezi configurarile de registri.

Editat de mars01
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări