CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

A problem with interrupt _external

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cuopbienquin



Joined: 17 Aug 2007
Posts: 4

View user's profile Send private message Yahoo Messenger

A problem with interrupt _external
PostPosted: Wed Sep 19, 2007 7:08 am     Reply with quote

Hi everyone.These followed codes are control stepper motor program.
include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)
#byte portb=0x06
#byte intcon=0x000B
#bit RB4=portb.4
#bit RB5=portb.5
#bit RB6=portb.6
#bit RB7=portb.7
#bit RBIF=intcon.0 //
#bit RBIE=intcon.3 //
void left()
{
portb=0b00000101;
delay_ms(50);
portb=0b00000110;
delay_ms(50);
portb=0b00001010;
delay_ms(50);
portb=0b00001001;
delay_ms(50);

}
void right()
{
portb=0b00000101;
delay_ms(50);
portb=0b00001001;
delay_ms(50);
portb=0b00001010;
delay_ms(50);
portb=0b00000110;
delay_ms(50);

}
void stop()
{
portb=0;
}
// Interrupt
#int_RB
void ngat_RB()
{
if((RBIF)&&(RBIE))
{
//Test sw1
{
if(RB4==0)
{
while ( RB5==1 && RB6 ==1)
{
left();
}
}
}
//Test sw2
{
if(RB5==0)
{
while( RB4==1 && RB6==1)
{
right();
}
}
}
//Test sw3
{
if(RB6==0)
{
while ( RB5==1 && RB4 ==1 )
{
stop();
}
}
}


}
RBIF=0; //
}

// Main program
main()
{
set_tris_b(0b11110000);
portb=0b00001111;
enable_interrupts(global);
enable_interrupts(int_RB);
ext_int_edge(H_to_L);
while(true)
{


}
}
When press sw1 ,motor turn left
sw2 ,.................right
sw3,..................stop
But when motor is mode 1(left),I press once other mode ,it also mode 1.I press twice ,motor is other mode?I dont know so why ?I hope your helping.Good luck
_________________
Let shared to be shared.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Sep 19, 2007 8:49 am     Reply with quote

First of all, this is not the proper way to use an interrupt. Interrupts are meant to react, quickly, to an internal/external event, do some kind of action (relatively short) and then exit the interrupt. You have functions being called from inside the interrupt and at least 200ms worth of delays for each function being called.

Instead of using an interrupt, I would suggest you simply monitor separate input pins, from inside of main(), and call the apropriate functions from there. There are several posts on reading inputs, with switches, in the forums.

Ronald
Ttelmah
Guest







PostPosted: Wed Sep 19, 2007 9:21 am     Reply with quote

First, use the 'code' buttons when posting. It makes code easier to read....
Then, you do not need to test the interrupt flag, or the interrupt enable. The interrupt handler, will only be called if these are both set.
Then at the end of the routine, you do not need to clear the interrupt. This is already done for you by the compiler.
Now, as it stands, once the interrupt is triggered by a 'left', the code stays for 200mSec, in the 'left' handler. The buttons are only tested each time round the loop, and if RB5 goes low, while RB4 is also low, the code will drop out ofthe 'left' loop (since RB5 is no longer '1'), but not then execute the right loop (since RB4 is still 0). Only on a second press, retriggering the interrupt, will the motor go the other way...
The code, sits permanently inside the interrupt handler, handling the stepping, which makes using an interrupt, rather 'pointless'.
Realistically, the whole thing is slightly the wrong approach.
Have something like:
Code:

include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)

int1 motor_on=FALSE;
int1 direction;
int8 phases[4] = {0b00000101,0b00000110,0b00001010,0b00001001};

#define RIGHT (0)
#define LEFT (1)
#define BUTTON_LEFT (16)
#define BUTTON_RIGHT (32)
#define BUTTON_STOP (64)

#INT_RB
void b_changed(void) {
   int8 temp;
   temp=input_b() ^ 0xFF;
   if (temp & BUTTON_STOP) motor_on=FALSE;
   else {
      //This way, 'stop' overrides other buttons
      if (temp & BUTTON_RIGHT) {
         direction=RIGHT;
         motor_on=TRUE;
      }
      if (temp &BUTTON_LEFT) {
         direction=LEFT;
         motor_on=TRUE;
      }
   }
}

#INT_TIMER2
void tick(void) {
   static int8 state=0;
   if (motor_on) {
      if (direction==LEFT) {
         state=++state & 3;
      }
      else {
         state=--state & 3;
      }
      portb=phases[state];
   }
   else portb=0;
}

// Main program
void main(void) {
   int8 temp;
   set_tris_b(0b11110000);
   portb=0b00001111;
   setup_timer_2(T2_DIV_BY_16,207,15);
   //Gives approximately a 50mSec timer 'tick'
   temp=input_b();
   //you should read the port, and clear the interrupt, or a spurious
   //trigger will occur when the interrupt is enabled.
   clear_interrupts(int_RB);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RB);
   enable_interrupts(INT_TIMER2)
   //ext_int_edge(H_to_L);
   //The _RB_ interrupt, occurs on both edges. The edge control function
   //Only works with the external 'INT' interrupt.
   while(true) {
       //Now the code here will carry on executing. When a button
       //is pushed, the control bits 'direction', and 'motor_on' get set
       //or cleared. In the timer interrupt, according to the state of
       //these, patterns are fed out to the motor, to drive it.

   }
}

No guarantees, this is just 'freehand' typed in, so errors may well exist. However it shows how to continue code execution, while the motor is driven, and how to make the 'stop' have priority over the other buttons.

Best Wishes
cuopbienquin



Joined: 17 Aug 2007
Posts: 4

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Sep 20, 2007 5:39 am     Reply with quote

Thank for comment.And I use ur codes to simulink stpeper motor circuit by Proteuss and it oprerate as I desire.But actually, I cant understand fully this code (sorry u ) .I wish u can find the error in my code and correct it .Good luck.
_________________
Let shared to be shared.
Ttelmah
Guest







PostPosted: Thu Sep 20, 2007 4:03 pm     Reply with quote

The main error, is described in what I have already typed.
You are sticking inside the interrupt, handling the stepper.
I'll try to document what is happening in my code better.
Code:

include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)

int1 motor_on=FALSE;
int1 direction;
int8 phases[4] = {0b00000101,0b00000110,0b00001010,0b00001001};
//These are the four bit pattern wanted to drive the motor. To turn it
//left, we need to output these patterns in order, 'right to left'. To turn
//the motor right, we need to go through these the other way.
#define RIGHT (0)
#define LEFT (1)
#define BUTTON_LEFT (16)
#define BUTTON_RIGHT (32)
#define BUTTON_STOP (64)

#INT_RB
void b_changed(void) {
   int8 temp;
   temp=input_b() ^ 0xFF;
   //Read the input port, and 'invert' all the bits. Bits are now '1', where
   //a switch is pressed.
   if (temp & BUTTON_STOP) motor_on=FALSE;
   //If the 'stop' button is pressed, turn off the motor
   else {
      //This way, 'stop' overrides other buttons
      if (temp & BUTTON_RIGHT) {
         //If the 'right' button is pressed, turn on the motor, and set the
         //direction to 'right'
         direction=RIGHT;
         motor_on=TRUE;
      }
      if (temp &BUTTON_LEFT) {
         //if the left button is pressed, set the direction to left, and motor 'on'
         direction=LEFT;
         motor_on=TRUE;
      }
   }
}
//Now this handler does nothing, except as the buttons are pressed, sets
//the motor_on and direction bits to the required patterns.

#INT_TIMER2
void tick(void) {
   //The actual movement is done here.
   //This routine will be called about every 50mSec
   //(actually 4000000/(4*16*208*15) times per second
   //20.03* per second, or 49.92mSec
   static int8 state=0;
   //Because this variable is 'static', it retains it's value beween calls
   if (motor_on) {
      //Here only if motor is 'on
      if (direction==LEFT) {
         //Move _forward_ through the array for 'left'
         state=++state & 3;
      }
      else {
         //Otherwise backwards for right
         state=--state & 3;
      }
      //Because of the '&3', the value of'state', can only be 0,1,2,3
      //Hence it gives 0,1,2,3,0,1,2,3, on subsequent calls when 'left'
      //is selected, and 3,2,1,0,3,2,1,0 when 'right' is selected
      portb=phases[state];
      //Output the required bit pattern
   }
   else portb=0;
   //If motor is not on, turn off the output drive.
}

// Main program
void main(void) {
   int8 temp;
   set_tris_b(0b11110000);
   portb=0b00001111;
   setup_timer_2(T2_DIV_BY_16,207,15);
   //Gives approximately a 50mSec timer 'tick'
   temp=input_b();
   //you should read the port, and clear the interrupt, or a spurious
   //trigger will occur when the interrupt is enabled.
   clear_interrupts(int_RB);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RB);
   enable_interrupts(INT_TIMER2)
   //ext_int_edge(H_to_L);
   //The _RB_ interrupt, occurs on both edges. The edge control function
   //Only works with the external 'INT' interrupt.
   while(true) {
       //Now the code here will carry on executing. When a button
       //is pushed, the control bits 'direction', and 'motor_on' get set
       //or cleared. In the timer interrupt, according to the state of
       //these, patterns are fed out to the motor, to drive it.
       //The key 'neat' thing is that you can do other jobs here
       //and the motor will keep moving.
   }
}


Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 20, 2007 4:16 pm     Reply with quote

Don't forget to add the NOLVP fuse.
Quote:
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT, NOLVP
#use delay(clock=4000000)

void main(void) {

set_tris_b(0b11110000);
portb=0b00001111;
cuopbienquin



Joined: 17 Aug 2007
Posts: 4

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Sep 20, 2007 9:49 pm     Reply with quote

@Ttlemah.Okay I see what you expalin in ur code.Genarally, I tend to expand urs to switch program using Timer2_interrupt. For example:
button 1: portb=0b0001111;
delay 50 ms
portb =0b1111111;
delay 100ms;
portb=0b0001101;
delay 200ms;
button 1: portb=0b0001111;
delay 50 ms
portb =0b1111111;
delay 100ms;
portb=0b0001101;
delay 200ms;
portb=0b0000111;
delay 50 ms
portb =0b1111001;
delay 100ms;
portb=0b1110000;
delay 200ms;
button3 : portb=0;
I think in ur code , a number of the phase left mode is equivalent one's right mode is 4.So what's the happiness if they are diffirent ??I hope u can correct ur code to more general.The best wish u?
@PCM programmer.Thank you for comment,MR PCM . I hope u canlead me the link of switch program in forum,cant u?.Good luck to u.
_________________
Let shared to be shared.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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