|
|
View previous topic :: View next topic |
Author |
Message |
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
timer0 with 12f675 |
Posted: Fri Jun 17, 2011 1:06 am |
|
|
Hi guys, I've got a problem that is really pissing me off! I'm trying to enable timer0 interruptions with pic 12f675, I've searched and tried all possible examples, but nothing seems to work. This is my code:
Code: |
#include <12F675.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //No Master Clear pin
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD
#use delay(int=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_A1,rcv=PIN_A0,bits=8,stream=comPort)
#define LED PIN_A2
#int_TIMER0
void TIMER0_isr(void)
{
disable_interrupts(INT_TIMER0);
printf("working!");
enable_interrupts(INT_TIMER0);
}
void main()
{
delay_ms(100);
setup_comparator(NC_NC);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit); //1.0 ms
printf("about to enable interrupt!");
enable_interrupts(INT_TIMER0); // The program stops in this line!
enable_interrupts(GLOBAL);
char string[20]; // Buffer
while(true)
{
if(kbhit()){ // check for new character
gets(string);
puts(string);
}
}
} |
When I run the program I only see in my screen "about to enable interrupt!" over and over again. As far as I understand, the code inside "TIMER0_isr()" should be executed every 1 ms... right??
My other question is... how can I use "get_timer0()" ?? I'm really confused with this... I reckon I need a lot of help!
Thanks! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jun 17, 2011 3:20 am |
|
|
First big problem. Don't print in the ISR. The PIC does not support re-entrant code. Printf, is using putc. Hence interrupts _will_ be disabled in all the external code wherever you output data.
Second (non important), generally, don't disable/enable interrupts in the ISR.
Third problem. Remember how long things take. 'Working!', at 9600bps, takes 8.33mSec to send.....
Fourth, remember this chip does not have a UART. 'kbhit', _must_ be called at least 20000 times per second, if characters are not to be missed. What is going to happen with interrupts taking 8+mSec are being called...
Are you sure your RS232 input line is being pulled high?. If not the code will loop forever.
You really need to use a chip with a hardware UART, to make what you show even begin to work, but as a crude 'near miss':
Code: |
#include <12F675.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //No Master Clear pin
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD
#use delay(int=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_A1,rcv=PIN_A0,bits=8,DISABLE_INTS)
#define LED PIN_A2
int16 tick=1000;
int1 one_sec=FALSE;
#int_TIMER0
void TIMER0_isr(void) {
if (tick) --tick;
else {
tick=1000;
one_sec=TRUE;
}
}
void main()
char buffer[20];
delay_ms(100);
setup_comparator(NC_NC);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit); //1.0 ms
// Don't declare variables mid code - char string[20]; // Buffer
while (input(PIN_A0)) {
printf("Serial input is high - cannot continue/n/r");
delay_ms(1000);
}
printf("about to enable interrupt!/n/r");
enable_interrupts(INT_TIMER0); // The program stops in this line!
enable_interrupts(GLOBAL);
do {
if(kbhit()){ // check for new character
gets(string);
puts(string);
}
if (one_sec) {
one_sec=FALSE;
printf("T");
}
} while(TRUE);
}
|
This will still miss characters on the input, if the 'T' display is called at the moment you type, but at least has a chance.....
Some parts are purely 'cosmetic'. The 'do while' construct avoids the compiler error message about condition always true.
Use of 'inline' variable declarations is 'borderline'. C does not support them. C++ does. CCS stopped complaining about them a while ago, _but_ they still cause problems in more complex code - better to stick to standard C practice here....
The disable_ints option on the RS232, will mean that the tick will be delayed till the end of each character when sending/receiving. Without this, characters _will_ be distorted by the interrupt.
Note the test for the RX line going high before starting.
Since you are not using streams in your I/O, don't declare them.
Best Wishes |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Wed Jun 22, 2011 5:07 am |
|
|
Hi Ttelmah, thanks for your reply and sorry for my delay...
All about rs232 and printf was just for give an example, the real problem is that the program doesn't continue after activating interrupts (enable_interrupts(INT_TIMER0);). Even your code seems to do the same...
However, I noticed that apparently the PIC is reseting itself over and over again, cos I get the same message continuously "about to enable interrupt!". So I wonder if it's because of not defined fuses or something like that.
Really appreciate any further help! |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Tue Jul 05, 2011 7:56 pm |
|
|
Guys, still having problems... nobody?? really?
I updated my code to check my theory about resetting...
Code: |
void main()
{
int8 t = restart_cause();
switch (t)
{
case NORMAL_POWER_UP:
puts("Starting...");
break;
case MCLR_FROM_RUN:
puts ("from run!");
break;
case WDT_TIMEOUT:
puts("Time out!");
break;
default:
printf("Value: %d", t);
break;
}
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit); //1.0 ms overflow
setup_comparator(NC_NC);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while(true);
}
|
And in fact, I'm getting: "Starting..." the first time, and "from run!" over and over again. It means the chip is resetting itself (I guess every 1 ms) and It is never reaching TIMER0_isr(void).
Please please, what am I doing wrong?? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 05, 2011 8:56 pm |
|
|
What is the Vdd voltage on the PIC ? Is it +5v ?
Is a clean, stable Vdd voltage ? Or does it have noise on it ? |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Tue Jul 05, 2011 9:03 pm |
|
|
Vdd is 3V, from 2 AA batteries... The only 2 devices connected are a xbee module and the pic itself. So I reckon it doesn't have any noise.
I also tested the circuit with 5V from a regulated power supply, but the result is the same.
Any ideas? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 05, 2011 9:25 pm |
|
|
1. What is your CCS compiler version ?
2. What are you using for a programmer ? ICD2 ? Pickit 2 ? ICD-U40 ?
Or something else ?
3. What Windows program are you using to run your programmer ?
MPLAB ? CCS IDE ? or something else ?
4. Read the 12F675 with your programmer and examine the Config bits
that it reports. What are they ? Is it possible that the WDT is enabled ?
5. After you read the 12F675 with your programmer, look at program
memory address 0x3FF. What is the value of the hex word that is
programmed at that address ? |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Tue Jul 05, 2011 10:19 pm |
|
|
PCM Programmer, this is my configuration:
1. PCM Compiler V4.114
2. I'm using a usb programmer compatible with K149, this is it:
http://www.ebay.com.au/itm/USB-Interface-PIC-Programmer-40-ZIF-Microchip-K149-JDM-/330579620150?pt=AU_B_I_Electrical_Test_Equipment&hash=item4cf814b136#ht_2703wt_907
3. I'm using DIY K149-BC PICmicro Programmer V141204
4. WDT=Disabled, MCLRE=Disabled, Code Protect ROM=Disabled, PWRTE=Enabled, Oscillator=INTOSC
5. 0x3FF = 3440
On the other hand, I added this to my program:
set_timer0(6);
while(true){
if(get_timer0() > 254){
set_timer0(6);
onTick();
}
}
and removed the line "enable_interrupts(INT_RTCC);"
It seems to be working properly, it calls "onTick()" every 1 ms... however, I would like to make it work as everybody else, I mean without asking for "get_timer0()".
Thanks for your help. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 05, 2011 10:59 pm |
|
|
Post your current test program that shows the failure. It should have
the #include for the PIC, #fuses, #use statements, variable declarations,
main(), etc. |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Wed Jul 06, 2011 2:02 am |
|
|
Ok, this is the original code without the modifications I mentioned before:
Code: |
#include <12F675.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#use delay(int=4000000)
#define XBEE_IN PIN_A0
#define XBEE_OUT PIN_A1
#define LED PIN_A2
#define SW1 PIN_A3
#use rs232(baud=9600,parity=N,xmit=XBEE_OUT,rcv=XBEE_IN,bits=8,stream=xbee)
//test.c
#include <test.h>
#int_TIMER0
int16 time=0;
void TIMER0_isr()
{
output_high(LED);
time++;
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit); //1.0 ms overflow
setup_comparator(NC_NC);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while(true)
{
if(time > 1000)
{
time = 0;
puts("1s");
}
}
}
|
After several tests, I'm sure TIMER0_isr is never called (LED is never ON). The pic is reseted after (I guess) 1ms. Thus, I never receive "1s".
Hope you can help me. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Wed Jul 06, 2011 2:25 am |
|
|
A couple of things:
1) move the variable declaration above the INT declaration.
The #INT line, should be the line immediately above the function it applies to. Don't know if having a variable declaration between, will cause a problem, but better to be safe...
Code: |
int16 time=0;
#int_TIMER0
void TIMER0_isr() {
output_high(LED);
time++;
}
|
2) You _have_ got a series resistor between the PIC and the LED?.
3) You have got a low ESR capacitor right by the PIC?.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jul 06, 2011 2:31 pm |
|
|
If you do the fix that Ttelmah suggested, I think it has a chance to work.
I was able to make your program work this morning, but it was painful.
First, I used Pickit2, and set it up so I could remotely power the board,
instead of having Pickit2 provide the Vdd power. When I did this, the
calibration word at address 0x3FF in the 12F675 was destroyed. I had
to re-program it with the ICD2, since Pickit2 has no ability to do this in
the programmer setup screen. This happened at least 2x.
Eventually, I got tired of wasting my time with trying to make Pickit2 work
with it. So I switched to ICD2. But ICD2 doesn't like the NOMCLR fuse.
It gives a warning. So I changed it to MCLR, and I have a 10K pullup on
the PIC's MCLR pin on the board, as required by ICD2.
Then I discovered that my nominal Calibration memory word of 0x3480
produced an internal oscillator frequency that was substantially off
frequency from the nominal 4.0 MHz. Just to make it run now, I changed
the baud rate in the #use rs232() statement to 9200 baud. Then it
started working. Later, I'll figure out what the correct calibration value
should be for this particular PIC. Here is the Terminal output:
Quote: |
1s
1s
1s
1s
1s
1s
1s |
Also, I didn't like your isr routine, where it turned the LED on if you get
an interrupt. I wanted more activity. So I changed it to toggle the LED
at approximately a rate of 1 second On, 1 second Off.
Code: |
#int_TIMER0
void TIMER0_isr()
{
if(time == 0)
output_toggle(LED);
time++;
}
|
These tests were done with your version, 4.114. |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Wed Jul 06, 2011 4:37 pm |
|
|
Guys, I really appreciate your help!
I haven't been able to test it, as I'm about to leave, I'll be back in a couple of hours and I'll let you know how is going.
Thanks again. |
|
|
alex323qp
Joined: 17 Jun 2011 Posts: 12
|
|
Posted: Wed Jul 06, 2011 9:47 pm |
|
|
wow! I can't believe it was so simple!
You are my heroes guys!!!
It's finally working. I just moved the variable above the procedure (as Ttelmah suggested) and it worked.
I also noticed that with NOMCLR also works fine. However my rs232 communication stopped working, I guess is a speed problem, as you said PCM p.
Thanks, thanks, thanks!! |
|
|
|
|
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
|