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

12F1822 Simple Interrupt_On_change does not work

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



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

12F1822 Simple Interrupt_On_change does not work
PostPosted: Mon Nov 21, 2011 7:11 am     Reply with quote

Simple program to test/simulate an Interrupt on change at RA3.
IOCAP & IOCAN registers work fine, IOCAF is always zero.
IDE, PCB and PCM version 4.127 (latest).
Remark, this is just a stupid test-program and does nothing.
How do I manage to increase the counter variable by PortA?

Code:

#include <12F1822.H>
#Device ADC=10
#FUSES INTRC_IO, NOMCLR, CPD,PROTECT, NOWDT, BROWNOUT, PUT
#use delay(clock=16000000)                         
#use fast_io(A)

#bit RXDTSEL = 0x11D.7
#bit SDOSEL  = 0x11D.6
#bit SSSEL   = 0x11D.5
#bit T1GSEL  = 0x11D.3
#bit TXCKSEL = 0x11D.2
#bit P1BSEL  = 0x11D.1
#bit CCP1SEL = 0x11D.0

//#define  POTM           PIN_A0    //pin7           analoog input     
#define    LED            PIN_A1    //pin6           digital output 
#define    PWM            PIN_A2    //pin5           PWM output
#define    PPM            PIN_A3    //pin4           digital input   1K pull-up external
//#define  LDR            PIN_A4    //pin3           analoog input 
#define    PIR            PIN_A5    //pin2           digital input  10K pull-up external

int    counter=0;
long   loop_counter=0;

#INT_RA
void ra_isr()
     {
     counter = counter+1;
     }

//====================================
void main()
{
setup_oscillator(OSC_16MHZ);
setup_comparator(NC_NC);
setup_adc_ports(sAN0|sAN3||VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);                                 // Built-in A/D setup function TAD
setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_256);                 //
set_timer0 (0);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);                     //
setup_timer_2(T2_DIV_BY_1, 127, 1);                         // 31.2kHz
setup_ccp1(CCP_PWM);                                        // Configure CCP1 as a PWM

set_tris_a    (0x39);       //  111001  (0=output)      5 4 3 2 1 0
PORT_a_PULLUPS(0x00);       //  000000  (1=enabled)     5 4 3 2 1 0

enable_interrupts   (INT_RA3);
enable_interrupts   (GLOBAL);

RXDTSEL = 0;
SDOSEL  = 0;
SSSEL   = 0;
T1GSEL  = 1;
TXCKSEL = 0;
P1BSEL  = 0;
CCP1SEL = 0;

while  (1)
       {
////////////////////////////////////////////////////////////////////////////////
       output_low (LED); 
       loop_counter=0;
       while (loop_counter<=7600)
             { 
             loop_counter=loop_counter+1;          //Vertraging van 25mSec
             }
//////
       output_high (LED);   
       loop_counter=0;
       while (loop_counter<=7600)
             { 
             loop_counter=loop_counter+1;          //Vertraging van 25mSec
             }
      set_pwm1_duty (64);     
      }
}
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Nov 21, 2011 7:57 am     Reply with quote

In all interrupt service routines (isr) you must clear the source of the interrupt. In this case you must read port a in ra_isr().

RF Developer
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

PostPosted: Mon Nov 21, 2011 8:41 am     Reply with quote

I know, to reset the isr I must read the port but the reset of the interrupt is not the problem.
The real problem is the IOCAF register is always zero, so the program does NEVER reach the interrupt. So again the problem is not to leave the interrupt but to GO TO the interrupt.
I only simulated this program with MPlab and the Asynchronous PIN simulus but for hours.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 21, 2011 5:35 pm     Reply with quote

I was able to make it work in hardware. I used compiler vs. 4.127 with a
Microchip "low pin count" board. I have Pin A1 jumpered over to one of
the LEDs on the board. When I press the push-button switch, the LED
toggles. I supply +5v power to the board from a bench power supply.
The ICD3 doesn't power the board.
Code:

#include <12F1822.H>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOMCLR
#use delay(clock=4M)

#define LED_PIN  PIN_A1

#byte IOCAF = getenv("SFR:IOCAF")   
#define clear_IOCA_flags() IOCAF = 0

#int_ra
void ra_isr(void)
{
output_toggle(LED_PIN);

delay_ms(10);   // Debounce delay for testing purposes

clear_IOCA_flags();   // Clear flags after the debounce delay
}

//==========================================
void main()
{
output_low(LED_PIN);    // Initialize LED to "Off".
port_a_pullups(0x08);   // Enable pull-up on pin A3

clear_interrupt(INT_RA);   // Clear any existing interrupt condition
clear_IOCA_flags();         // Clear any existing "change" condition
enable_interrupts(INT_RA3_L2H);  // Interrupt when button is released

enable_interrupts(GLOBAL);

while(1);
}
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

Hardware OK, simulation fails
PostPosted: Tue Nov 22, 2011 3:46 am     Reply with quote

Thank you pcm programmer.

The hardware works but the simulation with MPlab does NOT work.

We learned from the past to simulate first with MPlab because the registers of the WATCH window will inform you in an early stage about possible bugs of the CCS compiler. Due to manual bit settings most of the time we were able to make the program working until now.

I only got 1 warning left nr: 225 and it informs about a Duplicate define.

Best regards,
Bas
norman_tan



Joined: 30 Jan 2008
Posts: 27

View user's profile Send private message

INT_TIMER1 will disable INT_RA function in PIC12F1822?
PostPosted: Sat Oct 19, 2019 1:47 am     Reply with quote

Dear PCM programmer,
I read your codes here and change pin_RA3 to pin_RA2, it also works well, very good.
And I add codes of INT_TIMER1(it also works well without enable INT_RA), then I find INT_RA does not work at all now!
Codes as below:
Code:

#include <12F1822.H>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOMCLR
#use delay(clock=8M)

#define LED_PIN  PIN_A1
#define Launch_ON   output_high(PIN_A5)         // For Laser tube control
#define Launch_OFF  output_low(PIN_A5)          // For Laser tube control

#byte IOCAF = getenv("SFR:IOCAF")   
#define clear_IOCA_flags() IOCAF = 0

unsigned char pulse_counter = 0;                // record counting for LS led control in Timer1 interrupt

#int_ra
void ra_isr(void)
{
output_high(LED_PIN);

delay_ms(10);   // Debounce delay for testing purposes

clear_IOCA_flags();   // Clear flags after the debounce delay

output_low(LED_PIN);
}
[color=red]
#INT_TIMER1
void clock1_isr()
{   
   pulse_counter++;
   
   // codes below will generate pulse with period 115uS(_||______) as:
   //  31us high and 84us low with setup_oscillator(OSC_8MHZ);
   if(pulse_counter == 1) Launch_ON;
   else if(pulse_counter == 2) Launch_OFF;
   else if(pulse_counter >= 4) pulse_counter = 0;
   
   set_timer1(0xFFFE); // 31uS/115uS
}[/color]


//==========================================
void main()
{
output_low(LED_PIN);    // Initialize LED to "Off".
port_a_pullups(0x04);   // Enable pull-up on pin A2

clear_interrupt(INT_RA);   // Clear any existing interrupt condition
clear_IOCA_flags();         // Clear any existing "change" condition
enable_interrupts(INT_RA2_L2H);  // Interrupt when button is released

[color=red]set_timer1(0xFFFE); //
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);   // used for pulse generation[/color]

enable_interrupts(GLOBAL);

while(1);
}

And I also found I/O function input(PIN_A2) fails too if INT_TIMER1 used.
Would you please teach me how to solve this problem?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: INT_TIMER1 will disable INT_RA function in PIC12F1822?
PostPosted: Sat Oct 19, 2019 2:48 am     Reply with quote

norman_tan wrote:

And I add codes of INT_TIMER1 (it also works well without enable
INT_RA), then I find INT_RA does not work at all now!


#INT_TIMER1
void clock1_isr()
{
pulse_counter++;

// codes below will generate pulse with period 115uS(_||______) as:
// 31us high and 84us low with setup_oscillator(OSC_8MHZ);
if(pulse_counter == 1) Launch_ON;
else if(pulse_counter == 2) Launch_OFF;
else if(pulse_counter >= 4) pulse_counter = 0;

set_timer1(0xFFFE); // 31uS/115uS
}


//==========================================
void main()
{
output_low(LED_PIN); // Initialize LED to "Off".
port_a_pullups(0x04); // Enable pull-up on pin A2

clear_interrupt(INT_RA); // Clear any existing interrupt condition
clear_IOCA_flags(); // Clear any existing "change" condition
enable_interrupts(INT_RA2_L2H); // Interrupt when button is released

set_timer1(0xFFFE);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1); // used for pulse generation[/color]

enable_interrupts(GLOBAL);

while(1);
}

Your Timer1 reload value of 0xFFFE is way too small, in terms of time.
It's only two instruction cycles before it rolls over to 0x0000 and causes
an interrupt. With Fosc = 8 MHz, the instruction clock is 2 MHz. Each
instruction clock is 1/2 usec. So two clocks is 1 usec. That's your
interrupt rate.

By counting instructions in the .LST file, I calculate that the shortest
path through your Timer1 isr and through the compiler's interrupt handler
code will take about 27 usec. You can't interrupt every 1 usec, and then
take 27 usec (minimum) to process it. Your program will continuously
process the interrupt and them immediately jump right back into it.
There will be no processor time left to run the main program or anything
else. The net effect is that your program will appear to be locked up.

You need to substantially increase the time between Timer1 interrupts.
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Sat Oct 19, 2019 4:41 am     Reply with quote

As a comment, if you want to toggle a pin at that sort of speed, this can be
done using the PWM on pin A2 or A5.
norman_tan



Joined: 30 Jan 2008
Posts: 27

View user's profile Send private message

PostPosted: Sat Oct 19, 2019 8:11 pm     Reply with quote

Dear PCM Programmer and Ttelmah,

Thanks for your kindly reply!

According to advice from email of CCS support, I added command line "if(bit_test(input_a(),2))" in codes, it works well now.

but I will try to change the value in set_timer1(0xFFFE) to get a better pulse too. As said by PCM Programmer, "0xFFFE" will cause interrupt too frequently, hehe.

I also want to try the PWM from RA5, it is the first time I use this small chip, I am not familiar to some functions of it , I will try them.

Thanks again!
norman_tan



Joined: 30 Jan 2008
Posts: 27

View user's profile Send private message

PostPosted: Sat Oct 19, 2019 8:45 pm     Reply with quote

Dear PCM Programmer and Ttelmah,
I tried the PWM function just now according to your history posts as below:
http://www.ccsinfo.com/forum/viewtopic.php?t=46496&highlight=pic12f1822
http://www.ccsinfo.com/forum/viewtopic.php?t=45185&start=1

PWM works on RA2 but not on RA5 even if I change "setup_ccp1(CCP_PWM);" to "setup_ccp1(CCP1_A5); //Put CCP1 output on A5 "

All codes are:
setup_timer_2(T2_DIV_BY_16, 255, 2);
setup_ccp1(CCP_PWM);
//setup_ccp1(CCP1_A5); //Put CCP1 output on A5
set_pwm1_duty(30); // 30/256 duty cycle

At present, I do not know how to use the TRIS to switch PWM generated on RA5.
norman_tan



Joined: 30 Jan 2008
Posts: 27

View user's profile Send private message

PostPosted: Sat Oct 19, 2019 9:09 pm     Reply with quote

Dear PCM Programmer and Ttelmah,
Additional remarks as below:
When I changed "setup_ccp1(CCP_PWM); " to "setup_ccp1(CCP_PWM|CCP1_A5); ", PWM generated on RA5 now, it works!

Thanks!
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Sat Oct 19, 2019 10:52 pm     Reply with quote

Well done. This is where reading what the .h file actually says helps.
Some things are 'single' values, while others need to be ored together
like this.
norman_tan



Joined: 30 Jan 2008
Posts: 27

View user's profile Send private message

PostPosted: Sun Dec 01, 2019 7:34 pm     Reply with quote

Dear PCM Programmer and Ttelmah,
I am very regret that I met an issue as below,
pulse width on PA5 changed to unnormal 19us(interrupt happens on PA2) form normal 9us(no interrupt on PA2)!!!!
and I don't know how to solve it Confused

All codes I attach here:
Code:
#define Launch_ON   output_high(PIN_A5)         // For Laser tube control
#define Launch_OFF  output_low(PIN_A5)          // For Laser tube control

#bit IOCAF_2 = getenv("SFR:IOCAF").2
#define clear_IOCA_2_flags() IOCAF_2 = 0

#int_ra
void ra_isr(void)
{   
   clear_IOCA_2_flags();   // Clear flag of PA2
}

void main()
{
    Initialization();
    while(TRUE)
    {   
         // pulse width on PA5 is 9.2us
         Launch_ON;
         delay_us(8);
         Launch_OFF;
         delay_us(450);
       
    }
}

void Initialization(void)
{
   setup_oscillator(OSC_16MHZ);               // Set the internal oscillator to 16MHz   
   SET_TRIS_A(0x0C);       // 00 1100: Set A5, A4, A1, A0 as output, A3, A2 as input
   port_a_pullups(0x0C);   // Enable pull-up on pin A2
   
   SETUP_ADC_PORTS(NO_ANALOGS);

   // set INT-RA interrupt
   // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   clear_interrupt(INT_RA2);   // Clear any existing interrupt condition
   clear_IOCA_2_flags();         // Clear any existing "change" condition
   enable_interrupts(INT_RA2_L2H);  // Interrupt when button is released
   // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   
   enable_interrupts(global);                   // Enabled all interruptions.
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Dec 01, 2019 8:41 pm     Reply with quote

If you don't want the 9us pulse to be lengthened by an interrupt occurring
during the pulse, then disable interrupts during the pulse. Example:
Quote:
while(TRUE)
{
disable_interrupts(GLOBAL);
Launch_ON;
delay_us(8);
Launch_OFF;
enable_interrupts(GLOBAL);
delay_us(450);
}

If you do it as shown above, then the 450us pulse low time could become 459us
if the interrupt occurs.
norman_tan



Joined: 30 Jan 2008
Posts: 27

View user's profile Send private message

PostPosted: Sun Dec 01, 2019 9:05 pm     Reply with quote

but, I shoud give a fixed period pulse with on PA5, and interrput happens only in the period of PA5 is high
Launch_ON;
delay_us(8);
Launch_OFF;
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