|
|
View previous topic :: View next topic |
Author |
Message |
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
Enabling Interrupts for Change on Pin |
Posted: Fri Apr 25, 2014 11:04 am |
|
|
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
|
re |
Posted: Fri Apr 25, 2014 11:30 am |
|
|
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
|
|
Posted: Fri Apr 25, 2014 12:11 pm |
|
|
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
|
|
Posted: Fri Apr 25, 2014 12:21 pm |
|
|
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
|
|
Posted: Fri Apr 25, 2014 12:35 pm |
|
|
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
|
|
Posted: Fri Apr 25, 2014 1:10 pm |
|
|
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
|
|
Posted: Fri Apr 25, 2014 1:49 pm |
|
|
1. What is your CCS compiler version ?
2. Describe the external circuit on Pin A1, in detail.
3. Why is this fuse set ? What programmer are you using ? |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Fri Apr 25, 2014 2:59 pm |
|
|
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
|
|
Posted: Fri Apr 25, 2014 3:31 pm |
|
|
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
|
|
Posted: Fri Apr 25, 2014 3:51 pm |
|
|
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. |
|
|
|
|
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
|