|
|
View previous topic :: View next topic |
Author |
Message |
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
Help:Code gives different results on different hardware. |
Posted: Fri Jun 25, 2010 7:31 am |
|
|
The following code give different values on supposedly identical prototype boards.
Code: |
//Calculation of execution time.
#include <16f877A.h>
#device ICD=TRUE
#fuses HS, NOLVP, NOWDT, PUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main ()
{
long time;
long a,b,c; //was int a,b,c;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("\r\n Ticks=%lu",time); //Ticks to do a=b*c
} |
The code gives a Timer1 tick value of approx 211, but may go as high as 231, for exactly the same hex files. The value differs randomly between boards, and on the same board for whatever else you can think of. We've talked to the instructior and he has no idea what the problem may be. The point is: because the same instructions are executed on each try, we should NOT get a difference. The xtal freq does NOT effect the result.
We are students in a course. We were all given the same proto boards (seen at http://www.ccsinfo.com/product_info.php?products_id=16F877Akit). The school has the CCS C Compiler V3.170b,and we use a PICKit 2 Programmer (seen here http://www.canakit.com/pic-programmer.html?gclid=CODLz8-nu6ICFSQ65QodAyHY6A). The two devices are connected via an RJ12 cable. The proto board has its own power. The Programmer is powered via the USB port. It is set NOT to power the proto board. The proto board uses a 20 MHz xtal. |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Jun 25, 2010 7:58 am |
|
|
I see 2 potential problems with your code although these do not explain the isuue you are having.
1. a = b * c;
As b and c are not assigned and a is not used after this the compiler *may* optimise this out. Check your .lst file to make sure it is doing the math.
2. I am amazed you are seeing the full output because as soon as the printf is executed the pic will go to sleep. this should prevent the last 2 chars being sent as the uart will be turned off. Put a while(true); at the end.
[*edit*]
Actually, isn't there a delay after writing to the timer before the timer is set with the correct value, that might be the 2 ticks you are subtracting and if the calculation is not being done you could be reading a random value from the timer before it has had a chance to be updated. [*edit*] I think I am talking rubish here
Last edited by Wayne_ on Fri Jun 25, 2010 8:07 am; edited 1 time in total |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Fri Jun 25, 2010 8:06 am |
|
|
Wayne_ wrote: | I see 2 potential problems with your code although these do not explain the issue you are having.
1. a = b * c;
As b and c are not assigned and a is not used after this the compiler *may* optimise this out. Check your .lst file to make sure it is doing the math.
2. I am amazed you are seeing the full output because as soon as the printf is executed the pic will go to sleep. this should prevent the last 2 chars being sent as the uart will be turned off. Put a while(true); at the end. |
Re (2): Now THAT was a really helpful comment. It probably explains why we get bad behavior from printf. I will pass it on to the rest of the bunch.
Re (1): Yes, it may optimize, but you are right, it should have no effect on the results because we use the same hex file. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Jun 25, 2010 9:32 am |
|
|
It will....
You are not initialising 'b', or 'c' to values.
Though the maths takes _similar_ times for different values, the time will vary a little.
Try adding a line to initialise b, and c, like:
Code: |
a=0x0000;b=0x0000;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
|
Now try with say:
Code: |
a=0xFFFF;b=0xFFFF;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
|
Note that now the times are the same with different hardware, but differ in the first case, and second case.
Best Wishes |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Fri Jun 25, 2010 12:00 pm |
|
|
Sorry, fellows, I didn't think those ideas make any difference. I tried the code below
Code: | //Lab13B V3 Calculation of execution time.
#include <16f877A.h>
#device ICD=TRUE
#fuses HS, NOLVP, NOWDT, PUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main ()
{
long time;
long a,b,c; //was int a,b,c;
b=0;
c=0;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu \n\r",time); //Ticks to do a=b*c
while(1);
} |
and by repeated use of the Reset button (not to trustworthy, it seems - I got...
Code: | Ticks=
Ticks=211
Ticks=
Ticks=211
Ticks=
Ticks=211
Ticks=703
Ticks=/9573
Ticks=51
Ticks=211
Ticks=213
Ticks=211
Ticks=211
Ticks=211
Ticks=
Ticks=211
Ticks=218
Ticks=211
Ticks=211
Ticks= 0211
Ticks=211
Ticks=5i=8e
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82
Ticks=5i=82 Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j
Ticks=6dv3j Ticks=6dv3j
|
The timing is more consistent now. But the output is still erratic.
Lou. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 25, 2010 12:40 pm |
|
|
1. Add BROWNOUT to the #fuses statement.
2. Add the ERRORS parameter to the #use rs232() statement.
3. Don't run the program in Debug mode. Comment out the Device
ICD=TRUE statement. Re-compile and use the Programmer menu.
Run it as a stand-alone program.
See if this helps. |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Fri Jun 25, 2010 8:19 pm |
|
|
-Have you got a noisy supply?
-Have you got a pull up on MCLR?
Could you please post results for this code:
Code: | while(1)
{
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu \n\r",time); //Ticks to do a=b*c
delay_ms(10); //or any appropriate value
} | Put this code after setting up the timer.
Rohit |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Sat Jun 26, 2010 9:28 am |
|
|
PCM programmer wrote: | 1. Add BROWNOUT to the #fuses statement.
2. Add the ERRORS parameter to the #use rs232() statement.
3. Don't run the program in Debug mode. Comment out the Device
ICD=TRUE statement. Re-compile and use the Programmer menu.
Run it as a stand-alone program.
See if this helps. |
Big difference; see the code and output below. I do not know what to do with the ERRORS result.
The reset button was used for each occurrence of the printf. The same results were obtained with and without the PICkit 2 Programmer connected.
What is the significance of these changes - especially the BROWNOUT? I would have thought it should be NOBROWNOUT.
And the NODEBUG?
The output without the while(1){} is significant; the ending LFCR is missing on EACH reset.
Code: |
//Lab13B V Calculation of execution time.
#include <16f877A.h>
#fuses HS, NOLVP, NOWDT, PUT, NODEBUG, BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)
void main ()
{
long time;
long a,b,c; //was int a,b,c;
b=0;
c=0;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu\n\r",time); //Ticks to do a=b*c
while(1){};
}
|
Without while(1){};
Code: |
Ticks=211Ticks=211 Ticks=211Ticks=211Ticks=211Ticks=211Ticks=211Ticks=211
Ticks=211Ticks=211Ticks=211Ticks=211Ticks=211Ticks=211Ticks=211Ticks=211T
icks=211Ticks=211Ticks=211Ticks=211Ticks=211
|
With while(1){};
Code: |
Ticks=211
Ticks=211
Ticks=211
Ticks=211
Ticks=211
Ticks=211
Ticks=211
|
I will try the next suggestions form Rohit de Sa, but pls explain these. |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Sat Jun 26, 2010 9:56 am |
|
|
Rohit de Sa wrote: | -Have you got a noisy supply?
-Have you got a pull up on MCLR?
Could you please post results for this code:
Code: | while(1)
{
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu \n\r",time); //Ticks to do a=b*c
delay_ms(10); //or any appropriate value
} | Put this code after setting up the timer.
Rohit |
The board has a pull-up resistor on !MCLR.
Your code works. I assume it was simply an experiment, but I'm not sure what it proves.
I had to replace the 10 ms with 1000 ms after several tries because the serial port monitor (C compiler tool) could not keep up. Its output is constant, and 211 is, I assume the correct answer. Later I added
#device ICD=TRUE and it did not output anything until it was reprogrammed several times.
I will let you all know if that value changes tomorrow <grin>
Re: power supply: We thought of this and we traded both boards and power supplies (9v adapters) independently, with the same erratic results and behavior.
Code: |
//Lab13B X5 Calculation of execution time.
#include <16f877A.h>
#fuses HS, NOLVP, NOWDT, PUT//, NODEBUG, BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main ()
{
long time;
long a,b,c; b=0;
c=0;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
while (1)
{
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu\n\r",time); //Ticks to do a=b*c
delay_ms(1000);
}
}
//Output on serial port monitor
Ticks=211
Ticks=211
Ticks=211
Ticks=211
|
|
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Sat Jun 26, 2010 10:15 am |
|
|
Wayne_ wrote: |
[*edit*]
Actually, isn't there a delay after writing to the timer before the timer is set with the correct value, that might be the 2 ticks you are subtracting and if the calculation is not being done you could be reading a random value from the timer before it has had a chance to be updated. [*edit*] I think I am talking rubbish here |
Well, if you go execute the new code (below), the result is 2 ticks. That is the overhead of the setup_timer and the set_timer1(0) code. The 211 ticks are the "computer-time" of the instruction a=b*c.
What is unclear to many is that the ticks values do not change with crystal speed. There be will the same number of ticks for every 16F877A for 20Mhz xtal as for 4Mhz xtal. But start another thread if you want to talk about this.
Code: |
//Lab13B V4 Calculation of execution time.
#include <16f877A.h>
#fuses HS, NOLVP, NOWDT, PUT, NODEBUG, BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)
void main ()
{
long time;
long a,b,c; //was int a,b,c;
b=0;
c=0;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
// a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
// time-=2; //Subtract overhead
printf("Ticks=%lu\n\r",time); //Ticks to do a=b*c
while(1){};
}
|
|
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Sat Jun 26, 2010 10:25 am |
|
|
A sample problem with the new code. Note the ICD=TRUE. Why is the output in a sequence and why does it repeat?? Code: |
//Lab13B V6 Calculation of execution time.
#include <16f877A.h>
#device ICD=TRUE
#fuses HS, NOLVP, NOWDT, PUT//, NODEBUG, BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main ()
{
long time;
long a,b,c; //was int a,b,c;
b=0;
c=0;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu\n\r",time); //Ticks to do a=b*c
while(1){};
}
For each reset button depression
Ticks=222
Ticks=223
Ticks=224
Ticks=226
Ticks=227
Ticks=228
Ticks=229
Ticks=218
Ticks=219
Ticks=221
Ticks=222
Ticks=223
Ticks=224
Ticks=226
Ticks=227
|
Last edited by louarnold on Sat Jun 26, 2010 11:34 am; edited 1 time in total |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Sat Jun 26, 2010 11:08 am |
|
|
Here is some more analysis. It would be helpful if someone could explain the reason for the results.
Code: |
//Lab13B V7 Calculation of execution time.
#include <16f877A.h>
//#device ICD=TRUE
#fuses HS, NOLVP, NOWDT, PUT
//#fuses NODEBUG
//#fuses BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main ()
{
long time;
long a,b,c; //was int a,b,c;
b=0;
c=0;
//Set Timer1 as Timer mode from instruction clock.
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(0); //Start the timer at value 0
a=b*c; //Calculate time to execute this
time=get_timer1(); //Get the # of clock ticks.
time-=2; //Subtract overhead
printf("Ticks=%lu\n\r",time); //Ticks to do a=b*c
while(1){};
}
|
PIC 16F877A Fuses and ICD=TRUE - Calculation of ticks for a=b*c
#device ICD=TRUE ("added" means not commented out)
#fuse NODEUG ("omitted" means line is commented out)
#fuse BROWNOUT
Conclusion: You should have ICD=TRUE with NODEBUG for proper results, otherwise do not use ICD=TRUE.
BROWNOUT makes no difference.
Code: |
ICD=TRUE BROWNOUT NODEBUG Result(Reset button)
added added omitted repeated 218 to 227
added omitted omitted repeated 218 to 227
added omitted added ticks=211
added added added repeated 218 to 227
omitted omitted omitted ticks=211
omitted added omitted ticks=211
omitted omitted added ticks=211
omitted added added ticks=211
|
Last edited by louarnold on Mon Jun 28, 2010 7:52 am; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 27, 2010 5:09 pm |
|
|
I can't duplicate your problem. I don't have your test setup. I have an
ICD2. I believe you have a PicKit2. I tested it with vs. 4.109. I used
"Programmer" mode in MPLAB (not Debugger mode). I used your latest
program with this configuration:
Code: |
#include <16f877A.h>
#device ICD=TRUE
#fuses HS, NOLVP, NOWDT, PUT, BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)
|
This is one of the configurations that fails for you, but it works for me:
Quote: |
Ticks=213
Ticks=213
Ticks=213
Ticks=213
Ticks=213
Ticks=213
|
I assume it's a peculiarity of the PicKit2 and/or your test setup.
I recommend that you don't do software timings in Debug mode. |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Mon Jun 28, 2010 6:19 am |
|
|
PCM programmer wrote: | I can't duplicate your problem. I don't have your test setup. I have an
ICD2. I believe you have a PicKit2. I tested it with vs. 4.109. I used
"Programmer" mode in MPLAB (not Debugger mode).
--snip--
I assume it's a peculiarity of the PicKit2 and/or your test setup.
I recommend that you don't do software timings in Debug mode. |
I agree; its likely the test set-up.
As for the code, it was given to us, left over from a previous course when an ICD was used. We no longer have an ICD, and we debug by printf. The compiler menu option Debug, shows the debugger disabled, but I assume that when ICD=TRUE, then Debug is in effect.
You recommended these changes; can you explain what ICD=TRUE does?
I know what BROWNOUT does, but how would it have helped here?
I assume DEBUG would leave hooks somewhere for the debugger, but as we set no breakpoints, I am at a loss to understand why it makes a difference. Can you explain?
Last edited by louarnold on Mon Jun 28, 2010 8:10 am; edited 2 times in total |
|
|
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Mon Jun 28, 2010 8:02 am |
|
|
PCM programmer wrote: | I can't duplicate your problem. I don't have your test setup. I have an
ICD2. I believe you have a PicKit2. I tested it with vs. 4.109. I used
"Programmer" mode in MPLAB (not Debugger mode). I used your latest
program with this configuration:
Code: |
#include <16f877A.h>
#device ICD=TRUE
#fuses HS, NOLVP, NOWDT, PUT, BROWNOUT
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)
|
This is one of the configurations that fails for you, but it works for me:
Quote: |
Ticks=213
Ticks=213
Ticks=213
Ticks=213
Ticks=213
Ticks=213
|
I assume it's a peculiarity of the PicKit2 and/or your test setup.
I recommend that you don't do software timings in Debug mode. |
I tried it again with my set-up. The output was intermittent with the reset button - sometimes nothing, and other times "ticks=211", but then it went into the sequence again - 218,218...229,218,219, etc. |
|
|
|
|
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
|