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

Enabling Interrupts for Change on Pin

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



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

Enabling Interrupts for Change on Pin
PostPosted: Fri Apr 25, 2014 11:04 am     Reply with quote

I'm using a 12LF1552. I want the cpu to sleep until a particular input pin (A1) changes state, then wake up. But I can't get it to work.

On power-up:
set_tris_a( 0x0B ); // Bits 0,1,3 = inputs; Bits 2,4,5,6,7 = outputs.
enable_interrupts(GLOBAL);

Main Loop:
while(1) {
do_some_stuff();
enable_interrupts(INT_RA1);
sleep();
}

My ISR:
#INT_RA
void RA1_isr()
{
disable_interrupts(INT_RA1);
}

Is there something wrong with the process?[/code]
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

re
PostPosted: Fri Apr 25, 2014 11:30 am     Reply with quote

Use Code button to present your code.
Post the entire code (it doesnt seems to be huge).

Your ISR function should be defined/declared before the main one.
enable_interrupts(INT_RA1); should be declared before GLOBAL not necessary to enabled into the infinite loop.
_________________
A person who never made a mistake never tried anything new.
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 12:11 pm     Reply with quote

The code is small. And what I posted is about 90% of it. Don't see how the rest helps.
I use function prototypes, which means I don't have to locate functions before main(). I have never had a problem putting ISR's at the end of the source code. And I always have main() as the first function in the file. It's easier to find quickly.

Code flow:
1. Power-up
2. Initialize CPU and I/O.
3. Program synthesizer.
4. Enable Interrupt in Pin A1.
5. Sleep.
6. State change on A1 wakes up CPU.
7. Jump to step 3.


Code:

void main()
{
   Init();
    
   while( TRUE )
   {
      // Get selected band to program.
      pReg = ( input(BAND) ) ? highband_data:lowband_data;

      // Program synthesizer for band.
      ProgramSynthesizer( pReg );

      enable_interrupts(INT_RA1);

      sleep();

   }
}

void Init()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit);      //1.0 ms overflow

   set_tris_a( 0x0B );   // Bits 0,1,3 = inputs; Bits 2,4,5,6,7 = outputs.

   delay_ms(250);

   clear_interrupt(INT_RA1);

   enable_interrupts(GLOBAL);

}

#INT_RA
void  RA1_isr(void)
{
   disable_interrupts(INT_RA1);
}
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Apr 25, 2014 12:21 pm     Reply with quote

see this post:
especially item 4
http://www.ccsinfo.com/forum/viewtopic.php?t=26245

i want to be able to make it compile before i'll bother any further.
what you posted will NOT compile in a useful way.
need the FUSES etc - in short THE WHOLE attempt at a working program.
as rikotech8 said ......
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 12:35 pm     Reply with quote

You need to make a dummy read of a port A (inside ISR functionn) so interrupt flag can be cleared.
Something like this:
Code:

void RA1_isr()
{
if(input_a());     //if non zero, do nothing
disable_interrupts(INT_RA1);
}


Also, have you tried a simple blinking led program (let say 1Hz) to see if the configurations and timing are properly set?
_________________
A person who never made a mistake never tried anything new.
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 1:10 pm     Reply with quote

The whole thing.
Code:

#include <12LF1552.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>

#device ADC=16

#ZERO_RAM

#FUSES NOWDT                   //No Watch Dog Timer
#FUSES NOPUT                   //No Power Up Timer
#FUSES MCLR                    //Master Clear pin enabled
#FUSES NOPROTECT               //Code not protected from reading
#FUSES NOBROWNOUT              //No brownout reset
#FUSES NOCLKOUT                //I/O function on OSC2
#FUSES NOWRT                   //Program memory not write protected
#FUSES STVREN                  //Stack full/underflow will cause reset
#FUSES BORV19                  //Brownout reset at 1.9V
#FUSES NOLPBOR                 //Low-Power Brownout reset is disabled
#FUSES LVP                       //low voltage programming

#use delay(internal=4000000)
#use FAST_IO(A)

#define TP      PIN_A0
#define BAND   PIN_A1
#define SCK   PIN_A2
#define SEN   PIN_A4
#define SDI   PIN_A5

typedef int1              BOOL; // 1-bit
typedef int1              bit;  // 1-bit
typedef unsigned int32    u32;  // 32-bits, unsigned
typedef signed int32      i32;   // 32-bits
typedef unsigned int      USI;  // 8-bits

// Function Prototypes
void   main(void);
void   ProgramSynthesizer( u32 *p );
void   Init(void);
void   SerInit(void);
void   SetRegisters(u32 *p);
void   SetReg(u32 data);
byte   SerRead(void);
void   SerWrite(byte numBits, byte data);
void   ToggleClk(void);
void   SerStart(void);
void   SerEnd(void);
u32   GetReg(byte);

// *** 7.000GHz
const i32 lowband_data[] = {
   0x02000004,   //  1 - Register 2 = 0x04   (R)
   0x0300008C,   //  2 - Register 3 = 0x8C   (N)
   0x05006095,   //  4 - Register 5 = 0x006095   // was: 0x05C10205
   0x062003CA,   //  5 - Register 6 = 0x2003CA
   0x0700044D,   //  6 - Register 7 = 0x044D   
   0x0809BEFF,   //  7 - Register 8 = 0x09BEFF
   0x098DBFFF,   //  8 - Register 9 = 08ADBFFF
   0x0A002205,   //  9 - Register A = 0x002205
   0x0B0F8071,   // 10 - Register B = 0x0F8071
   0x0F000081    // 14 - Register F = 0x81            //0x01
};

// *** 7.250GHz
const i32 highband_data[] = {
   0x02000004,   //  1 - Register 2 = 0x04   (R)
   0x03000091,   //  2 - Register 3 = 0x91   (N)
   0x05006095,   //  4 - Register 5 = 0x006095
   0x062003CA,   //  5 - Register 6 = 0x2003CA
   0x07000C4D,   //  6 - Register 7 = 0x0C4D   
   0x0809BEFF,   //  7 - Register 8 = 0x09BEFF
   0x098DBFFF,   //  8 - Register 9 = 0x8DBFFF
   0x0A002205,   //  9 - Register A = 0x002205
   0x0B078071,   // 10 - Register B = 0x078071
   0x0F000081    // 14 - Register F = 0x81            //0x01
};

void main()
{
   Init();
    
   while( TRUE )
   {
      // Get selected band to program.
      pReg = ( input(BAND) ) ? highband_data:lowband_data;

      // Program synthesizer for band.
      ProgramSynthesizer( pReg );

      enable_interrupts(INT_RA1);

      sleep();

   }
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Program synthesizer for selected RF Band.

Arg1:   p - Pointer to systhesizer register data.
------------------------------------------------------------------------------------------------------------*/
void ProgramSynthesizer( u32 *p )
{
   SerInit();
   SetReg( (i32)1 );      // Reset synthesizer
   delay_ms(100);
   SetRegisters(p);      // Write data to registers
   SerEnd();
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Writes all the registers of the synthesizer in the selected register array.

Arg1:   p - Pointer to register array.
------------------------------------------------------------------------------------------------------------*/
void SetRegisters( u32 *p )
{
   int nRegs, Reg;
   nRegs = sizeof(lowband_data) >> 2;  // Number of registers to program
   for ( Reg = 0; Reg < nRegs; Reg++) {
      SetReg( p[Reg] );
      delay_us(10);
   }
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Write 32-bits of data to selected synthesizer register. The data contains the register address.

Arg1:   data - Register Data to write.
------------------------------------------------------------------------------------------------------------*/
void SetReg( u32 data )
{
   byte b[4];

   // Separate value into bytes.
   b[3] = make8(data,3) << 2;      // Register Address
   b[2] = make8(data,2);         // Data bits: 23-16
   b[1] = make8(data,1);         // Data bits: 15-8
   b[0] = make8(data,0);         // Data bits: 7-0

   // Enable Chip
   SerStart();

   // Send Register data.
   SerWrite( 6, b[3] );
   SerWrite( 8, b[2] );
   SerWrite( 8, b[1] );
   SerWrite( 8, b[0] );

   ToggleClk();

   SerInit();

   delay_us(1);
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Write a byte of data out serial port, MSB first.
------------------------------------------------------------------------------------------------------------*/
void SerWrite( byte numBits, byte data )
{
   byte mask;

   for ( mask = 128; numBits; numBits--, mask >>= 1 ) {
      if (mask & data)   output_high(SDI); //output_float(SDI);
      else                     output_low(SDI);
      ToggleClk();
   }
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Generate a Write Start signal to the synthesizer.
------------------------------------------------------------------------------------------------------------*/
void SerStart()
{
   output_high(SEN);
   output_low(SDI);
   delay_us(1);
   ToggleClk();
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Initialize serial port to prepare for writing.
------------------------------------------------------------------------------------------------------------*/
void SerInit()
{
   output_low(SEN);
   delay_us(1);
   output_high(SDI);
   output_low(SCK);
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Set serial port pins to low to disable serial interface.
------------------------------------------------------------------------------------------------------------*/
void SerEnd()
{
   output_low(SEN);
   output_low(SCK);
   output_low(SDI);
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Power-up initialization.
------------------------------------------------------------------------------------------------------------*/
void Init()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit);      //1.0 ms overflow

   set_tris_a( 0x0B );   // Bits 0,1,3 = inputs; Bits 2,4,5,6,7 = outputs.

   delay_ms(250);

   clear_interrupt(INT_RA1);

   enable_interrupts(INT_RA1);

   enable_interrupts(GLOBAL);

}

/*------------------------------------------------------------------------------------------------------------
Summary:   Generate a 20us clock pulse.
------------------------------------------------------------------------------------------------------------*/
void ToggleClk()
{
   delay_us(1);
   output_high(SCK);
   delay_us(1);
   output_low(SCK);
   delay_us(1);
}


/*------------------------------------------------------------------------------------------------------------
Summary:   Interrupt Service Routine for Port A, bit 1. This ISR is called when Port A, bit 1, changes state.
------------------------------------------------------------------------------------------------------------*/
#INT_RA
void  RA1_isr(void)
{
   disable_interrupts(INT_RA1);
}

/*------------------------------------------------------------------------------------------------------------
Summary:   Interrupt Service Routine for Timer 0. (NOT USED)
------------------------------------------------------------------------------------------------------------*/
#int_TIMER0
void  TIMER0_isr(void)
{
  /*static bit i;
  if ( i )  output_high(SDI);
  else      output_low(SDI);
  i  = !i;*/
  //ToggleClk();

}

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 1:49 pm     Reply with quote

1. What is your CCS compiler version ?

2. Describe the external circuit on Pin A1, in detail.

Quote:
#FUSES LVP

3. Why is this fuse set ? What programmer are you using ?
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 2:59 pm     Reply with quote

Compiler is v5.025.
Programmer is ICD-U64 with CCSLoad.
The circuit on pin A1 is a 10k pull-up to 3.3V. I use a wire, connected to ground, to touch the input and bring it to ground or let it be pulled-up.
The fuse "LVP" is there because the CCS Project Wizard put it there.

Everything except the interrupt-on-change works in the program. The Timer 0 interrupt works, the I/O works, I can program the external synthesizer chip just fine. It all works...except for interrupt-on-change.

FYI, per rikotech8's suggestion, I added a statement to read port A in the interrupt handler, and it made no difference.

byte a;
a = input_a();

It acts like the interrupt is not being enabled. I notice in the 1552 header file that there are defines for INT_RA, INT_RA1, INT_RA1_L2H, and INT_RA1_H2L.

Could it be that I'm not using the correct interrupt defines? I want the interrupt to fire whenever A1 changes state. Should I do something like:

enable_interrupts(INT_RA1_L2H);
enable_interrupts(INT_RA1_H2L);

Do I also need to do a separate enable for the port as a whole?

enable_interrupts(INT_RA);
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Apr 25, 2014 3:31 pm     Reply with quote

Quote:

The interrupt source
must have the appropriate Interrupt Enable bit(s) set
prior to entering Sleep.

On waking from Sleep, if the GIE bit is also set, the
processor will branch to the interrupt vector. Otherwise,
the processor will continue executing instructions after
the SLEEP instruction. The instruction directly after the
SLEEP instruction will always be executed before
branching to the ISR.


your MAIN code seems to be OK as far as the "on waking response"
i'm betting the issue is improper int enable setup

the .LST file might be a good place to investigate this

JUST to humor an old fellow
try putting your MAIN LAST in the program .....
and see if it matters??
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 3:51 pm     Reply with quote

Moving main() to the bottom of the file made no difference.

What did make a difference was to change the interrupt enables to this:

enable_interrupts(INT_RA1_L2H);
enable_interrupts(INT_RA1_H2L);

Now it works.
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