0- 15 seconds counter using 16f877a

Discussion about projects that used PIC Microcontroller, Hardware Interface, Programming Algorithm and etc......

0- 15 seconds counter using 16f877a

Postby Kromuald13 » Thu Oct 27, 2011 1:23 pm

Hi ,
i am romuald ,and i am kinda new when it comes to pic programming ..
humm, actually i a writing here , to require your help for a program i have written . actually the program is a 0-15 counter using timer interrupt and TMR0 . i want the system to count from 0 to 15 seconds ..
For this i use a pic16f877a , at 20MHz
but for the program i am using the internal frequency of 4MHz
here below is the program , i have written . it compiles successful , but when i go for simulation at Pic simulator or Proteus . i have nothing .. and i am sure my simulation software work properly because ,i had already used them for other pic project successfully .
i am afraid i am missing something in my programs
code :
CODE: SELECT_ALL_CODE
#include<pic.h>
__CONFIG (0x3F32);

#define lcd        PORTC
#define rs         RB4
#define e          RB5


unsigned char int_counter = 0;
unsigned char counter = 0;
unsigned char data ;


// =============================Prototypes===========================
//===================================================================

void lcd_goto(unsigned char data);
void send_config(unsigned char data);
void send_char(unsigned char data);
void e_pulse(void);
void lcd_clr(void);
void send_string(const char *s);
void dis_num(unsigned long data);
void delay(unsigned long data);

//=====================================================================
//=====================================================================




 void main()
 {
    ADCON1=0b00000110;
    TRISA=0b11111111;   
   TRISB=0b00000000;
    TRISC=0b00000000;

    PORTA =0;
    PORTB=0;
   OPTION_REG = 0b00000111;
   INTCON = 0b10100000;
   TMR0=0x00;
   while(1)
  {
    PORTC=0;
   PORTD=0;
   
   send_config(0b00001001);   //clear display at lcd
   send_config(0b00000010);   //Lcd Return to home
   send_config(0b00000110);   //entry mode-cursor increase 1
   send_config(0b00001100);   //diplay on, cursor off and cursor blink off
   send_config(0b00111000);   //function

  // void interrupt()
   //{
    if (INTCON == 0b10100100)
        { int_counter++;
          if(int_counter==61)
            { counter ++;
              lcd_clr();
              lcd_goto(0);
              send_string(" Confirm ?");
              delay(5000);
              lcd_goto(23);
              dis_num( counter);
              int_counter = 0 ;
              delay(5000);
            }
        }
     INTCON = 0b10100000;
              
//   }
}
}


//========================================================================================
//   LCD   functions
//========================================================================================
void send_config(unsigned char data)
{
   rs=0;                        //clear rs into config mode
   lcd = data;
   delay(10);// before 50000
   e_pulse();
}

void send_char(unsigned char data)
{
   rs=1;                        //set rs into write mode
   lcd =data;                  
   delay(50);// before 50000
   e_pulse();
}

void e_pulse(void)
{
   e=1;
   delay(10);
   e=0;
   delay(10);
}

void lcd_goto(unsigned char data)
{
    if(data<16)
   {
       send_config(0x80+data);
   }
   else
   {
       data=data-20;
      send_config(0xc0+data);
   }
}

void lcd_clr(void)
{
    send_config(0x01);
   delay(600);   
}

void send_string(const char *s)
{         
   //unsigned char i=0; ( the comments bars weren't ther before .
     while (s && *s)send_char (*s++);

}


void dis_num(unsigned long data)
{
   unsigned char hundred_thousand;
   unsigned char ten_thousand;
   unsigned char thousand;
   unsigned char hundred;
   unsigned char tenth;

   hundred_thousand = data/100000;               
   data = data % 100000;
   ten_thousand = data/10000;
   data = data % 10000;
   thousand = data / 1000;
   data = data % 1000;
   hundred = data / 100;
   data = data % 100;
   tenth = data / 10;
   data = data % 10;

   if(hundred_thousand>0)
   {
      send_char(hundred_thousand + 0x30);   //0x30 added to become ASCII code
      send_char(ten_thousand + 0x30);
      send_char(thousand + 0x30);
      send_char(hundred + 0x30);
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }

   else if(ten_thousand>0)
   {
      send_char(ten_thousand + 0x30);   //0x30 added to become ASCII code
      send_char(thousand + 0x30);
      send_char(hundred + 0x30);
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }
   else if(thousand>0)
   {
       send_char(thousand + 0x30);   //0x30 added to become ASCII code
      send_char(hundred + 0x30);
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }
   else if(hundred>0)
   {
       send_char(hundred + 0x30);   //0x30 added to become ASCII code
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }
   else if(tenth>0)
    {
      send_char(tenth + 0x30);   //0x30 added to become ASCII code
      send_char(data + 0x30);
   }
   else send_char(data + 0x30);   //0x30 added to become ASCII code
}



//===============================================================================================
//   General Purpose   function
//===============================================================================================

void delay(unsigned long data)
{
   for( ;data>0;data-=1);
}
Kromuald13
Novice
 
Posts: 26
Joined: Wed Feb 09, 2011 2:03 am

Re: 0- 15 seconds counter using 16f877a

Postby Brian Griffin » Thu Oct 27, 2011 2:46 pm

I would suggest a simple pseudocode for you, something like:

CODE: SELECT_ALL_CODE

// Turn on and enable interrupts here in main function.
// Clear interrupt flags here too.

...

void Timer0Delay()
{
   // start timer0 here.
   // reload TMR0H and TMR0L values here.
   while(INTCON.TMR0IF == 0);
  // clear interrupt flag here.
  // inside here do something quick, like "counter++"...
}



or, put the interrupt handling routines outside, like:

CODE: SELECT_ALL_CODE

main()
{
   // Enable interrupts and turn them on.
   // other things like LCD routines go here.
   while(1)
   {
       // other code goes here.
   }   
}

void interrupt()          // check compiler manual for a correct implementation of interrupt based routines!
{
    if(INTCON.TMR0IF)
    {
       // clear interrupt flag here.
       // do something quickly.
       // for your example:
       // if (counter > ____ )
       // {
       //     counter = 0;
       //     stop timer or any other thing goes there;
       // }
       // else
       //      counter++;
       // reload TMR0H and TMR0L values here too.
     }
}
PIC - UIC00B from Cytron (replacement for my broken PICKit 2), Pickit 3, MikroC for PIC
dsPIC - MikroC for dsPIC, mikromedia board (dsPIC33)
AVR - AVR Dragon
Parallax - Prop tool
User avatar
Brian Griffin
Enthusiast
 
Posts: 403
Joined: Mon Jan 17, 2011 9:36 am

Re: 0- 15 seconds counter using 16f877a

Postby Kromuald13 » Fri Oct 28, 2011 5:44 pm

Hello Brian Griffin ,
thank you for your reply , but i am like can't get what your are proposing me as solution , can you have it as a code pls ...
Kromuald13
Novice
 
Posts: 26
Joined: Wed Feb 09, 2011 2:03 am

Re: 0- 15 seconds counter using 16f877a

Postby Kromuald13 » Fri Oct 28, 2011 6:53 pm

Hey brian , i have tried to write the program , the way you advise me to do . i keep trying but can't get anything , i doesn't even compile , this error keeps coming out :
CODE: SELECT_ALL_CODE
Error   [285] C:\Desktop\MPLAB projects\counter1.c; 31.17 no identifier in declaration
Error   [285] C:\Desktop\MPLAB projects\counter1.c; 64.16 no identifier in declaration

********** Build failed! **********
Please help , getting desperate...
 
here below is my code:
#include<pic.h>
#include <htc.h>
#include <pic16f877a.h>

__CONFIG (0x3F32);
/*xtal freq for ms and us delays : __delay_ms(5) */

//#define _XTAL_FREQ 4000000

#define lcd        PORTC
#define rs         RB4
#define e          RB5


unsigned char int_counter = 0;
unsigned char counter = 0;
unsigned char data ;


// =============================Prototypes===========================
//===================================================================

void lcd_goto(unsigned char data);
void send_config(unsigned char data);
void send_char(unsigned char data);
void e_pulse(void);
void lcd_clr(void);
void send_string(const char *s);
void dis_num(unsigned long data);
void delay(unsigned long data);
void interrupt();

//=====================================================================
//=====================================================================




 void main()
 {
   ADCON1=0b00000110;
    TRISA=0b11111111;   
   TRISB=0b00000000;
    TRISC=0b00000000;

    PORTA =0;
    PORTB=0;
    PORTC=0;
   PORTD=0;

   OPTION_REG = 0b00000111;
   INTCON = 0b10100000;
   TMR0=0x00;
    send_config(0b00001001);   //clear display at lcd
   send_config(0b00000010);   //Lcd Return to home
   send_config(0b00000110);   //entry mode-cursor increase 1
   send_config(0b00001100);   //diplay on, cursor off and cursor blink off
   send_config(0b00111000);   //function

   while(1)
  {
    int_counter = 0;
    counter =0;
    interrupt(void);
    counter++;
   // PORTB=PORTB+1;
    delay(5000);
    lcd_clr();
    lcd_goto(0);
    send_string(" Confirm..");
    lcd_goto(23);
    dis_num(counter);
    delay(5000);
    }
    }
   
   
   
   
   
    /========================================================================================
//   LCD   functions
//========================================================================================
void send_config(unsigned char data)
{
   rs=0;                        //clear rs into config mode
   lcd = data;
   delay(500);// before 50000
   e_pulse();
}

void send_char(unsigned char data)
{
   rs=1;                        //set rs into write mode
   lcd =data;                  
   delay(500);// before 50000
   e_pulse();
}

void e_pulse(void)
{
   e=1;
   delay(500);// before50000
   e=0;
   delay(500); // before 50000
}

void lcd_goto(unsigned char data)
{
    if(data<16)
   {
       send_config(0x80+data);
   }
   else
   {
       data=data-20;
      send_config(0xc0+data);
   }
}

void lcd_clr(void)
{
    send_config(0x01);
   delay(600);   //before 60000
}

void send_string(const char *s)
{         
   //unsigned char i=0; ( the comments bars weren't ther before .
     while (s && *s)send_char (*s++);

}


void dis_num(unsigned long data)
{
   unsigned char hundred_thousand;
   unsigned char ten_thousand;
   unsigned char thousand;
   unsigned char hundred;
   unsigned char tenth;

   hundred_thousand = data/100000;               
   data = data % 100000;
   ten_thousand = data/10000;
   data = data % 10000;
   thousand = data / 1000;
   data = data % 1000;
   hundred = data / 100;
   data = data % 100;
   tenth = data / 10;
   data = data % 10;

   if(hundred_thousand>0)
   {
      send_char(hundred_thousand + 0x30);   //0x30 added to become ASCII code
      send_char(ten_thousand + 0x30);
      send_char(thousand + 0x30);
      send_char(hundred + 0x30);
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }

   else if(ten_thousand>0)
   {
      send_char(ten_thousand + 0x30);   //0x30 added to become ASCII code
      send_char(thousand + 0x30);
      send_char(hundred + 0x30);
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }
   else if(thousand>0)
   {
       send_char(thousand + 0x30);   //0x30 added to become ASCII code
      send_char(hundred + 0x30);
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }
   else if(hundred>0)
   {
       send_char(hundred + 0x30);   //0x30 added to become ASCII code
      send_char(tenth + 0x30);
      send_char(data + 0x30);
   }
   else if(tenth>0)
    {
      send_char(tenth + 0x30);   //0x30 added to become ASCII code
      send_char(data + 0x30);
   }
   else send_char(data + 0x30);   //0x30 added to become ASCII code
}



//===============================================================================================
//   General Purpose   function
//===============================================================================================

void delay(unsigned long data)
{
   for( ;data>0;data-=1);
}

void interrupt()
{
   while(int_counter!=62)
   {
      if(INTCON==0b10100100)
         {
            int_counter++;
            delay(5000);
            INTCON=0b101000000;
            TMR0 =0x00;
   }
}            }
Kromuald13
Novice
 
Posts: 26
Joined: Wed Feb 09, 2011 2:03 am

Re: 0- 15 seconds counter using 16f877a

Postby Brian Griffin » Fri Oct 28, 2011 8:06 pm

Do not put delays in interrupts. It renders the program almost useless. Interrupts must be quick and instant.

Fix it to something like this:

CODE: SELECT_ALL_CODE
void interrupt()
{
if(INTCON==0b10100100)
{
int_counter++;
if (int_counter == 62)
   // do something here
INTCON=0b101000000;
TMR0 =0x00;
}
}


Also, have you calculated the TMR0 values before? For the program, how many microseconds for the next Timer0 interrupt?
PIC - UIC00B from Cytron (replacement for my broken PICKit 2), Pickit 3, MikroC for PIC
dsPIC - MikroC for dsPIC, mikromedia board (dsPIC33)
AVR - AVR Dragon
Parallax - Prop tool
User avatar
Brian Griffin
Enthusiast
 
Posts: 403
Joined: Mon Jan 17, 2011 9:36 am

Re: 0- 15 seconds counter using 16f877a

Postby robosang » Fri Oct 28, 2011 9:36 pm

Brian Griffin WROTE:Also, have you calculated the TMR0 values before? For the program, how many microseconds for the next Timer0 interrupt?

Hey, brian, when you give sample code, they never do calculation :mrgreen:

BTW, good example there.
robosang
Expert
 
Posts: 1239
Joined: Wed Jun 10, 2009 5:37 pm

Re: 0- 15 seconds counter using 16f877a

Postby Brian Griffin » Fri Oct 28, 2011 9:42 pm

robosang WROTE:
Brian Griffin WROTE:Also, have you calculated the TMR0 values before? For the program, how many microseconds for the next Timer0 interrupt?

Hey, brian, when you give sample code, they never do calculation :mrgreen:

BTW, good example there.


If I plonk down the sample code in front, there are very high chances people won't learn immediately.

If I give a code-fragment, there will be more chances for people to understand.

I learned it the hard way, I have a scientific calculator on the desk when I program microcontrollers. No one in my uni had to explain everything to me, so I have to read up a lot. :mrgreen:
PIC - UIC00B from Cytron (replacement for my broken PICKit 2), Pickit 3, MikroC for PIC
dsPIC - MikroC for dsPIC, mikromedia board (dsPIC33)
AVR - AVR Dragon
Parallax - Prop tool
User avatar
Brian Griffin
Enthusiast
 
Posts: 403
Joined: Mon Jan 17, 2011 9:36 am

Re: 0- 15 seconds counter using 16f877a

Postby Kromuald13 » Sat Oct 29, 2011 2:31 am

robosang WROTE:
Brian Griffin WROTE:Also, have you calculated the TMR0 values before? For the program, how many microseconds for the next Timer0 interrupt?

Hey, brian, when you give sample code, they never do calculation :mrgreen:

BTW, good example there.


Hey Brian , thx for your reply ,
concerning your question i am kinda perplexed , in fact, what i did is that , i set a value of TMR0 then i found the number of time (int_count) the Timer interrupt has to go off to produce a certain delay . For this purpose i always has to set the prescaler. In this case i set the prescaler at 256 , TMRO at 0 , and i found that int_count = 61 for Fout = 1Hz
That is the Timer0 interrupt will have to goes off 61 times , in order to create a delay of 1Second
the formula i used is as follow

Fclk
Fout = ---------------------------------------------
prescaler (256-TMRO)x (int_count)

Thank for ur assistance ....
Kromuald13
Novice
 
Posts: 26
Joined: Wed Feb 09, 2011 2:03 am

Re: 0- 15 seconds counter using 16f877a

Postby Kromuald13 » Sat Oct 29, 2011 3:31 am

Hello brian , i was able to find the mistake of the program, it was certainly due to the fact that i used the word "interrupt" it was certainly conflicting with something in the pic configuration.
thanx again

humm , now ,
when i got to Proteus , it does not simulate properly , but instead , i am having , sth like this

" stack overflows excecuting call function
stack underflos excecuting return function "

From what i got from my readings, this prove the interrupt is working , but i can't get to dispaly the countdown on the lcd don't know now ... :?
Kromuald13
Novice
 
Posts: 26
Joined: Wed Feb 09, 2011 2:03 am

Re: 0- 15 seconds counter using 16f877a

Postby Brian Griffin » Sat Oct 29, 2011 10:10 am

Do not depend too much on the simulation. Interrupts are not simulated properly in software. Things can be wrongly simulated and this may produce even more misleading results. Test them on that chip.

For the Timer0, did you set it to 16-bit? All set up at the start? Double check the values.

If you want a one second interrupt from Timer0, you may need to double check the TMR0H and TMR0L values. The int_count variable is not probably neccessary at the first place.

Get a pencil and a paper and calculate this again, and come back to us if you have problems calculating it. :)

Hint: [ (Oscillator Freq.) / 4 ] / Prescaler = Timer0 Frequency.
PIC - UIC00B from Cytron (replacement for my broken PICKit 2), Pickit 3, MikroC for PIC
dsPIC - MikroC for dsPIC, mikromedia board (dsPIC33)
AVR - AVR Dragon
Parallax - Prop tool
User avatar
Brian Griffin
Enthusiast
 
Posts: 403
Joined: Mon Jan 17, 2011 9:36 am

Next

Return to PIC Microcontroller

Who is online

Users browsing this forum: No registered users and 2 guests

cron