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

Weird problem involving timer1 and printf?

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







Weird problem involving timer1 and printf?
PostPosted: Mon Nov 15, 2004 1:59 am     Reply with quote

Hi

I have a weird bug involving counters/ timers.
In the code below the interH, and ChXH are output correctly, while interL and ChXL are output incorrectly. If I swap the two bits of code "Look for Low on ChX" and "Look for High on ChX", the output for interL and ChXL are correct now, and the other 2 are incorrect.

By changing the baud rate I can decrase or decrease the error. The error seems always to be a fixed value. I think that printf is occuring simultaneously as the first bit of code in the "while(TRUE)" loop.
I also tried to insert delay_ms(5) but that made the output of the variables out by a further 5ms.

Can someone please help me?
Thank you in advance for your help.
arrow
Code:
//-----------------------------------
#include <16F873.H>

#fuses   HS,NOPROTECT,NOWDT

#use delay(clock=19660800)
#use rs232(baud=57600, xmit=PIN_A0, rcv=PIN_A1)
//=====================nnnce=============================
int inter;
#int_timer1
void int_counter(){
   inter++;
}
//==================================================
main() {
   long int ChXH, ChXL;
   int interH, interL;
 //--------------
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
 //--------------
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
   while(TRUE){
      //-----------
      //***Look for Low on ChX
      set_timer1(0);
      inter=0;
      while(!input(PIN_C2)){

      }
      ChXL = get_timer1();
      interL = inter;
      //-----------
      //***Look for High on ChX
      set_timer1(0);
      inter=0;
      while(input(PIN_C2)){

      }
      ChXH = get_timer1();
      interH = inter;
      //-----------
      printf("H%x%x%x ",
         interH,(ChXH>>8)&0x00ff,ChXH&0x00ff
      );
      printf("L%x%x%x ",
         interL,(ChXL>>8)&0x00ff,ChXL&0x00ff
      );
   }
}
//=======================================================
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Mon Nov 15, 2004 3:08 am     Reply with quote

You are using a software generated serial port, which creates the timings for the desired baud rate artificially (unlike the hardware UART). You also have the Timer1 interrupting at full speed. In CCS, there is an interrupt overhead of about 40 instructions. It seems what is happening is that while the UART is transmitting the interrupt keeps happening and messing up the timing of the bits. The delays CCS uses to generate the correct timing will get bigger, because the length of the ISR keeps getting added to them, many times. This will cause baud rate problem which result in broken communications. Especially with a connection as fast as 57600 which is very sensitive to bit times. At this speed you easily can have a bit streched twice as long as it should be.
You either have to use the hardware UART, or slow down your interrupt, or slow down your serial port (you may need to bring it down as low as 4800bps, believe it or not. do some calculations on the bit-width, the interrupt period and the time it takes to execute the ISR+overhead).
arrow
Guest







PostPosted: Mon Nov 15, 2004 2:12 pm     Reply with quote

Hi Haplo

Thank you for your reply. I shall try the 4800 baud rate.
Also could you please tell me how to do the UART communication?
I am not sure what UART is, but I need to communicate with my PC over the RS232 port.

All the best
arrow
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Mon Nov 15, 2004 4:23 pm     Reply with quote

Change your #use RS232 statement to:

Code:
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)



This will use the hardware UART which makes RC6 your transmit pin and RC7 your receive pin. In this case all the bit timings are generated in hardware, so the Timer1 interrupt will not mess up the serial communication. Therefore you can maintain the 57600bps and don't need to bring it down.

By the way, you will also need a level converter (such as MAX232) to be able to talk to a PC.
arrow
Guest







PostPosted: Tue Nov 16, 2004 2:31 am     Reply with quote

Hi Haplo

Thank you for your post. I have tried what you say, and it does not
fix the problem!
I have written a VC++ program that reads the RS232 port, and displays
the data. Both what you suggested, and what I had before allowed the
PC to read the data (I dont seem to be able to go faster than 57600 though).
However, somewhere within the PIC code there is a problem.
Its as if printf starts executing, and instead of completing and
then going back to the while loop, the while loop starts to execute
in parallel (!?!) with the printf- is this possible?
I have noticed that the faster I printf (via baudrate), the smaller
is the timing error.
Also, global disabling the interrupts, does not change the error.

Would you know of a way to ensure that the printf finishes and then
the code goes to the beginning of the loop?

(I tried to delay_ms(5) after the printf, that did not help either).

Once again, I appreciate your help.
All the best
arrow
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Tue Nov 16, 2004 9:39 pm     Reply with quote

The other statements should not run until printf finishes...
It seems like your watchdog is resetting. Make sure the watchdog is disabled. I see you have NOWDT in the fuses, but if you use ICD with MPLAB or some other programmer aside from CCS' ICD.EXE, they will override these fuse settings. Make sure you adjust the fuse settings of the programmer as well.
And by the way, unless you are using Low Voltage Programming, make sure you always include the NOLVP fuse.
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