View previous topic :: View next topic |
Author |
Message |
miripek
Joined: 29 May 2012 Posts: 5
|
pic18f46k22 counter using timer and interrupt |
Posted: Tue May 29, 2012 7:47 am |
|
|
Hi all!
I need some help - I need to write a counter of 20 sec,
I wrote this for the interrupt:
#include <18f46k22.h>
#fuses INTRC_IO,NOMCLR,PUT,NOWDT,XINST,LVP
#use delay(clock=16000000) //16MHz
void interrupt() {
TMR1H=0xEC;
TMR1L=0x78;
PIR1=1;
}
But the compiler (mplab) didn't recognize it.
What's missing? some fuses?
Thanks a lot for the help.
Miri |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue May 29, 2012 8:03 am |
|
|
Just to clear things up, which compiler are you using? MPLAB is not a compiler but an IDE from which you can use many compilers like CCS, Microchip, High Tech and others.
This forum is for support on the CCS compiler, when you are using another compiler go to their website.
Code: | void interrupt() {
TMR1H=0xEC;
TMR1L=0x78;
PIR1=1;
} | This is not CCS code, I suspect you are using another compiler...
Just in case I'm wrong and you are using CCS:
- What is your compiler version number?
- XINST fuse can not be used with the CCS compiler
- Change LVP to NOLVP. The last 10 years I've never met anyone using a Low Voltage Programmer.
- Post a small but complete program. |
|
|
miripek
Joined: 29 May 2012 Posts: 5
|
I use a ccs compiler |
Posted: Tue May 29, 2012 8:13 am |
|
|
What should be the code then? _________________ miri |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue May 29, 2012 8:46 am |
|
|
Assuming that you ARE using the CCS compliler:-
You replace
Code: | TMR1H=0xEC;
TMR1L=0x78; |
with Code: | set_timer1(0xEC78); |
Your code
MIGHT try to set the timer1 interrupt flag with a different compiler, and would be nonsense. Since the timer1 overflow normally sets this flag and the ISR clears it.
If you really must operate directly on the PICs registers, you often have to tell the compiler what their addresses are, but it's NOT the easy way to go.
I recommend you read the CCS manual. CCS also supplies loads of code to show you how to do most things.
Mike |
|
|
miripek
Joined: 29 May 2012 Posts: 5
|
I tried to write this code |
Posted: Tue May 29, 2012 11:11 pm |
|
|
Code: |
output_high(pin_E1);
disable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
enable_interrupts(GLOBAL);
while(1);
output_low(pin_E1);
|
should it work as a counter? How can I set a counter for 5 sec? _________________ miri |
|
|
miripek
Joined: 29 May 2012 Posts: 5
|
HERE IS THE FULL CODE - SO FAR |
Posted: Tue May 29, 2012 11:53 pm |
|
|
I have to do a count - delay of 1 min, or 5 min, a delay that won't stop all program.
What is missing in my code?
Code: |
#include <18f46k22.h>
#fuses INTRC_IO,NOMCLR,PUT,NOWDT,NOLVP
#use delay(clock=16000000) //16MHz
void interrupt() {
set_timer1(0xFFFF); //set TMR1H and TMR1L
}
void main() {
setup_adc( ADC_OFF );
set_tris_a(0x00); // A5 A4 A3 A2 A1 A0 - SOLENOID (OUTPUT)
set_tris_b(0xF0); // B7 B6 B5 B4 - SWITCHES (INPUT) // B3 B2 B1 B0 - LCD (OUTPUT)
set_tris_c(0x00); // C7 C6 C5 C4 C3 C2 C1 C0 - SOLENOID (OUTPUT)
set_tris_d(0x3F); // D7 D6 - SOLENOID (OUTPUT) D5 D4 D3 D2 D1 D0 - SWITCHES (INPUT)
set_tris_e(0x0C); // E3 E2 - SWITCHES (INPUT) E1 E0 - SOLENOID (OUTPUT)
while(1) {
if (input(pin_E2)==1)
{
output_low(pin_A0); output_low(pin_A1); output_low(pin_A2); output_low(pin_A3);
output_low(pin_A4); output_low(pin_A5); output_low(pin_D6); output_low(pin_D7);
output_low(pin_C0); output_low(pin_C1); output_low(pin_C2); output_low(pin_C3);
output_low(pin_C4); output_low(pin_C5); output_high(pin_C6); output_low(pin_C7);
output_low(pin_E0); output_low(pin_E1);
disable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
enable_interrupts(GLOBAL);
while(1);
output_low(pin_A0); output_low(pin_A1); output_low(pin_A2); output_low(pin_A3);
output_low(pin_A4); output_low(pin_A5); output_low(pin_D6); output_low(pin_D7);
output_low(pin_C0); output_low(pin_C1); output_low(pin_C2); output_low(pin_C3);
output_low(pin_C4); output_low(pin_C5); output_low(pin_C6); output_low(pin_C7);
output_low(pin_E0); output_low(pin_E1);
}
}
} |
_________________ miri |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed May 30, 2012 1:53 am |
|
|
As shown, you will never leave the timer interrupt.
The timer counts upwards. The interrupt occurs when the timer wraps from FFFF, to 0000. You are setting the timer to FFFF in the interrupt, so the wrap will occur on the very next count. You are setting the timer to run at the instruction rate, so the interrupt will trigger one instruction later, putting you straight back into the interrupt.....
Best Wishes |
|
|
miripek
Joined: 29 May 2012 Posts: 5
|
And if I change the internal code to: |
Posted: Wed May 30, 2012 2:00 am |
|
|
disable_interrupts ( GLOBAL );
setup_timer_0 ( RTCC_DIV_128 | RTCC_INTERNAL );
set_timer0 ( 61 );
enable_interrupts (INT_RTCC);
enable_interrupts (GLOBAL);
do{
output_low(pin_A0); output_low(pin_A1); output_low(pin_A2); output_low(pin_A3);
output_low(pin_A4); output_low(pin_A5); output_low(pin_D6); output_low(pin_D7);
output_low(pin_C0); output_low(pin_C1); output_low(pin_C2); output_low(pin_C3);
output_low(pin_C4); output_low(pin_C5); output_low(pin_C6); output_low(pin_C7);
output_low(pin_E0); output_low(pin_E1);
}while(true);
it still doesn't work.
Thanks all for your help, _________________ miri |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed May 30, 2012 2:23 am |
|
|
You're using the internal oscillator.
This line does NOT set the frequency to 16MHz.
Code: |
#use delay(clock=16000000) //16MHz
|
You have to use the setup_oscillator for that.
I don't have your chip but this code will generate timings for you.
Code: | #include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
int16 tick_count;
#int_timer2
void tick_advance()
{ tick_count++; }
void main()
{
setup_timer_2(T2_DIV_BY_4,249,1);
enable_interrupts(int_timer2);
enable_interrupts(global);
tick_count = 0 ;
output_high(PIN_B0);
while (tick_count < 1000) {}
output_low(PIN_B0);
tick_count = 0 ;
output_high(PIN_B1);
while (tick_count < 1000) {}
output_low(PIN_B1);
while (1) {}
} |
You should be able to adapt it for your device.
I'm using MPLAB and an external crystal module.
I've used a PIC16F877 because it was to hand and happened to be plugged into my PICDEM 2 PLUS board.
The board has LEDs connected to B0...B3.
The code turns on B0, B1 for 1 second each, then stops.
Main() sets up the timer2 to overflow at 1ms intervals with a 4MHz clock.
The Timer2 interrupt advances the tick_count every 1ms.
Main() then monitors the tick_count to control the timing of everything else.
Main() can of course do other things whilst it monitors the tick_count. That's up to you.
The modification to minutes etc is your homework project.
You can of course use any of the other timers with some adjustment.
Timer2 is often used as a PWM clock so may not be available.
Mike |
|
|
|