|
|
View previous topic :: View next topic |
Author |
Message |
timmeh87 Guest
|
pic16f767 timing |
Posted: Fri Jun 09, 2006 6:23 pm |
|
|
ok. so lets start with some basic details here:
im programming a pic 16f767 with mplab (with CCS of course). its set to the 8mhz internal osc, and is running off of an ICD2 so its getting about 5 volts. hooked up to PORTA i have 8 leds, so i can send a byte to the port and read it off easily.
i am trying to create a device similar to ones created by other people that can display an image in a bicycle wheel, using POV, in a similar way to those novelty clocks you can get. (ladyada made one called "Spoke POV" and a character named 'Ian' made a similar one of the same name. google "ian pov", its the first result. sorry, i cant post links)
i plan to have a string of 32 leds on shift registers (like ian did), and flash 256 raster lines per revolution to create an image (like ian did).
an external interrupt (when the device passes under the 'fork' of the bike) will begin drawing the image regardless of current position, to keep it static within the wheel.
right now i am just trying to get the timing down, before i start trying to work with pictures or anything fancy like that. the basic algorithm i'm going with is as follows:
Code: |
int_timer0 increments a counter
int_ext raises a flag
main loop
-if flag has been raised:
--multiply the counter by the length of one timer0 overflow
--divide this time by 256 (256 radial raster lines)
--reset counter, flag, and line counter
- display the (linecouter)th line
- increment line counter
- wait the length of one raster line
|
so basically it times a revolution and bases the timing of the next revolution on the previous one. now, the problem im having (as the title may suggest) is that the timing is terribly off. i had to calculate some constants, and i really hope im just screwy in my assumptions and that that is where the problem lies.
here is the code i have right now. it just outputs the line counter to PORTA for debugging purposes. as this code is written, the lines are displayed wayyy too fast (less than 10ms for all of them).
Code: | #include <16f767.h>
#use delay(clock=8000000)
void main(void);
void tmr0int(void);
void externalint(void);
void mainloop(void);
long x; // timer counter
int1 restart; // ext_int flag
void main(void){
setup_oscillator (osc_8mhz); //set oscillator to 8mhz
setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_256); //set timer to internal osc, 256x prescaler
enable_interrupts (global); //enable interrupts
enable_interrupts (int_ext|int_timer0); //enable timer0 and external interrupts
EXT_INT_EDGE (h_to_l); //set external interrupt edge to high-to-low
mainint(); //main loop
}
#INT_TIMER0
void tmr0int(void){x++; clear_interrupt(INT_timer0);} // increment counter, clear interrupt
#INT_EXT
void externalint(void){restart = 0x01; clear_interrupt(INT_EXT);} // raise flag, clear interrupt
void mainloop(){
long UsPerRev; // microseconds per revolution ('micro' to avoid floating point operations)
long linenumber, msperline; // line number, miliseconds per line
enable_interrupts(global); //i wasnt sure if you had to enable these for each function or not
enable_interrupts(int_timer0|int_ext);
do{
if (restart == 0x01){ // if flag is raised
restart = 0x00; // clear flag
UsPerRev = x * 32768; // ok, this line is suspect. see below for detials
x = 0; // clear timer counter immediately (timer is still ticking!)
msPerLine = UsPerRev / 256000; // calculate ms per line (256 lines, 1000us per ms)
linenumber = 0; // resent line count
}
output_a(make8(linenumber, 0)); // output line counter so i can see whats going on inside
linenumber++; // increment line counter
delay_ms(make8(msPerLine,0)); // wait
}while(linenumber<255);
} |
ok. so i assume that one timer overflow takes 32768us. here is my logic:
-timer0 is incremented once each instruction cycle (datasheet)
-instruction cycle is fosc/4 = 2mHz = .5us
.5us * 256 (8bit timer) * 256 (prescaler) = 32768us
(in the help file it says you cant pass a variable bigger than 256 to the delay functions, which is why i converted it to ms. but the functions seem to take long variables without trouble. whats up with this?)
so, like i said, no matter how fast you trigger the external interrupt, the loop fires off in an impreceptably small amount of time. whats up with that?
thanks in advance for your help
- Tim |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 09, 2006 8:03 pm |
|
|
Quote: | void mainloop()
{
long UsPerRev;
long linenumber, msperline;
enable_interrupts(global);
enable_interrupts(int_timer0|int_ext);
do{
if(restart == 0x01)
{
restart = 0x00;
UsPerRev = x * 32768;
x = 0;
msPerLine = UsPerRev / 256000;
linenumber = 0;
} |
In CCS, a "long" is an unsigned 16-bit integer. In the code above,
you multiply x by 32768. If x is greater than 1, you'll get immediate
overflow of the 16-bit variable, UsPerRev.
In the line where you divide by 256000, you will always get 0 as the
result, because UsPerRev can be from 0 to 65535, and dividing any
of those values by 256000 will give 0.
If you want to use values larger than 65535, then I suggest that
you declare your variables as "int32". This gives unsigned 32-bit
variables.
Quote: | #INT_TIMER0
void tmr0int(void)
{
x++;
clear_interrupt(INT_timer0);
}
#INT_EXT
void externalint(void)
{
restart = 0x01;
clear_interrupt(INT_EXT);
} |
The statements shown in bold above are not necessary.
The compiler inserts code to clear the interrupts before it leaves the isr.
Quote: |
In the help file it says you cant pass a variable bigger than 256 to the
delay functions, which is why i converted it to ms. but the functions
seem to take long variables without trouble. whats up with this?) |
They truncate the 16-bit argument and use only the lower 8 bits.
See the following links for functions that accept a 16-bit variable.
long_delay_us():
http://www.ccsinfo.com/forum/viewtopic.php?t=16656
long_delay_ms():
http://www.ccsinfo.com/forum/viewtopic.php?t=375 |
|
|
Guest
|
|
Posted: Fri Jun 09, 2006 8:48 pm |
|
|
haha. yeah. im used to longs being 32 bits. i never even thought about that.
ok well, thank you for the help fine sir. i shall see if i can get it to work now |
|
|
|
|
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
|