|
|
View previous topic :: View next topic |
Author |
Message |
johnh
Joined: 03 Jan 2004 Posts: 19 Location: UK - Brighton
|
It's a simple problem...... |
Posted: Thu Jan 29, 2004 9:21 am |
|
|
For those who know what they're doing....unlike me!
Hello people,
If i compile this simple bit of code
Code: |
//SerialServo.c
//----------------
#include <SerialServo.h>
#define PinServo0 PIN_B4
#int_TIMER0
TIMER0_isr()
void main()
{
int x;
x=12;
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
enable_interrupts(INT_TIMER0);
enable_interrupts(global);
byte data_byte = 0;
while (TRUE)
{
if (kbhit())
{
data_byte = getc();
// the byte will be between 0x10 and 0x5F
data_byte = data_byte - 0x10;
// data_byte will now be between 0 and 4F
output_high(PinServo0);
delay_ms(1); // the minimum on time for servo
// this loop will delay for a number of microseconds in data_byte 12 times
// which will give a delay between approx. 0 to 1 ms
do
{
delay_us(data_byte);
}
while(--x);
// now the output pulse will be on for 1 - 2 ms
output_low(PinServo0);
}
}
}
|
Why does it give me this error message
Code: |
Building 628SERVO.HEX...
Compiling 628SERVO.C:
Command line: "C:\PROGRA~1\PICC\CCSC.EXE +FM C:\PROGRA~1\MPLAB\628SERVO.C"
Error[29] C:\PROGRA~1\MPLAB\628SERVO.C 14 : Function definition different from previous definition
MPLAB is unable to find output file "628SERVO.HEX". This may be due to a compile, assemble, or link process failure.
Build failed.
|
the serialservo.h header is just -->
Code: |
//Serialservo.h
//---------------
#include <16F628.h>
#use delay(clock=4000000)
#fuses HS,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,MCLR,NOLVP,NOCPD
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_B2,rcv=PIN_B1,ERRORS,RESTART_WDT)
|
It's got to be something simple, but being a bit new to all this i can't see the damn problem!!
Help please....... _________________ There are 10 kinds of people who understand binary, those who do and those who don't |
|
|
Ttelmah Guest
|
Re: It's a simple problem...... |
Posted: Thu Jan 29, 2004 9:31 am |
|
|
johnh wrote: | For those who know what they're doing....unlike me!
Hello people,
If i compile this simple bit of code
[code]
//SerialServo.c
//----------------
#include <SerialServo.h>
#define PinServo0 PIN_B4
#int_TIMER0
TIMER0_isr()
|
I'd guess the problem is that you actually have not got a function here...
You either need:
TIMER();
to 'terminate' the definition, or:
TIMER0_isr() {
}
With the code that you want to run (or just a blank for now). The compiler knows that you have said you are going to have an interrupt subroutine, but then sees no subroutine (and hence the 'function definition differs').
Best Wishes |
|
|
SteveS
Joined: 27 Oct 2003 Posts: 126
|
|
Posted: Thu Jan 29, 2004 9:34 am |
|
|
By inspection I think it's this:
You defined a timer interrupt service routine, but it is not complete:
#int_TIMER0
TIMER0_isr()
is what you have. You need at least:
#int_TIMER0
TIMER0_isr()
{
}
to make it compile. You need to add whatever code in there to accomlish what you want to have happen during the interrupt (reload timer, etc). |
|
|
johnh
Joined: 03 Jan 2004 Posts: 19 Location: UK - Brighton
|
|
Posted: Thu Jan 29, 2004 9:53 am |
|
|
Excellent, thanks people..
Suspect my project will kick out a few more problems yet!!
Be back soon...
John _________________ There are 10 kinds of people who understand binary, those who do and those who don't |
|
|
johnh
Joined: 03 Jan 2004 Posts: 19 Location: UK - Brighton
|
|
Posted: Thu Jan 29, 2004 11:07 am |
|
|
next problem......
i want the RTCC to interrupt every ~17ms
at the moment the setup of the timer0 is
Code: |
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
|
in the device file it says
#define RTCC_INTERNAL 0
#define RTCC_DIV_256 7
I am using a 4Mhz crystal and a 16F628
any ideas
John _________________ There are 10 kinds of people who understand binary, those who do and those who don't |
|
|
johnh
Joined: 03 Jan 2004 Posts: 19 Location: UK - Brighton
|
|
Posted: Thu Jan 29, 2004 11:31 am |
|
|
for completeness - this is my actual code inside the isr
Code: | #int_TIMER0
TIMER0_isr(){
output_high(PinServo0);
delay_ms(1); // the minimum on time for servo
data_test = data_test + data_dir; //testing
if (data_test <= 0) data_dir = 1; //testing
// this loop will delay for a number of microseconds in data_byte 12 times
// which will give a delay between approx. 0 to 1 ms
x=12;
do
{
delay_us(data_test); //testing
}
while(--x);
//now the output pulse will be on for 1 - 2 ms
output_low(PinServo0);
} |
Do i need to include something in there to reset the timer?? Like what?
John _________________ There are 10 kinds of people who understand binary, those who do and those who don't |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
oh-oh! |
Posted: Thu Jan 29, 2004 1:24 pm |
|
|
Hi John,
There's a few no-no's in that code I'm afraid!
1) *Never* put CCS's delays in an interrupt. An interrupt needs to be kept short. I know the delay only looks like one command, but it creates a loop which ties up the processor for that duration. This kinda spoils the original intention of using interrupts!
2) Don't use 'while' loops in an interrupt, again for the same reason as above. Depending on the while() condition, this will tie up the processor for the duration it is true.
What is the "while(--x)" supposed to do? That looks to me like it would just continue to decrement 'x' forever, as it is not an operation which returns a true or false. 'x' will just wrap around from 0 to 255. I could be wrong here though.
Finally, you are testing if "data_test <= 0". Unless this is declared as a signed number, it can never be <0.
The best advice I can give is not to put any sort of loop in an interrupt. You can use an interrupt to trigger an event which takes a long time to execute by setting a 1-bit flag in the interrupt, then polling for it in main(). If it is true, make it false, then do whatever you want to do.
I always keep my main loop as a series of flag tests which don't do anything until required, so the poll time is very short. It is only when an event is triggered that the time-consuming bit needs to be done.
Any time based events can be triggered by postscale variables inside an interrupt, so no software delays need to be used. This then (dare I say it) makes your program start to look like a multi-tasking system!
I like your quote by the way! I saw another one yesterday on someone's website: "The thing I like about standards is that there are so many to choose from"
All the best,
Neil. |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
interrupt period calculation |
Posted: Thu Jan 29, 2004 1:54 pm |
|
|
Hi John, me again.
To calculate the interrupt period, remember that inside the PIC, the xtal frequency is divided by 4; so at 4MHz, your 'instruction clock' is at 1MHz, or 1MIPS.
For Timer0, you have a prescaler, so if you assign the prescaler to the watchdog timer (timer0 div by 1) it increments every micrsecond. The timer0 is an 8-bit register, so it will roll-over when it reaches 255, back to 0 and trigger the interrupt. Therefore, the interrupt period is 256us.
If you set the prescaler to divide by 256, you interrupt every 256^2, or 65536us -> 65.536ms. To get your desired ball-park interrupt rate, look in the datasheet for the possible values the prescaler can be set to, and choose one which fits best. Some people have produced spreadsheet charts for quick reference. I think Neutone is one.
To get multiples of that rep. rate, you can create a variable and increment or decrement it inside the ISR, then test for either zero, or a certain value. When true, set a flag ready to be picked up in main(), or do 'something', provided it is *short*!
Example. Provides an event every 10ms approx. Code: |
setup_counters(RTCC_INTERNAL,RTCC_DIV_8); // 4MHz/4 give 1us period. 1us * 8 = 8us bit resolution.
int postscale=0;
short event_trig=0;
....
#int_timer0
RTCC_ISR(){ // This occurs every 8us * 256 = 2.048ms.
postscale--; // Decrement your scale factor.
if(postscale==0){ // Test it.
postscale = 5; // Re-initialise it for next cycle.
event_trig = TRUE; // Set a flag to trigger an event, or do stuff here. True every 10.024ms.
}
} |
Until recently I have been getting (what I thought were) more accurate time intervals by presetting the timer0 register in each interrupt to give varying multiples of the bit rate, rather than 256 times the bit rate. I have been advised against this though. (See:http://www.ccsinfo.com/forum/viewtopic.php?t=18175 for details).
Whoa, time to crack a beer, and watch TV!
Cheers,
Neil. |
|
|
Pete Smith
Joined: 17 Sep 2003 Posts: 55 Location: Chester, UK
|
Re: oh-oh! |
Posted: Fri Jan 30, 2004 3:49 am |
|
|
neil wrote: | Hi John,
What is the "while(--x)" supposed to do? That looks to me like it would just continue to decrement 'x' forever, as it is not an operation which returns a true or false. 'x' will just wrap around from 0 to 255. I could be wrong here though.
|
do
{}
While (--x) will keep going so long as X is not zero.
As soon as it _is_ zero, it'll exit the loop.
Pete. |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
ah |
Posted: Fri Jan 30, 2004 3:54 am |
|
|
Oh well, the code looks shorter. I'll use that in future. Maybe I should get the old Kernaghan & Ritchie book out again!
Neil. |
|
|
|
|
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
|