|
|
View previous topic :: View next topic |
Author |
Message |
cypher
Joined: 05 Oct 2007 Posts: 31
|
Need help with interrupts |
Posted: Fri Oct 19, 2007 11:14 am |
|
|
Hi,
I'm trying to write a simple program with interrupts. Bascially, the interrupt is on PORTB.0 on the rising edge. Here's what I have so far:
Code: |
#include <18F8722.h>
#device ADC=10
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#fuses HS,NOWDT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)
#use standard_io(D)
#use standard_io(E)
#define CLK_IN PIN_D0
#define DAT_IN PIN_D1
#define CS_PULSE PIN_D2
#define DAT_OUT PIN_D5
#int_ext //Use External Interrupt on PORTB.0
void interrupt_routine();
void shiftout(int byte5, int byte4, int byte3, int byte2, int byte1);
int switch1 = 0b10000000;
int switch2 = 0b10000000;
int switch3 = 0b10000000;
int switch4 = 0b10000000;
int control_w = 0b00001010;
int count = 0;
void interrupt_routine(void) //Interrupt subroutine
{
clear_interrupt(int_ext); //Clears the interrupt flag
output_bit(DAT_IN,1); //Toggles the LED on PIN_D1 if an interrupt is detected
delay_ms(100);
output_bit(DAT_IN,0);
delay_ms(100);
}
void main()
{
//Setup ADC
output_d(0);
output_e(0);
set_tris_d(0x20);
set_tris_e(0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(ALL_ANALOG);
output_bit(CS_PULSE,0);
printf("Working");
set_tris_b(0x0F);
ext_int_edge(L_TO_H);
enable_interrupts(int_ext);
shiftout(switch4,switch3,switch2,switch1,control_w);
output_bit(CS_PULSE,1);
delay_us(100);
output_bit(CS_PULSE,0);
delay_us(100);
disable_interrupts(int_ext);
}
void shiftout(int byte5, int byte4, int byte3, int byte2, int byte1)
{
int a;
set_tris_d(0x20);
for(a = 0; a < 8; a++)
{
output_bit(CLK_IN,1);
delay_ms(1);
output_bit(CLK_IN,0);
delay_ms(1);
output_bit(CLK_IN,1);
delay_ms(1);
output_bit(CLK_IN,0);
delay_ms(1);
}
return;
}
|
Basically, I'm generating a clock on CLK_IN and connecting that to PORTB.0 and hoping to see the LED on PIN_D1 toggle everytime it detects an interrupt. However this does not seem to work. Does anyone know what i'm missing? |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Fri Oct 19, 2007 11:43 am |
|
|
Before you do anything else, you need a loop in your MAIN. Right now you're just going to sleep after your first trip through. |
|
|
Guest
|
|
Posted: Fri Oct 19, 2007 11:45 am |
|
|
You enabled your interrupt then disable it again about 6 lines down and your code comes to and end.
try this
Code: | void main()
{
//Setup ADC
output_d(0);
output_e(0);
set_tris_d(0x20);
set_tris_e(0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(ALL_ANALOG);
output_bit(CS_PULSE,0);
printf("Working");
set_tris_b(0x0F);
ext_int_edge(L_TO_H);
enable_interrupts(int_ext);
shiftout(switch4,switch3,switch2,switch1,control_w);
output_bit(CS_PULSE,1);
delay_us(100);
output_bit(CS_PULSE,0);
delay_us(100);
while (1)
{
//sit here and wait for interrupt to occur
output_bit(CS_PULSE,1);
delay_us(100);
output_bit(CS_PULSE,0);
delay_us(100);
}
disable_interrupts(int_ext);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 19, 2007 12:14 pm |
|
|
Your interrupt routine is not being compiled. You can see this if you
look at the .LST file. You must put the #int_ext directive right before
the isr, to tell the compiler that it is an isr. Do it like this:
Quote: |
#int_ext
void interrupt_routine(void) //Interrupt subroutine
{
clear_interrupt(int_ext); //Clears the interrupt flag
output_bit(DAT_IN,1); //Toggles LED on PIN_D1 int is detected
delay_ms(100);
output_bit(DAT_IN,0);
delay_ms(100);
} |
The 2nd thing is, you don't need function prototypes if the function
is placed above main(), so that the compiler has already seen it
before it's called in later code. |
|
|
Ken Johnson
Joined: 23 Mar 2006 Posts: 197 Location: Lewisburg, WV
|
|
Posted: Fri Oct 19, 2007 1:42 pm |
|
|
Also..
You have 200 msec of delay IN the isr. During this time, no other processing can take place. Don't use delays in an isr. Find some other way to do this in your main loop.
Ken |
|
|
cypher
Joined: 05 Oct 2007 Posts: 31
|
|
Posted: Fri Oct 19, 2007 3:44 pm |
|
|
Thanks for all your replies.
I made all the suggested changes and it still does not seem to work. I have a feeling it has something got to do with the INTCON register.
I think it should be cleared at the start of the program. How do you set INTCON = 0 in C. I cannot find the syntax for setting internal registers.
And is there any other way I can confrim an interrupt has been detected since toggling an LED or printf does not seem to work. |
|
|
Guest
|
|
Posted: Fri Oct 19, 2007 4:59 pm |
|
|
This is what it looks like now. However I do not understand why its important to keep looping in the main function since the interrupt should occur when I go to the shiftout function and generate a clock.
Code: |
#include <18F8722.h>
#device high_ints = TRUE
#device ADC=10
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#fuses HS,NOWDT,NOLVP,NOPROTECT,NOBROWNOUT,NOPUT
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)
#use standard_io(D)
#use standard_io(E)
#int_ext //Use External Interrupt on PORTB.0
void interrupt_routine(void);
#int_ext fast
#define CLK_IN PIN_D0
#define DAT_IN PIN_D1
#define CS_PULSE PIN_D2
#define DAT_OUT PIN_D5
void shiftout(int byte5, int byte4, int byte3, int byte2, int byte1);
int switch1 = 0b10000000;
int switch2 = 0b10000000;
int switch3 = 0b10000000;
int switch4 = 0b10000000;
int control_w = 0b00001010;
int state = 0;
void main()
{
//Setup ADC
output_d(0);
output_e(0);
set_tris_d(0x20);
set_tris_e(0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(ALL_ANALOG);
output_bit(CS_PULSE,0);
printf("Working");
set_tris_b(0x0F);
ext_int_edge(L_TO_H);
enable_interrupts(int_ext);
shiftout(switch4,switch3,switch2,switch1,control_w);
output_bit(CS_PULSE,1);
delay_us(100);
output_bit(CS_PULSE,0);
delay_us(100);
while (1)
{
//sit here and wait for interrupt to occur
output_bit(CS_PULSE,1);
delay_ms(100);
output_bit(CS_PULSE,0);
delay_ms(100);
}
disable_interrupts(int_ext);
}
void shiftout(int byte5, int byte4, int byte3, int byte2, int byte1)
{
int a;
set_tris_d(0x20);
for(a = 0; a < 8; a++)
{
output_bit(CLK_IN,1);
delay_ms(100);
output_bit(CLK_IN,0);
delay_ms(100);
output_bit(CLK_IN,1);
delay_ms(100);
output_bit(CLK_IN,0);
delay_ms(100);
}
return;
}
#int_ext
void interrupt_routine(void) //Interrupt subroutine
{
clear_interrupt(int_ext); //Clears the interrupt flag
output_bit(DAT_IN,1); //Lights an LED when interrupt occurs
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 19, 2007 5:16 pm |
|
|
Quote: | #device high_ints = TRUE |
You don't need to enable this feature right now. Delete it.
Quote: | #int_ext //Use External Interrupt on PORTB.0
void interrupt_routine(void);
#int_ext fast |
The line in bold is just floating around in space. It shouldn't be there.
Interrupt directives only go in front of the Function Prototype, as above,
and in front of the actual isr routine. Delete the line in bold.
Quote: | set_tris_b(0x0F);
ext_int_edge(L_TO_H);
enable_interrupts(int_ext);
enable_interrupts(GLOBAL); |
You need to enable Global interrupts, as shown in bold.
Quote: | while (1)
{
//sit here and wait for interrupt to occur
output_bit(CS_PULSE,1);
delay_ms(100);
output_bit(CS_PULSE,0);
delay_ms(100);
}
disable_interrupts(int_ext);
} |
The line in bold is never executed. It doesn't do anything. Delete it.
There are other things, such as the TRIS settings on Port D.
You've defined Port D to use Standard I/O. In that mode, the compiler
will set the TRIS, as long as you use CCS pin i/o functions. You are
doing that. Therefore, you don't need those set_tris_d() statements. |
|
|
cypher
Joined: 05 Oct 2007 Posts: 31
|
|
Posted: Fri Oct 19, 2007 7:48 pm |
|
|
Thanks...enabling the interrupts globally worked! |
|
|
|
|
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
|