|
|
View previous topic :: View next topic |
Author |
Message |
Ruby
Joined: 04 Jul 2014 Posts: 44
|
Timer0 Problem |
Posted: Sun Nov 23, 2014 2:29 am |
|
|
Hi. Can someone please tell me what is the wrong with the code???
Code: | #include <16f877a.h>
#include <stdlib.h> // atoi
#fuses hs,nowrt,nowdt,nodebug,brownout,nolvp,nocpd,put,noprotect
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, errors)
char data[2]={0,0};
unsigned int i=0,a=0,P_W=20;
#int_TIMER0
void hundred_micro() // 0.1 mili
{
if (i<P_W) output_high(Pin_D1);
if (i>P_W) output_low(Pin_D1);
i++;
if (i>=201) i=0;
set_timer0(6);
}
void main ()
{
set_tris_d(0x00); // Port D output
output_d(0x00); // Clear Port D
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_2);
set_timer0(6);
enable_interrupts(int_timer0);
enable_interrupts(GLOBAL);
printf("\fReady\n\r");
while (TRUE)
{
if (kbhit())
{
for (a=0;a<2;a++) data[a]=getc();
P_W=atoi(data);
if (P_W>20) P_W=20;
if (P_W<1) P_W=0;
printf("\PULSE TIME=%f ms i=%u \n\r",P_W*0.1,i);
}
}
} |
Timer is not working cause "i" stays in 0. I change the pic the same... i loaded a simple blinking led file , working good.
So what is the problem!!!! |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Nov 23, 2014 7:09 am |
|
|
what causes a change in the value of "data" ?
if you are going to use set_tris() then use FASTIO first.
Code: |
if (i<P_W) output_high(Pin_D1);
else output_low(Pin_D1);
|
lastly this :
since P_W is set to zero on every pass ,before the following is evaluated
what does THIS really do ??
Code: |
if (P_W>20) P_W=20;
if (P_W<1) P_W=0; |
as far as i can see, i would EXPECT the performance you are seeing
as this is JUST what your program commands. |
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Sun Nov 23, 2014 7:35 am |
|
|
Thanks for replay.
P_w is the data I am sending from pc in ascii. By atoi I am converting it to int. It has to be between 0 and 20.
I is set zero every 200. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Nov 23, 2014 9:07 am |
|
|
Code: |
data I am sending from pc
|
NOT in the code you posted though
it is a STATIC value AS shown.
show me the line of code where you think you are receiving the new value ..... |
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Sun Nov 23, 2014 9:31 am |
|
|
I didn't understand you...
By getc () I am getting the new data. There is no static value.
Code: |
if (kbhit()) { for (a=0;a<2;a++) data[a]=getc(); P_W=atoi(data); if (P_W>20) P_W=20; if (P_W<1) P_W=0; printf("\PULSE TIME=%f ms i=%u \n\r",P_W*0.1,i); }
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Nov 23, 2014 9:41 am |
|
|
from the ccs manual re ATOI()
Quote: |
Syntax:
ivalue = atoi(string)
or
lvalue = atol(string)
or
i32value = atoi32(string)
Parameters: string is a pointer to a null terminated string of characters. |
after reading the above - think about the implications to data[2]
BADCODE #1:
you enter your handler when the FIRST character is received but then try to get TWO characters before another char can arrive ....
you logic is very faulty in the time domain, and i have no idea what you send from the PC
BAD CODE #2 - format of received data
for instance suppose you want to set
P_W="15"
what do you send ??"15"<cr>
how many chars is that?
how about for "7"
where is your nul char terminator?
how do you differentiate between one and two digits?
is the light coming on for you yet ??
your thoughts?
Last edited by asmboy on Sun Nov 23, 2014 9:46 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sun Nov 23, 2014 9:46 am |
|
|
Are two incoming text characters a string?. A string _needs_ a null terminator. atol, won't work properly without this.
kbhit means _one_ character is waiting. You then read two. This will mean this part of the code will hang.
How will the code handle anything but numbers?. Error handling may be needed....
Your array needs to be larger. Then you should add characters to this, till a line feed is seen, and then add the null terminator instead of this. Then call atol.
As some more comments, when you set timer0 to 6, it has already counted to probably about 12.... Get rid of this and just let the timer free run. You are not going to get 0.1mSec by updating it. Instead you make the time less accurate. If you want 0.1mSec, then use timer2.
There is a big problem in trying to print 'i' it is updating 10000* per second. It is liable to change during the actual printout. Result 'garbage'. Take a copy and print this. If it was larger than an int8, then you'd have to either disable interrupts while doing the copy, or perform a loop till the copy was correct. The value will mean nothing though.
Do you realise how much time is involved in this interrupt?. You are executing it every 500 instructions. The save/restore, and maths, probably adds to about 90 instructions. Result nearly 20% of the entire processor time is being spent just handling this. Why not just use the hardware PWM - that is what it is for.....
Code: |
#include <16f877a.h>
#fuses hs,nowrt,nowdt,nodebug,brownout,nolvp,nocpd,put,noprotect
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, errors)
#include <stdlib.h> // atoi - only include things _after_ the processor is
//setup - otherwise functions using I/O and delays won't work....
unsigned int i=0,P_W=20;
#INT_TIMER2
void hundred_micro() // 0.1 mili
{
if (i<P_W)
output_high(Pin_D1);
else
output_low(Pin_D1);
if (++i > 200)
i=0;
}
void main ()
{
int8 chr;
int8 ctr=0;
int8 local_i;
char data[8]; //Keep variables _local_ unless they need to be global.
//set_tris_d(0x00); // pointless - doing the output below sets TRIS
output_d(0x00); // Clear Port D
setup_timer_2(T2_DIV_BY_4, 124,1); //Gives OSC/(4*4*125) = 10000
enable_interrupts(int_timer2);
enable_interrupts(GLOBAL);
printf("\fReady\n\r");
while (TRUE)
{
if (kbhit())
{
chr=getc();
if (chr=='\n') //line feed
{
//Only do this when line feed is seen
data[ctr]='\0'; //null terminate string
ctr=0;
P_W=atoi(data); //Now atoi can work
if (P_W>20)
P_W=20;
//if (P_W<1) P_W=0; //pointless P_W is unsigned
//If it is <1, it _is_ 0....
local_i=i;
printf("\PULSE TIME=%3.1w ms i=%u\n\r",P_W,local_i);
}
else
{
if (isdigit(chr))
{ //Ignore characters that are not numbers
data[ctr++]=chr;
if (ctr>7)
ctr=7; //ensure text cannot go beyond storage area.
}
}
}
}
}
|
|
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Sun Nov 23, 2014 10:04 pm |
|
|
Thank you very much you all specially Ttelmah.
I am sending the data through docklight program for now so I know how many characters I am sending. Although I am sending the data through docklight , do I still need to send a null terminator?
The reason I wanted to read "i" was to see if timer was working.
And finally I didn't use pwm cause I need to control 4 escs with pulses in 50hz or 400hz as I posted before in another forum. |
|
|
|
|
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
|