|
|
View previous topic :: View next topic |
Author |
Message |
Ian Guest
|
Output confusion + timer. |
Posted: Sun Feb 19, 2006 2:11 am |
|
|
I'm having a hard time understanding why two different programs, while seemingly the same functionaly, don't actually behave the same in reality. Both programs are short tests to do the same thing: toggle two LEDs (RB0, RB1) in unison every second. The first program works, but the second doesn't.
Here's the first one:
Code: | #include "C:\PicProjects\Test\test2.h"
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
BYTE int_count; // Number of interrupts left before a second has elapsed
int1 foo;
#int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
// For this program this is apx 76 times
if(--int_count==0) { // per second.
output_toggle(PIN_B1);
foo = !foo;
int_count=INTS_PER_SECOND;
}
}
void main() {
int_count=INTS_PER_SECOND;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
foo = 1;
output_bit(PIN_B0, 1);
output_bit(PIN_B1, 1);
do {
output_bit(PIN_B0, foo);
//output_bit(PIN_B1, foo);
} while(TRUE);
} |
This one doesn't. (Both LEDs stay on.)
Code: | #include "C:\PicProjects\Test\test2.h"
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
BYTE int_count; // Number of interrupts left before a second has elapsed
int1 foo;
#int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
// For this program this is apx 76 times
if(--int_count==0) { // per second.
//output_toggle(PIN_B1);
foo = !foo;
int_count=INTS_PER_SECOND;
}
}
void main() {
int_count=INTS_PER_SECOND;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
foo = 1;
output_bit(PIN_B0, 1);
output_bit(PIN_B1, 1);
do {
output_bit(PIN_B0, foo);
output_bit(PIN_B1, foo);
} while(TRUE);
} |
Here's the content of Test2.h:
Code: | #include <16F73.h>
#device adc=8
#use delay(clock=20000000)
#fuses NOWDT,HS, NOPUT, NOPROTECT, NOBROWNOUT
|
I don't understand what's going on. They should both do the same thing, the only difference is both RB0 and RB1 are sharing the "buffer" of foo in the second example. Can anyone shed some light on this? |
|
|
Ttelmah Guest
|
|
Posted: Sun Feb 19, 2006 4:19 am |
|
|
What does happen?.
One possibility, is the 'read modify write' problem of the PIC.
When an output pin is changed, the actual values currently on all the pins are read. Then the required bit is set/reset, and the result written back to the output register.
Now, in your first example, the first pin, is set inside the interrupt handler. The code then has to return from the interrupt (which will typically involve perhaps 25 instruction times on a 16 chip), before it can arrive at the part in the 'main' loop, where the other bit is updated. In fact there are also the instructions to toggle the register, and update the counter, so a total in excess of perhaps 30 instruction times. On the second example, the two bits are updated one after the other in the main loop. There are perhaps just five instruction times, between changing one bit, and changing the other. Now if the output being driven by Pin B0, has a significant load, and especially a significant capacitance present, it may take several uSec, before the actual 'output' value, reaches the newly set level. What happens in the time between is:
Read the current value on the port.
Set B0. Output the new value to the port. B0 starts charging towards logic '1'.
Read the current value on the port. B0, has not yet reached '1', so is read as '0'. Set B1. Write this value to the port's output register. B1, now starts charging towards logic '1', but B0, now starts charging back down to logic 0'....
This is only for a single 'set' cycle, but the same may also happen on 'off' cycles. Depending on how quickly the logic levels actually charge, the outputs may change sometimes, or never...
Solutions are twofold. Either allow enough time after changing a pin, before changing another, or hold a 'dummy copy' of the value you require to output on the port, toggle the required bits in this, and output the whole value to the port each time.
Best Wishes |
|
|
Guest
|
|
Posted: Sun Feb 19, 2006 10:35 am |
|
|
Thanks for the response. I've changed the code to hold a var with what should be the port's state, so I can check that to see if any changes are required. That seems the work fine. Thanks for your help. Here's the new example for clarity:
Code: | #include "C:\PicProjects\Test\test2.h"
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
BYTE int_count; // Number of interrupts left before a second has elapsed
int8 output;
int8 buffer;
#int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
// For this program this is apx 76 times
if(--int_count==0) { // per second.
buffer ^= 0x03;
int_count=INTS_PER_SECOND;
}
}
void main() {
int_count=INTS_PER_SECOND;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
buffer = 0x03;
output = 0x00;
do {
if (output != buffer) {
output = buffer;
output_b(output);
}
} while(TRUE);
} |
|
|
|
|
|
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
|