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

Output confusion + timer.

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







Output confusion + timer.
PostPosted: Sun Feb 19, 2006 2:11 am     Reply with quote

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







PostPosted: Sun Feb 19, 2006 4:19 am     Reply with quote

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








PostPosted: Sun Feb 19, 2006 10:35 am     Reply with quote

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);
}
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