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

Port change interrupt mask (12F675)

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



Joined: 09 May 2020
Posts: 7

View user's profile Send private message

Port change interrupt mask (12F675)
PostPosted: Sat May 09, 2020 6:11 pm     Reply with quote

Hello.

I'm trying to read 2 buttons with the port change interrupt with the PIC 12F675, but it is triggering with any pin change (INT_RA), which is expected. I have checked the datasheet, it says about REGISTER 3-4: IOC, which looks like is what I need, but how can I access it with the CCS?
Also I have found in the CCS the INT_RAx, which the x is the pin number, which triggers the interrupt also, but just one pin, I need two.
I believe this is simple to solve, it just lack of my knowledge.

Thank you very much.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 09, 2020 6:47 pm     Reply with quote

The program below shows how to enable the IOC interrupts. You will have
to add your user code in the interrupt routine:
Code:

#include <12F675.h>
#use delay(clock=4M)

#byte PORTA = getenv("SFR:PORTA")

#INT_RA
void int_ra_isr(void)
{
int8 temp;

// Read port pins to clear mismatch condition.
temp = PORTA;

 
}

//======================
void main()
{
port_a_pullups(0b00011000);  // Enable weak pullups on RA3, RA4
delay_us(10);                // Allow time for them to pull up

enable_interrupts(INT_RA3);  // Set IOC register, bit 3 = 1
enable_interrupts(INT_RA4);  // Set IOC register, bit 4 = 1

clear_interrupt(INT_RA);     // Clear any existing IOC interrupts

enable_interrupts(GLOBAL);

while(TRUE);

 


Look at this CCS example file, which shows how to detect a specific edge
on a specific pin, inside the interrupt routine code:
Quote:
c:\...\picc\examples\ex_pbutt.c
ChicoCyber



Joined: 09 May 2020
Posts: 7

View user's profile Send private message

PostPosted: Sat May 09, 2020 7:27 pm     Reply with quote

NICE! Thank you very much!

I was trying like this, but not worked, I would like very much to understand why.
Code:

#include <main.h>
#USE FAST_IO (A)
#byte WPU = 0x95    //Pullups 1=ativado
#bit GPPU = 0x81.7  //Pullups global 0=seleção individual
#byte IOC = 0x96    //Port on change mask (1=Enabled)

#INT_RA
void  RA_isr(void)
{
   clear_interrupt(INT_RA);
   output_toggle(PIN_A5);
   delay_ms(100);
}

void main()
{
   set_tris_a(0b11011111);     //0=saída 1=entrada
   WPU =      0b00000000;      //Pullups 0=ativado 1=desativado
   GPPU = 0;                   //Global Pullups 0=seleção individual pelo WPU
   IOC =      0b00010100;      //Port on change mask (1=Enabled)
   enable_interrupts(INT_RA);
   enable_interrupts(GLOBAL);

   while(TRUE)  {}

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 09, 2020 7:56 pm     Reply with quote

Your code doesn't read PortA inside the isr.

You have to read PortA to clear the mismatch condition latch.

The 12F675 datasheet says:
Quote:
The user, in the Interrupt Service Routine, can clear
the interrupt in the following manner:

a) Any read or write of GPIO. This will end the mismatch condition.

b) Clear the flag bit GPIF.

A mismatch condition will continue to set flag bit GPIF.
Reading GPIO will end the mismatch condition and
allow flag bit GPIF to be cleared.

Both (a) and (b) have to be done. The compiler handles item (b).
You have to do item (a) in the interrupt routine. I show how to read
PortA without affecting the TRIS bits in my sample code.

If you don't read the port, the mismatch latch will continue to cause
an interrupt. You'll get re-interrupted again, as soon as the code exits
the interrupt routine. The program will appear to be locked up.
So it's essential to read the port in the interrupt routine.

Note that my code also reads the port before enabling interrupts in main().
That way, you won't get an interrupt immediately upon enabling global
interrupts. A new change condition must occur to get your first IOC interrupt.
ChicoCyber



Joined: 09 May 2020
Posts: 7

View user's profile Send private message

PostPosted: Sat May 09, 2020 8:30 pm     Reply with quote

Nice! I got it!
But here is what is happening:

Cant make it work with the IOC register, it is triggered constantly (it is just curiosity):
Code:

#include <main.h>
#USE FAST_IO (A)
#byte WPU = 0x95    //Pullups 1=ativado
#bit GPPU = 0x81.7  //Pullups global 0=seleção individual
#byte IOC = 0x96    //Port on change mask (1=Enabled)
int8 Temp;

#INT_RA
void  RA_isr(void)
{
   Temp = input_a();
   clear_interrupt(INT_RA);
   output_toggle(PIN_A5);
   delay_ms(100);
}

void main()
{
   set_tris_a(0b11011111);     //0=saída 1=entrada
   WPU =      0b00000000;      //Pullups 0=ativado 1=desativado
   GPPU = 0;                   //Global Pullups 0=seleção individual pelo WPU
   IOC =      0b00010100;      //Port on change mask (1=Enabled)
   Temp = input_a();
   
   enable_interrupts(INT_RA);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      //TODO: User Code
   }

}


This works ok even without the 2 port reads:
Code:

#include <main.h>
#USE FAST_IO (A)
#byte WPU = 0x95    //Pullups 1=ativado
#bit GPPU = 0x81.7  //Pullups global 0=seleção individual
int8 Temp;

#INT_RA
void  RA_isr(void)
{
   Temp = input_a();
   clear_interrupt(INT_RA);
   output_toggle(PIN_A5);
   delay_ms(100);
}

void main()
{
   set_tris_a(0b11011111);     //0=saída 1=entrada
   WPU =      0b00000000;      //Pullups 0=ativado 1=desativado
   GPPU = 0;                   //Global Pullups 0=seleção individual pelo WPU
   Temp = input_a();
   
   enable_interrupts(INT_RA2);
   enable_interrupts(INT_RA4);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      //TODO: User Code
   }

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Sun May 10, 2020 1:46 am     Reply with quote

Enabling INT_RA, without specifying any pin, automatically sets
all the bits in the IOC register 'on'. Overrides what you have already
written to this register....

In fact you can 'OR' combine multiple pins in one enable:

enable_interrupts(INT_RA2 | INT_RA4);

Potentially tidier.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 10, 2020 2:33 am     Reply with quote

Your code is disabling the pull-up resistors.
The WPU comments below are wrong. You have it backwards.
ChicoCyber wrote:


void main()
{
set_tris_a(0b11011111); //0=saída 1=entrada
WPU = 0b00000000; //Pullups 0=ativado 1=desativado
GPPU = 0; //Global Pullups 0=seleção individual pelo WPU
IOC = 0b00010100; //Port on change mask (1=Enabled)
Temp = input_a();


A logic '1' turns on each pull-up. The 12F675 datasheet says:
Quote:
REGISTER 3-3: WPU: WEAK PULL-UP REGISTER (ADDRESS: 95h)

bit 7-6 Unimplemented: Read as ‘0’

bit 5-4 WPU<5:4>: Weak Pull-up Register bit
1 = Pull-up enabled
0 = Pull-up disabled

bit 3 Unimplemented: Read as ‘0’
bit 2-0 WPU<2:0>: Weak Pull-up Register bit
1 = Pull-up enabled
0 = Pull-up disabled
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun May 10, 2020 4:45 am     Reply with quote

also...
CCS will(should) add the 'clear_interupt' automatically,so you don't need to ....

having delay_ms(100); inside the ISR is 'bad' programming.
ISRs are supposed to be short and fast. Set a few bits or bytes( flags) then exit. delays, prints and 'math' should be avoided within ISRs.
ChicoCyber



Joined: 09 May 2020
Posts: 7

View user's profile Send private message

PostPosted: Sun May 10, 2020 4:42 pm     Reply with quote

Ttelmah wrote:
Enabling INT_RA, without specifying any pin, automatically sets
all the bits in the IOC register 'on'. Overrides what you have already
written to this register....

In fact you can 'OR' combine multiple pins in one enable:

enable_interrupts(INT_RA2 | INT_RA4);

Potentially tidier.


This explains a lot! Thank you!
ChicoCyber



Joined: 09 May 2020
Posts: 7

View user's profile Send private message

PostPosted: Sun May 10, 2020 4:44 pm     Reply with quote

PCM programmer wrote:
Your code is disabling the pull-up resistors.
The WPU comments below are wrong. You have it backwards.
ChicoCyber wrote:


void main()
{
set_tris_a(0b11011111); //0=saída 1=entrada
WPU = 0b00000000; //Pullups 0=ativado 1=desativado
GPPU = 0; //Global Pullups 0=seleção individual pelo WPU
IOC = 0b00010100; //Port on change mask (1=Enabled)
Temp = input_a();


A logic '1' turns on each pull-up. The 12F675 datasheet says:
Quote:
REGISTER 3-3: WPU: WEAK PULL-UP REGISTER (ADDRESS: 95h)

bit 7-6 Unimplemented: Read as ‘0’

bit 5-4 WPU<5:4>: Weak Pull-up Register bit
1 = Pull-up enabled
0 = Pull-up disabled

bit 3 Unimplemented: Read as ‘0’
bit 2-0 WPU<2:0>: Weak Pull-up Register bit
1 = Pull-up enabled
0 = Pull-up disabled


I have noticed that soon as posted here, just writed the comment wrong.
Thank you for the advice :D
ChicoCyber



Joined: 09 May 2020
Posts: 7

View user's profile Send private message

PostPosted: Sun May 10, 2020 4:48 pm     Reply with quote

temtronic wrote:
also...
CCS will(should) add the 'clear_interupt' automatically,so you don't need to ....

having delay_ms(100); inside the ISR is 'bad' programming.
ISRs are supposed to be short and fast. Set a few bits or bytes( flags) then exit. delays, prints and 'math' should be avoided within ISRs.


Got it, thank you.

Actually what I need is very simple but as I'm not so used to program this it is getting very hard, I dont know very well how to join the interrupt things with the main code, or what to put each thing.
I just want to solve it quickly, even it is a little dirty.

I want to make a timer, one button starts and stops, another one sums +5 minutes.
After the time it beeps and turns off the device.
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