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 CCS Technical Support

Interrupt on change RB.3 Problems

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



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

Interrupt on change RB.3 Problems
PostPosted: Sat Sep 04, 2010 8:43 pm     Reply with quote

Hi

I am using a pic16f886 running at 8MHZ internal clock.

I have not been able to get the interrupt on change function to work.
for pin RB3 detecting a high to low transition.

In my code I was expecting that when button2 gets pressed, The ISR
would invoke and update value1. Since my display routine is running in
main I was expecting it to show an increment to Value1, but alas it just
sits there doing nothing as the button gets pressed.

I verified the display works by removing the interrupt routines and
making a call to the button function from main. Without the ISR's I can press the button and the display does increment.

Would I be correct in my assumption, or way off base as to how the ISR
should work.

The code compiles Ok without errors.

Thanks Scott

Code:

#include <main.h>
#use delay (INTERNAL = 8MHZ)
#include <lcd4bit.c>

#byte port_a = 0x05
#byte port_b = 0x06
#byte port_c = 0x07
   
#BIT BUTTON1 = port_b.2
#BIT BUTTON2 = port_b.3

#Define Backlight Pin_B1

int16    VALUE1;
int16    VALUE2;

void Display_Stuff()
{
   Lcd_cmd( LCD_LINE1 );
   printf(Write_LCD, "      %lu.%02lu0 :) ", VALUE1,VALUE2);
}

//====== Button Press =========================

#int_RB                                                                                               
void ButtonPress(void)
   {
   
   if( BUTTON2 == 0 )
   
   {
   
   ++VALUE1;

   if (VALUE1 > 1000)           
       VALUE1 = 1000;
   }
   
   Else                                                     
   
   {
   
    --VALUE1;
   
    if (VALUE1 < 2)
        VALUE1 = 1;
   }
     
}
   
void main()
{
setup_oscillator(OSC_8MHZ);
set_tris_b(0b00001101);
set_tris_c(0b10000000);

LCD_START();
Output_Low(Backlight);
   
VALUE1=1;         
VALUE2=0;

enable_interrupts(INT_RB3);
EXT_INT_EDGE(H_TO_L);

clear_interrupt(INT_RB);
enable_interrupts(GLOBAL);

while (true)
   {
   Display_Stuff();
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19477

View user's profile Send private message

PostPosted: Sun Sep 05, 2010 2:35 am     Reply with quote

First thing, 'Interrupt on change', does what it says. It generates an interrupt _when the level on the pin changes_. It does not support setting the 'edge'. This later ability is reserved for the hardware interrupt pin(s). This is why the setting edge function, refers to int_ext. So your function would be called on both edges, and needs to be written to handle this, and the edge selection code does nothing...
Then, if you want to do direct I/O, and not change the tris, select 'fast_io'. There is a very significant risk, that if your LCD code, does a write anywhere to portB, the tris may be being overridden.
Finally, simple question. Compiler version?. The individual bit masking involved in the interrupt on change on some of the later chips, is faulty in some compiler versions.

Best Wishes
Ttelmah



Joined: 11 Mar 2010
Posts: 19477

View user's profile Send private message

PostPosted: Sun Sep 05, 2010 4:24 am     Reply with quote

The last comment about tris, is almost certainly your problem.
I'm assuming the LCD code, is the code you have posted in the other thread about LCD speed. If so, this performs a byte wide output to port B, which will set the tris to zero. Your interrupt will then never work. You _need_ to select #use fast_io(B)

Best Wishes
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Sun Sep 05, 2010 4:44 pm     Reply with quote

I was using 4.108 ver.

I tried the LCD routine with the button test using both fast_io and the
standard io produced by the compiler.

In both cases the lcd and button function worked fine. The help file talks
about using Tris function and says that

These functions allow the I/O port direction (TRI-State) registers to be set. This must be used with FAST_IO and when I/O ports are accessed as memory such as when a # BYTE directive is used to access an I/O port. Using the default standard I/O the built in functions set the I/O direction automatically.

If I understand what your saying, then basically if using Tris to set the Pin
direction will work ok, but if you introduce a ISR into the code and I don't use Fast_IO then the default std/io of the compiler will go out to lunch and choke ?

Is that correct ?

Thanks Scott
Ttelmah



Joined: 11 Mar 2010
Posts: 19477

View user's profile Send private message

PostPosted: Mon Sep 06, 2010 1:54 am     Reply with quote

With 'standard_io', the port direction, is set whenever you read or write to a port or bit. So, in your LCD code, the tris gets set to '0' specifying 'all output', by the output_b instruction. If you then don't have an interrupt, but read the port bit in a loop, the act of reading the port bit, sets the required pin to 'input', and the read code works.
Problem with the interrupt, is that the 'read', doesn't occur, till _after_ the interrupt has fired. Since the port has been set as an 'output', the interrupt won't fire, so you are stuck.
Two routes round:
1) Use fast_io. This makes controlling the tris _your_ responsibility.
2) Tell the code to set the required pin as an input. You could (for instance), add a dummy 'read' of the input pin to the LCD code, which would then do this.

Best Wishes
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Mon Sep 06, 2010 1:36 pm     Reply with quote

Ttelamh, ah ha I see, Excellent explaination.

I appreciate your insight. With respect to using the tris for the direction
register. I notice that, in the compiler under the device editor Tris is
disabled for the 16f886 part in the "Other features" section

I had read somewhere that using tris was not a good idea. I am curious
to know if you dont use tris to set the direction of a port pin is there a
more reliable method of doing so ?

Most of the code I will be writing in the short term will use byte wide I/0
so I guess I am trying to figure out the correct method to configure port
pins so the compiler will know never to change an actual pin setting.

Is there any potential issues to using Tris going forward with some of the newer parts, like the f18 series.

Thanks Scott.
Ttelmah



Joined: 11 Mar 2010
Posts: 19477

View user's profile Send private message

PostPosted: Mon Sep 06, 2010 1:43 pm     Reply with quote

OK.
Historically, on the older chips, there was no tris register, and instead a separate tris instruction. This is still available on the later PIC 16 chips, but is no longer recommended. Instead you should write directly to the tris register. Just use the compiler's tris instruction, it will use the older instruction on chips that support it, and access the registers on latter chips.

Best Wishes
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Mon Sep 06, 2010 2:49 pm     Reply with quote

Ok, will do

Thanks for the help

Best regards Scott
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