View previous topic :: View next topic |
Author |
Message |
KamPutty Guest
|
Advice needed...LED multiplexing...timer0 |
Posted: Tue Jan 10, 2006 10:22 am |
|
|
hi all,
Hope all is well with you.
I need some advice (what?! again?!)
- My project contains 8 7-segment LED's
- I am using a CC LED's
- I am using a picf452@4mhz
- My code can update the LEDs
<question>
Now the issue is this, I need to update the LED's "n" times a second and I was going to do this via the timer0. Running at 4mhz, that means something like only 15 times a second that the timer0 is hit. I am now thinking that I need to speed up my processor (lets say 20mhz) so I can get approx 75 times the timer0 hits per second.
Now am I going this the wrong way? (BTW, I have chosen NOT to use the 7219, for now(?)...)
All the interrupt needs to do is display/update the LED's, it does NO calculations, processing etc other then toggling the LED's...
Any advice would be greatly appriciated!
Thanks all,
~Kam (^8* |
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Tue Jan 10, 2006 10:41 am |
|
|
I am doing something similiar:
PIC16F747, internal osc. x 4 (PLL x 4) (thus 32 mhz)
4-segment LED common anode display
I use the following to setup my my timer0 isr:
Code: |
int_count = INTS_PER_SECOND;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_128 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
|
This amounts to
(4 * 128 * 256) / 32000000 = .004096 sec per interrupt
For a 4-digit led display, this 4ms refreshing seems ideal. Maybe it's okay for your 8-digit display, or maybe you'll need to do an RTCC_DIV_64.
Notice that i'm using the one of the cheapest possible PICs and not using a crystal.
FYI, my isr looks like this: ('x' goes from 0 to 3, and it marks which digit i am currently refreshing)
Code: |
#INT_RTCC
void timer0_isr(void)
{
static int x = 0;
if (!GLOBAL_inhibit_all_leds)
{
port_a = ca_io[x];
port_d = GLOBAL_character[x];
}
else
{
port_a = 0xFF; // all leds off
}
x++;
if (x == 5)
{
x = 0;
}
if (--int_count == 0)
{
++seconds;
int_count = INTS_PER_SECOND;
}
GLOBAL_led_counter++;
}
|
|
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Tue Jan 10, 2006 10:51 am |
|
|
I read your post carefully again...
Given that you are using a 4MHz crystal on the PIC18F452, and let's say you will need 2ms to strobe thru each display:
Code: |
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_8 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
|
This amounts to
(4 * 8 * 256) / 4000000 = .002048 sec per interrupt |
|
|
KamPutty Guest
|
|
Posted: Tue Jan 10, 2006 11:00 am |
|
|
Mike,
Thanks for the replay,
This is what I currently have in setup:
Code: |
set_timer0(0);
setup_counters(RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
|
Do you think you can explain the RTCC_DIV_??? arg. It just has not "clicked" in my brain.
~Kam (^8* |
|
|
KamPutty Guest
|
Success! |
Posted: Tue Jan 10, 2006 11:35 am |
|
|
Mike, et al.,
100% success! I just changed to rtcc_div_8 and viola!
Here is my isr code...
Code: |
#int_timer0
/**
* This method is the timer0 isr
*/
void timer_0_isr(void)
{
// lets turn off the current LED
pinIO(PORT_C+currentActiveLED, OFF);
// go to next LED and display
currentActiveLED++;
if(currentActiveLED>=LED_COUNT)
{
currentActiveLED=0;
}
portIO(PORT_B, LEDValues[currentActiveLED]); // Set the segments
pinIO(PORT_C+currentActiveLED, ON); // turn on digit (using Common Cathode LED's)
}
|
Thanks for the suggestions
~Kam (^8* |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
|
kam
Joined: 15 Jul 2005 Posts: 59
|
KamPutty |
Posted: Tue Jan 10, 2006 12:59 pm |
|
|
Thanks! |
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Tue Jan 10, 2006 4:07 pm |
|
|
KamPutty wrote: | Mike,
Thanks for the replay,
This is what I currently have in setup:
Code: |
set_timer0(0);
setup_counters(RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
|
Do you think you can explain the RTCC_DIV_??? arg. It just has not "clicked" in my brain.
~Kam (^8* |
Think of it this way:
(4 * X * 256) / Fosc = time between tmr overflow interrupts [seconds]
where X is the post-divider value (e.g. RTCC_DIV_256); the 256 in the 3rd term is if you're using RTCC_8_BIT,
Otherwise it should be
(4 * X * 65536) / Fosc if it's RTCC_16_BIT |
|
|
|