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 CCS Technical Support

Need logical help for Seven segment display
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

Need logical help for Seven segment display
PostPosted: Thu Sep 26, 2013 2:00 am     Reply with quote

Hi,
I'm using PIC18F2520, Oscillator: Internal 1Mhz,

I'm designing a low power seven segment display(SSD) where i can feed current only about 1.5mA. Using POV technique, i'm displaying a number on the display. i.e, switching 'a' segment, some delay, switching 'b' segment, delay, goes on.... below is the sample code:

Not displaying '0' in the SSD,
Code:

#include "18F2520.h"
#include "f2520_regs.h"
#fuses INTRC
#use delay(clock=1000000)

const char DIGIT_ZERO[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11101110,         //   d
                        0b11011110,         //   e
                        0b10111110,         //   f
                        0b11111110         //   g
                     };      

unsigned int16 value = 0, temp_value = 0, value1 = 0, count = 0, segment = 0;
unsigned int16 temp_variable = 0;
unsigned int16 digit_variable = 0;
unsigned int16  i = 0;
unsigned int16 increment = 0, DIGIT_VALUE = 0;
int1 interrupt_flag = 1;

#INT_TIMER1
void timer1_isr()
{
   if(TMR1IF == 1)
   {
      interrupt_flag = 0;

      if(count > 6)
      {
         count = 0;
      }

      TMR1IF = 0;
      TMR1IE = 1;
      TMR1H = 0xFF;   // 100us for 1Mhz
      TMR1L = 0xE6;
   }
}   


void main()
{
   TRISA = 0b00000000;
   TRISB = 0b00000000;
   T1CON = 0b10000000;
   TMR1H = 0xFF;   // 100us for 1Mhz
   TMR1L = 0xE6;   
   TMR1ON = 1;

   TMR1IF = 0;
   TMR1IE = 1;

   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   
   count=0;

   INCREMENT = 0;
   DIGIT_VALUE = 0;

   while(1)
   {   
      if(interrupt_flag == 0)
      {

         value1 = (0b00000001 << INCREMENT);      
         PORTA = value1;                  // Digit ON
   
         if(DIGIT_VALUE == 0)
         {
            temp_value = (DIGIT_ZERO[count] >> 1);
            value = temp_value | 0b00000000;
            PORTB = value;                  // segment ON
         }
         
         interrupt_flag = 1;
      }
   }
}


When i change the program as below, it displays 0 in SSD.
Code:
#INT_TIMER1
void timer1_isr()
{
   if(TMR1IF == 1)
   {
      count++;
      if(count > 6)
      {
         count = 0;
      }
         value1 = (0b00000001 << INCREMENT);
         PORTA = value1;   
   
         if(DIGIT_VALUE == 0)
         {
            temp_value = (DIGIT_ZERO[count] >> 1);
            value = temp_value | 0b00000000;
            PORTB = value;   
         }
      TMR1IF = 0;
      TMR1IE = 1;
      TMR1H = 0xFF;   // 100us for 1Mhz
      TMR1L = 0xE6;
   }
}

Why the program doesn't execute the code in while loop?
Please help
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 2:10 pm     Reply with quote

Your interrupt rate is too high, compared to your PIC's instruction cycle
speed. You said you have the Timer1 isr set to run every 100 usec.
But with your very low PIC oscillator speed of 1 MHz, an instruction cycle
is 4 usec. So you have the Timer1 isr running every 25 instruction cycles.
100 usec / 4 usec per instr. cycle = 25 instr. cycles.

But, the Timer1 isr does not get executed instantly. Always remember
this. There is a overhead cost to get in and out of the isr. With just one
isr running, the overhead is about 50 instruction cycles. The program
has to "save the state of the machine" before it enters the isr, and the
it has to restore it when it exits the isr. That takes 50 instruction cycles.

Because you have Timer1 set to overflow after 25 instruction cycles, and
it takes 50 for the overhead alone (not counting user code inside the isr),
what this means is that as soon as the PIC exits the isr, another new
Timer1 interrupt is already waiting and is triggered right away. You're back
in the isr again almost instantly. And this happens continuously. There
is almost no time available to run your main code. The processor is tied
up running the isr over and over again. Your main code (the while loop)
will execute very slowly.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 11:54 pm     Reply with quote

Great help PCM programmer ... I have changed the isr to execute from 100us to 1ms. Now it displays '0' in the SSD.
Thank you very much.

If possible, can you please post any reference documents about how to calculate instruction cycle.

I'll work on my project and if i'm stuck at any portion, ill post the problem here rather than creating a new thread.

Thank you once again.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Fri Sep 27, 2013 1:51 am     Reply with quote

How to configure PORT A - pin RA4, pin RA6, RA7 as digital output?
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Fri Sep 27, 2013 2:32 am     Reply with quote

hemnath wrote:
How to configure PORT A - pin RA4, pin RA6, RA7 as digital output?


You know that surely? Otherwise you wouldn't have included TRISA = 0b00000000;

...But that is not how it is is it? You don't yet understand I/O direction setting and just included the TRISA = 0b00000000; because you saw it somewhere, or someone told you to put it in, which you did, but without understanding why, or what it actually does.

In the same way, you've got timer interrupt flag bit setting in your ISR. Do you understand what that does too? I doubt it.

In fact ALL of the tris and bit setting stuff in your code is either not needed, is redundant or, in the ISR, and much worse, causes real problems.

CCS C normally doesn't need the user to do any tris setting, the compiler will handle that for you. Also you don't need to do any interrupt flag/enable setting, the compiler will do all that for you. All you need is the enable_interrupts(INT_XXXX); for each individual interrupt source followed by enable_interrupts(GLOBAL); to enable interrupts. You've got these, which is good, but only after your bit setting stuff has already enabled timer1 interrupt!

Look at the CCS manual. Learn how it, by default, automatically sets IO direction for you. Massive hint: IO bits are input by default, they are set to output the first time you try to output to them.
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Fri Sep 27, 2013 2:46 am     Reply with quote

It's the 'trying to write assembler in C' style of programming.....

There are so many things:

setup_adc_ports(ALL_ANALOGS);

replaces all the ANSEL stuff.

set_timer_1(value);

replaces the TMR1H/L stuff, etc. etc.

What's posted could be done in less than ten lines, and done better (more likely to actually work...).

However major 'thinking' problems like the interrupt rate, are the other killers...

Best Wishes
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Fri Sep 27, 2013 9:25 pm     Reply with quote

Hi RF developer,
Thanks for your suggestion.

Yes i know why tris bit settings are used. Actually my problem is, when i configure TRISA = 0b00000000; ... pins - RA4, RA6 are not set as digital output. That's my problem. setting tris bit as 0 for output, 1 - input. Am i right?

@Ttelmah:
I will try to change my code as you suggested and post the results soon. Thank you so much.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 27, 2013 10:40 pm     Reply with quote

Quote:

How to configure PORT A - pin RA4, pin RA6, RA7 as digital output?

#fuses INTRC

Look at the programs posted on this board. You will rarely, if ever, see
this fuse used.

The correct fuse is INTRC_IO. It makes the crystal oscillator pins into
normal i/o pins. This should fix RA6 and RA7.

With regard to RA4, tell us how you are testing this problem. How do you
know that RA4 isn't working as a digital i/o pin ? Make a small test
program and put an LED (with series resistor) on pin RA4 and try to
make it blink.

Also, what is your CCS compiler version ?

------------
Edit: Fixed a typo


Last edited by PCM programmer on Sun Sep 29, 2013 10:46 pm; edited 1 time in total
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Sun Sep 29, 2013 10:43 pm     Reply with quote

Thanks PCM programmer.
I have changed the fuses to INTRC_IO. Now it is working properly.

my compiler version is 4.114. I'm testing on the hardware.

I have another doubt. I have connected a button to PIN_B0. and B4-B7 to SSD for digit drive.

sample code:

Code:


int1 DIGIT_FLAG = 1;
int1 UP_FLAG = 1;

#INT_EXT
void ext_interrupt_isr()
{
   DIGIT_FLAG = 0;
//   clear_interrupt(INT_EXT);
}

#INT_EXT1
void ext_interrupt_isr1()
{
   UP_FLAG = 0;
//   clear_interrupt(INT_EXT1);
}

void main
{
   ext_int_edge(H_TO_L);     
   enable_interrupts(INT_EXT);

   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT1);

   #priority TIMER1, EXT, EXT1

   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

        while(1)
        {

      value1 = (0b00010000 << INCREMENT);
      output_b(value1);
               if(DIGIT_FLAG == 0)
              {
                     DIGIT_FLAG = 1;
                     // do something
              }
        }
}


When i press the button, DIGIT_FLAG should set as zero and testing a loop in 'while loop'. But nothing happening when i press the button. I know where the logic is wrong. In the line, output_b(value1), i have set pin_b0 as zero which makes the pin permanently low. am i right?

how to use pin B0 as external interrupt and send some other data to output_b() without affecting the PIN B0.

Please help.
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Mon Sep 30, 2013 8:45 am     Reply with quote

Ok.
This is the 'downside' of the default port behaviour.

Basically in CCS, in default mode, if you perform 'output_b', then the whole of port B gets set as an output, which would override the input behaviour wanted for INT_EXT, and INT_EXT1.

There are three basic ways to use the ports in CCS.

1) standard_io. Easy, works 99% of the time. Means you don't have to do anything with TRIS.
2) fast_io. This makes the compiler work like assembler, with the compiler not doing any control of the TRIS, and you having to do it all.
3) fixed_io. Behaves like standard_io, but _you_ specify once what you want the pins to do, and the compiler listens to this.

So if you add the statement:

#use fixed_io(b_outputs=PIN_B4,PIN_B5,PIN_B6,PIN_B7)

near the top of your code (below the processor defines and clock, but before any code), B0, to B3, will be set as inputs, while B4 to B7 will be set as outputs, and this setting will remain in force, allowing the interrupts to work.

Best Wishes
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Mon Sep 30, 2013 10:17 pm     Reply with quote

Thanks Ttlemah.

#use fixed_io(b_outputs=PIN_B4,PIN_B5,PIN_B6,PIN_B7)

After using this line in the code, i can use external interrupts and also sending output data to port b.

Thank you very much. Smile
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Wed Nov 20, 2013 4:45 am     Reply with quote

when i start to display all 4 digits, LED's are blinking.
Present isr routine takesplace for every 1 ms

I have reduced it to 500us to reduce the blinking action of LEDs. But the problem remains the same.

Do i have to increase the crystal frequency?

Thanks.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Nov 20, 2013 6:49 am     Reply with quote

You should post your complete program for us as you've probably made several changes.
It's impossible to tell you why 'blinks'.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Wed Nov 20, 2013 9:36 pm     Reply with quote

segments connected to PORT A. Digits connected to PORT B4 to B7.
Complete code:
Code:
#include "18F2520.h"
#fuses INTRC_IO
#use delay(clock=1000000)

#use fixed_io(b_outputs=PIN_B4,PIN_B5,PIN_B6,PIN_B7)
 
const char DIGIT_ZERO[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11101110,         //   d
                        0b11011110,         //   e
                        0b10111110,         //   f
                        0b11111110         //   g
                     };     

const char DIGIT_ONE[] =    {
                     //     gfedcba

                        0b11111110,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11111110,         //   d
                        0b11111110,         //   e
                        0b11111110,         //   f
                        0b11111110         //   g
                     };                           

const char DIGIT_TWO[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11111110,         //   c
                        0b11101110,         //   d
                        0b11011110,         //   e
                        0b11111110,         //   f
                        0b01111110         //   g
                     };   

const char DIGIT_THREE[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11101110,         //   d
                        0b11111110,         //   e
                        0b11111110,         //   f
                        0b01111110         //   g
                     };

const char DIGIT_FOUR[] =    {
                     //     gfedcba

                        0b11111110,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11111110,         //   d
                        0b11111110,         //   e
                        0b10111110,         //   f
                        0b01111110         //   g
                     };

const char DIGIT_FIVE[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111110,         //   b
                        0b11110110,         //   c
                        0b11101110,         //   d
                        0b1111110,         //   e
                        0b10111110,         //   f
                        0b01111110         //   g
                     };

const char DIGIT_SIX[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111110,         //   b
                        0b11110110,         //   c
                        0b11101110,         //   d
                        0b11011110,         //   e
                        0b10111110,         //   f
                        0b01111110         //   g
                     };

const char DIGIT_SEVEN[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11111110,         //   d
                        0b11111110,         //   e
                        0b11111110,         //   f
                        0b11111110         //   g
                     };

const char DIGIT_EIGHT[] =    {
                     //     gfedcba
                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11101110,         //   d
                        0b11011110,         //   e
                        0b10111110,         //   f
                        0b01111110         //   g
                     };

const char DIGIT_NINE[] =    {
                     //     gfedcba

                        0b11111100,       //   a
                        0b11111010,         //   b
                        0b11110110,         //   c
                        0b11111110,         //   d
                        0b11111110,         //   e
                        0b10111110,         //   f
                        0b01111110         //   g
                     };

unsigned int16 value = 0, temp_value = 0, value1 = 0, count = 0;
unsigned int16 increment = 0, DIGIT_VALUE = 0;
int1 interrupt_flag = 1;
int1 DIGIT_FLAG = 1;
int1 UP_FLAG = 1;
unsigned int disp_value1, disp_value2, disp_value3, disp_value4;
unsigned int16 DIGIT_VAL;

void display_value();
void digit(int16 DIGIT_VALUE);


#INT_TIMER1
void timer1_isr()
{
   if(interrupt_active(INT_TIMER1))
   {
      interrupt_flag = 0;
      count++;

      if(count > 6)
      {
         INCREMENT++;
         count = 0;
      }

      if(INCREMENT > 3)
      {
         INCREMENT = 0;
      }

      set_timer1(0xFF05);         // 1ms for 1Mhz
      clear_interrupt(INT_TIMER1);
   }
}   

#INT_EXT
void ext_interrupt_isr()
{
   DIGIT_FLAG = 0;
}

#INT_EXT1
void ext_interrupt_isr1()
{
   UP_FLAG = 0;
}

void main()
{
   setup_comparator(NC_NC_NC_NC);

   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   set_timer1(0xFF05);       // 1ms for 1Mhz

   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT);

   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT1);

   #priority TIMER1, EXT, EXT1

   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   
   count=0;

   INCREMENT = 0;
   DIGIT_VALUE = 0;

   while(1)
   {
        // To display 1234 in Seven segment display
      DIGIT_VAL = 1234;
      
      disp_value1 = (DIGIT_VAL%10);
      disp_value2 = ((DIGIT_VAL/10)%10);
      disp_value3 = ((DIGIT_VAL/100)%10);
      disp_value4 = ((DIGIT_VAL/1000)%10);
      
      if(interrupt_flag == 0)
      {
         if(INCREMENT == 0)
         {
            value1 = (0b00010000 << 0);      // 1st digit
            output_b(value1);            // power digit 1
            DIGIT(disp_value4);             //
         }   
         
         if(INCREMENT == 1)
         {
               value1 = (0b00010000 << 1);
               output_b(value1);
               DIGIT(disp_value3);   
         }
         
         if(INCREMENT == 2)
         {
               value1 = (0b00010000 << 2);
               output_b(value1);
               DIGIT(disp_value2);   
         }
         
         if(INCREMENT == 3)
         {
               value1 = (0b00010000 << 3);
               output_b(value1);
               DIGIT(disp_value1);   
         }
      }
   }
}


void DIGIT(int16 DIGIT_VALUE)
{
   if(DIGIT_VALUE == 0)
   {
      temp_value = (DIGIT_ZERO[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 1)
   {
      temp_value = (DIGIT_ONE[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 2)
   {
      temp_value = (DIGIT_TWO[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 3)
   {
      temp_value = (DIGIT_THREE[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 4)
   {
      temp_value = (DIGIT_FOUR[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 5)
   {
      temp_value = (DIGIT_FIVE[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 6)
   {
      temp_value = (DIGIT_SIX[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 7)
   {
      temp_value = (DIGIT_SEVEN[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 8)
   {
      temp_value = (DIGIT_EIGHT[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
   
   if(DIGIT_VALUE == 9)
   {
      temp_value = (DIGIT_NINE[count] >> 1);
      value = temp_value | 0b00000000;
      output_a(value);     
   }
}


Display is blinking. How to resolve this issue? Please help!!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Thu Nov 21, 2013 1:30 am     Reply with quote

Though 'different', using a simple 7segment display, instead of the more complex update approach you are using, look at this thread:

<http://www.ccsinfo.com/forum/viewtopic.php?t=51452>

The point made is the same.
You should be updating the segments, in your interrupt. The display wants to update at a steady rate, whatever your main code is doing.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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