Sari la conținut
ELFORUM - Forumul electronistilor

Invatat programare de la zero


Postări Recomandate

Daca folosesti 16F73 (uC-ul nu pare sa aiba osc intern - nu am sapat in datasheet dar e vechi contorller-ul asa ca nu cred) cu un cuartz extern de 16MHz atunci pentru un firing rate de 1ms se configureaza Timer-ul 0 asa (am folosit aplicatia Timer Calculator):

//Timer0
//Prescaler 1:16; TMR0 Preload = 6; Actual Interrupt Time : 1 ms

//Place/Copy this part in declaration section
void InitTimer0(){
  OPTION_REG = 0x83;
  TMR0 = 6;
  INTCON = 0xA0;
}

void Interrupt(){
  if (TMR0IF_bit){ 
    TMR0IF_bit = 0;
    TMR0 = 6;
    //Enter your code here
  }
}

Tradus ar fi asa:

OPTION_REG = 0x83;

Ce ne intereseaza este ca aici se face LOW bitul T0CS, ceea ce inseamna ca incrementarea Timer0 se face pe internal instruction clock (adica la Microchip este Fosc/4 adica 16MHz/4 = 4MHz).

Tot aici, se fac btii PSA2 = 0, PSA1 = 1, PSA0 = 1 adica se seteaza un prescaler de 1:16 adica Timer0 merge la 4MHz / 16 = 250KHz adica fiecare tick incrementare Timer0 are o valoare de 4 microsecunde.

 

Fiindca se face:

TMR0 = 6;

inseamna ca timerul pleaca mereu de la 6 si numara astfel pana la 255 cand apare intreruperea. Adica numara de 250 ori pana are intrerupere adica o intrerupere apare la 250 x 4microsecunde = 1000 microsecunde = 1ms.

Editat de mars01
Link spre comentariu

Cu un cuartz de 4MHz setarile pentru 16F73 (TIMER0) sunt asa:

//Timer0
//Prescaler 1:4; TMR0 Preload = 6; Actual Interrupt Time : 1 ms
 
//Place/Copy this part in declaration section
void InitTimer0(){
  OPTION_REG = 0x81;
  TMR0 = 6;
  INTCON = 0xA0;
}
 
void Interrupt(){
  if (TMR0IF_bit){ 
    TMR0IF_bit = 0;
    TMR0 = 6;
    //Enter your code here
  }
}

Te-am avertizat ca de la uC la uC se schimba lucrurile (pozitii biti in registri, registri intregi etc). Iar functionarea timer-elor depinde de frecventa la care lucreaza uC. Implicit configurarea acestora.

Link spre comentariu

PS:eu timer 0 il am pe RA4, trebuie sa leg ceva fizic de acel pin?

PS2:se mai poate folosi pinul daca timerul este pe el?

 

Citeste si tu datasheet-ul (in special sectiunea Timer0, dar tot ce tine de configurare; nu exista un "quick fix"). Scrie clar ca incrememntarea Timer0 se face ori pe instruction clock intern ori pe un clock extern primit pe RA4. Din moment ce se foloseste clock-ul intern, pinul RA4 este liber sa faca ce vrei tu.

Configurarea se face cum am scris mai sus, ma citez:

 

Ce ne intereseaza este ca aici se face LOW bitul T0CS, ceea ce inseamna ca incrementarea Timer0 se face pe internal instruction clock (adica la Microchip este Fosc/4 adica 16MHz/4 = 4MHz).

 

PS: Mi-era clar ca astepti raspuns, doar erau intrebari si am raspuns in postul curent.

Editat de mars01
Link spre comentariu

Vreau si eu cateva explicatii aici daca se poate...ma refer la diferenta dintre primele 2 randuri....

//init timer
T1CKPS1_bit = 1;
T1CKPS0_bit = 0;
TMR1ON_bit = 1; // start Timer1
TMR1IF_bit = 0; // clear Timer1 interrupt flag
TMR1H = 0x3C;
TMR1L = 0xB0;
TMR1IE_bit = 1;
PEIE_bit = 1;
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
Editat de catalin004
Link spre comentariu

Salutare...am schimbat cele necesare prin program si l-am pus in aplicatie...am creat si o functie de afisare pe display cu functiile, ma gandeam sa fac un SHIFT_LEFT pe al doilea rand , insa nu stiu daca merge pe un singur rand , am facut teste insa merge, dar pe tot ecranul...

 

O alta problema este ca nu stiu ce sa modific la timer sa fie in acelasi timp cu procesorul meu...am micsorat timpul in program doar pentru teste( ca sa nu astept atat timp sa vad cum lucreaza).

 

Inca o problema este ca in momentul in care ambele utilaje se opresc, pompa nu o mai pot porni, as fi vrut sa mai mearga aceasta activitate, intrucat dupa oprirea ei automata as fi stiut ca nu mai este apa, si de exemplu as dori apa de baut, sa o pot porni, adica functia RUN cred ca ar fi repornita dupa ce ambele sunt OFF. - momentan asta o putem lasa ultima data , nu ma intereseqaza in mod deosebit...

 

Atasez programul meu modificat...

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

//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
   Lcd_Out(1,3, "POMPA OPRITA");
   hidro = ON;                //hidrofor stare initiala on
   Lcd_Out(2,2, "HIDROFOR PORNIT");

   //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;
      TMR1H         = 0x3C;
      TMR1L         = 0xB0;
      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;
}

// 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;
  // Lcd_Out(1,3, "POMPA PORNITA");
   clrwdt();
   if (check_button() == ON)
   {
      state = RUN;

      init_timer();
      initial_time = timer_func();
   }
   else
   {
    //Lcd_Out(1,3, "POMPA  OPRITA");
   }
}

void run_func() 
{
   pompa = ON;
   clrwdt();
   // if time is less than 15'
   if ((timer_func() - initial_time) < 90) 
   {
      if (check_button() == ON) {
         state = IDLE;
      }
   }
   else {
      state = HIDRO_OFF;
     // Lcd_Out(2,2, "HIDROFOR  OPRIT");
   }
}

void hidro_off_func() 
{
   hidro = OFF;
   clrwdt();
    // if the time is less than 30'
   if ((timer_func() - initial_time) < 180)
    {
      if (check_button() == ON) 
      {
         pompa = !pompa;
      }
   }
   else pompa = OFF;
   //Lcd_Out(1,3, "POMPA  OPRITA");

   // if the time is more than 45'
   if ((timer_func() - initial_time) >= 270)
    {
      state = IDLE;
   //   Lcd_Out(1,3, "POMPA OPRITA");
  //    Lcd_Out(2,2, "HIDROFOR PORNIT");
    }
}
void display()
{
  if(hidro==ON && pompa == OFF)
  {
   Lcd_Out(1,3, "POMPA  OPRITA");
   Lcd_Out(2,2, "HIDROFOR PORNIT");
   }
   else if(hidro==ON && pompa == ON)
   {
   Lcd_Out(1,3, "POMPA PORNITA");
   Lcd_Out(2,2, "HIDROFOR PORNIT");
   }
   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_Cmd(_LCD_SHIFT_LEFT);
   Lcd_Out(2,2, "LIPSA  APA");
   }
}

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

   }

} 
Link spre comentariu

Am modificat timerul cu cel din calculatorul mikcroC, PIC16, 4Mhz, 1 Interrupt, timer 1...dar parca nu face 15 minute....

Am mai bagat si un led pe RUN, care la pupitru sa imi arate ca am pompa prnita, un fel de avertizare...

#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

//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 = 0x01;           // start Timer1
   TMR1IF_bit = 0;           // clear Timer1 interrupt flag
   TMR1H         = 0xFC;     // Clear High byte
   TMR1L         = 0x18;     // 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;
      TMR1H         = 0xFC;
      TMR1L         = 0x18;
      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;
}

// 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;
  // Lcd_Out(1,3, "POMPA PORNITA");
   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) < 9000)
   {
      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) < 18000)
    {
      if (check_button() == ON) 
      {
         pompa = !pompa;
      }
   }
   else pompa = OFF; 
    // if the time is more than 45'
   if ((timer_func() - initial_time) >= 27000)
    {
      state = IDLE;
    }
}
void display()
{
  if(hidro==ON && pompa == OFF)
  {
   Lcd_Out(1,3, "POMPA  OPRITA");
   Lcd_Out(2,2, "HIDROFOR PORNIT");
   }
   else if(hidro==ON && pompa == ON)
   {
   Lcd_Out(1,3, "POMPA PORNITA");
   Lcd_Out(2,2, "HIDROFOR PORNIT");
   }
   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 bec()
{
LED_dir = OUTPUT;
if ( pompa==ON)
     {
     LED=ON;
     delay_ms(200);
     LED=OFF;
     delay_ms(200);
     LED=ON;
     delay_ms(200);
     LED=OFF;
     delay_ms(1000);
          }
 else
     {
     LED=OFF;
     }
 }
void main()
 {
   hw_init();
   state = IDLE;
   clrwdt();

   while (1)
    {
      clrwdt();
      display();
      bec();
      switch (state)
       {
         case IDLE:
            idle_func();
            break;
         case RUN:
            run_func();
            break;
         case HIDRO_OFF:
            hidro_off_func();
            break;
      }
   }
}

Scuze acum am vazut ca s-a calculat la 100ms intreruperea, eu calculasem la 1ms...merge perfect....

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