CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

7 segment flickering problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
energetic007



Joined: 10 Nov 2013
Posts: 10

View user's profile Send private message

7 segment flickering problem
PostPosted: Sun Nov 10, 2013 10:46 pm     Reply with quote

hello everyone i am a newbie ......
ccs compiler version 4.108
pic 16f877a interfacing with two 7 segment ANODE displays.
7 pins of segment connected from RD0 to RD6 on PORT-D.
Two enable pins i.e. base of bc547 transistors connected via 200 ohm resistor to PINS RB3 and RB4.
Interrupts of timer 0 to RB3 and RB4.
But the segment flickers a lot ... i am confused ....can anyone give a look to it....
Code:

#include <16f877a.h>
#fuses NOPROTECT,NOCPD,XT
#use delay(clock=4m)

const char LED_DIGIT[10]={
0b01000000, // zero
0b01111001, //one
0b00100100, //two
0b00110000, //three
0b00011001, //four
0b00010010, //five
0b00000010, //six
0b01111000, //seven
0b00000000, //eight
0b00010000}; //nine

void first()
{
output_d(LED_DIGIT[0]);
}

void sec()
{
output_d(LED_DIGIT[1]);
}

#INT_TIMER0
void isr()
{
output_toggle(PIN_B3);
delay_ms(10);
output_toggle (PIN_B4);
}

void main()
{
setup_adc(ADC_OFF);
setup_comparator(NC_NC_NC_NC);

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);

do
  {
   first();
   sec();
  }

while(1==1);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19470

View user's profile Send private message

PostPosted: Mon Nov 11, 2013 2:58 am     Reply with quote

Your approach is slightly flawed. You don't want to pulse RB3, then RB4 in the interrupt. What needs to happen is that the pattern for the first digit is sent, and RB3 turned on. _Then_ at the next interrupt, the pattern for the next digit is sent, and RB4 turned on. The pattern, and the drive must work together. Currently they are separate. So:
Code:

#include <16f877a.h>
#fuses NOPROTECT,NOCPD,XT
#use delay(clock=4m)
#include <stdlib.h>

const char LED_DIGIT[10]={
0b01000000, // zero
0b01111001, //one
0b00100100, //two
0b00110000, //three
0b00011001, //four
0b00010010, //five
0b00000010, //six
0b01111000, //seven
0b00000000, //eight
0b00010000}; //nine

int8 digits[2]={0,0};

#INT_TIMER0
void isr()
{
   static int8 digit=0;
   output_low(PIN_B3);
   output_low(PIN_B4); //ensure both drives are off before changing
   if (digit==0)
   {
      output_d(LED_DIGIT[digits[0]]);
      output_high(PIN_B3); //drive the first digit
      digit=1;
   }
   else
   {
      output_d(LED_DIGIT[digits[1]]);
      output_high(PIN_B4); //drive the second digit
      digit=0;
   }
}

void main()
{
   int8 count;
   div_t idiv;

   setup_adc(ADC_OFF);
   setup_comparator(NC_NC_NC_NC);
   output_low(PIN_B3);
   output_low(PIN_B4); //ensure both drives are off

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4; //slower
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   do
   {
       for (count=0;count<100;count++)
       {
           idic=div(count,10); //generate quotient, and remainder
           digits[0]=idiv.quot;
           digits[1]=idiv.rem;
           //put the counter value to display
           delay_ms(1000); //wait for a second displaying
       }
    }
}

I've slowed the interrupt to just 244* per second. Anything over perhaps 100* per second is fast enough, and the slower interrupt means less time wasted here.
The code sits in a loop, counting from 0 to 99, and puts this count, split into two digit values, into the array (digits[]), which is the values to be displayed, then waits for a second, and does this again for the next count.
Meanwhile the interrupt alternately displays digits[0], and digits[1], on the two display digits.
Using the fixed 'digits[0]' and 'digits[1]' in the interrupt, is quicker than having an array indexed by another array using a variable. Since there has to be a test to turn on the right drive, this is just a little more efficient.
Note the use if the div function from stdlib, which gives quotient and remainder in a single operation, so is more efficient than % and / here.

Best Wishes
energetic007



Joined: 10 Nov 2013
Posts: 10

View user's profile Send private message

flickering 7 segment
PostPosted: Mon Nov 11, 2013 8:02 am     Reply with quote

thanks a lot Ttelmah ... i don't know why< stdlib.h> is used and where should i find the contents of the header file from .
could you please make me understand its use.
Ttelmah



Joined: 11 Mar 2010
Posts: 19470

View user's profile Send private message

PostPosted: Mon Nov 11, 2013 8:35 am     Reply with quote

'stdlib', is the 'standard library'. Comes with the compiler (sits in the drivers directory). It contains lots of definitions for standard bits of C, and a few extended bit. It's where the definition of the 'idiv' data type is stored, so you can used the 'div' function. It contains all the functions for doing things like converting ASCII to integer and vice versa.

There are about ten include files like this that are 'standard' parts of C (_every_ C is required to have them). math.h, string.h. stdio.h, stdlib.h, stddef.h, stdarg.h, stdlibm.h, limits.h, float.h, errno.h, ctype.h etc..

Best Wishes
edi



Joined: 22 Dec 2003
Posts: 82

View user's profile Send private message

Making the display light for short period
PostPosted: Wed Jan 15, 2014 12:34 am     Reply with quote

Ttelmah, your code works perfect thanks.

In my project the 7 Seg should light only when the counter is change and only for short period of 2-3 sec.
I will appreciate if you suggest a proper way to turn on the 7 seg for 2-3 sec and then back off.

Thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19470

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 2:09 am     Reply with quote

Add something like a 'display_on' flag.

So:
Code:

int1 display_on=TRUE;

#INT_TIMER0
void isr()
{
   static int8 digit=0;
   output_low(PIN_B3);
   output_low(PIN_B4); //ensure both drives are off before changing
   if (display_on)
   {
      if (digit==0)
      {
         output_d(LED_DIGIT[digits[0]]);
         output_high(PIN_B3); //drive the first digit
         digit=1;
      }
      else
      {
         output_d(LED_DIGIT[digits[1]]);
         output_high(PIN_B4); //drive the second digit
         digit=0;
      }
   }
}


Then when you don't want anything displayed, set 'display_on=FALSE', and the code will stop outputting anything. When you want it displaying, set it TRUE again.

Best Wishes
edi



Joined: 22 Dec 2003
Posts: 82

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 6:33 am     Reply with quote

Thanks.
Is there an elegant way to perform the 2Sec on time?
Or just add counter that count the timer interrupts and after crossing threshold to turn the display off?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group