Forums

HC11 IC2 and IC3 Interrupt Problems (Possibly dealing with ImageCraft IC11)

Started by richard.danna January 6, 2006
Hi,

I am doing a senior design project at the University of Alabama at
Birmingham. I am building a robot, and I am using the microStamp11
chip for some of the robot's simple operations. The microStamp11
chip is notorious for being the world's smallest HC11 chip. I am
using the ImageCraft IC11 environment to compile my code and create
Motorola .s19 files. I have written several fully functional
programs thusfar, but I am running into some issues with interrupt
handling. Below is my interrupt handler and declaration statements,
including the necessary pragma. Now, IC1 (Input Capture 1) works
correctly, but I need IC2 (Input Capture 2) to work correctly as
well. I have set IC2 up in the same fashion as IC1, updated the
differing information (pragma address for sure), and yet only IC1
works. I have an IC3 as well, and it follows the same pattern as the
aforementioned two. Essentially, I have optical encoders that send
voltage signals to the pins associated with the Input Capture
Interrupts on the microStamp11. Note: as mentioned earlier, IC1
works perfectly for this. I then, in the interrupt handler,
increment the number of times via an int that a signal has been sent
and drive an output pin on Port A to light an LED. I want IC2 to do
the same thing as IC1, but for a different LED. I know that the
hardware is set up correctly, and as far as I can tell, so is the
software. My initialize function is shown at the bottom. I am
wondering if there are some issues with ImageCraft compiling C
to .s19 files dealing with interrupt handlers. I know that the
handler functions correctly, the correct pragma address is assigned,
and that all IC interrupts are enabled. In the interrupt handlers, I
even clear the flag for the respective interrupt as I am supposed
to. Please help me with this problem, for my senior design project
is at a standstill because of it. Note: the code for IC2 and IC3 are
identical to IC1 with the exception of the leftTicks variable
becomes the rightTicks variable, and PA3 is driven high to light a
different LED. IC1 works, but for some reason IC2 and IC3 do not.
The initialize function shown at the bottom is called from main
before a constant while loop.

// Sets IC1 interrupt vector
extern void IC1han();
#pragma abs_address:0xffee;
void (*IC1_handler[])() = {IC1han};
#pragma end_abs_address
/* Name: IC1han
* Args: none
* Desc: IC1 interrupt handler for PA2 (6)
*/
#pragma interrupt_handler IC1han()
void IC1han(void) {
// If rising edge is detected
if (TCTL2 == 0x10) {
// Begins timing the pulse
startPulse = TIC1;

// Pin 7 on Port A latched high (set as output)
PACTL |= 0x80;
// Increments the number of left tick marks
leftTicks = leftTicks + 1;
// Sets the left tick mark string
itoa(left, leftTicks, 10);
// Manages tick mark information
if (leftTicks == 45) {
leftRevs = leftRevs + 1;
itoa(lRev, leftRevs, 10);
leftTicks = 1;
itoa(left, leftTicks, 10);
}

// Writes to the screen indicating tick mark
OutString("Left...");
OutChar(CR);
OutChar(LF);
OutString(left);
OutChar(CR);
OutChar(LF);
OutString("Time...");
OutChar(CR);
OutChar(LF);
itoa(timer, time, 10);
OutString(timer);
OutChar(CR);
OutChar(LF);

// Sets for falling edge
TCTL2 = 0x20;
// If falling edge is detected
} else {
// Measures the pulse width
if (startPulse < TIC1) {
pulseWidth = TIC1 - pulseWidth;
} else {
pulseWidth = 65536 - startPulse + TIC1;
}
// Pin 7 on Port A latched low (set as input)
PACTL &= 0x78;
// Sets for rising edge
TCTL2 = 0x10;
}
// Sets flag to indicate IC1 occured
TFLG1 = IC1;
}

void init(void) {
// Disables all interrupts
asm("sei");
// Disables the watchdog timer (Bit 3 high)
CONFIG = 0x04;
// Sets the baud value
BAUD = BAUD9600;
// Sets RS232 to recieve data
SCCR1 = 0x00;
SCCR2 = 0x0C;
// Sets the variables
time = 0;
leftTicks = 0;
rightTicks = 0;
leftRevs = 0;
rightRevs = 0;
// Clears / enables the interrupts
TFLG1 = OC4;
TMSK2 = 0x00;
TMSK1 |= OC4;
TFLG1 = IC3;
TMSK1 |= IC3;
TFLG1 = IC2;
TMSK1 |= IC2;
TFLG1 = IC1;
TMSK1 |= IC1;

// Sets the TCTL values
TCTL1 = OM4; // Sets output low
TCTL2 = 0x10; // Sets rising edge

// Sets cycle to every ms
TOC4 = TCNT + TICK1uS;
// Enables all interrupts
asm("cli");
}


Hi Richard, richard.danna wrote:
> // Sets IC1 interrupt vector
> extern void IC1han();
> #pragma abs_address:0xffee;
> void (*IC1_handler[])() = {IC1han};
> #pragma end_abs_address
> /* Name: IC1han
> * Args: none
> * Desc: IC1 interrupt handler for PA2 (6)
> */
> #pragma interrupt_handler IC1han()
> void IC1han(void) {
> // If rising edge is detected
> if (TCTL2 == 0x10) {
>
TCTL2 won't be 0x10 if you have enabled caputure on IC2 or IC3. You
should only check for the two bits associated with IC1

> // Begins timing the pulse
> startPulse = TIC1;
>
> // Pin 7 on Port A latched high (set as output)
> PACTL |= 0x80;
> // Increments the number of left tick marks
> leftTicks = leftTicks + 1;
> // Sets the left tick mark string
> itoa(left, leftTicks, 10);
> // Manages tick mark information
> if (leftTicks == 45) {
> leftRevs = leftRevs + 1;
> itoa(lRev, leftRevs, 10);
> leftTicks = 1;
> itoa(left, leftTicks, 10);
> }
>
> // Writes to the screen indicating tick mark
> OutString("Left...");
> OutChar(CR);
> OutChar(LF);
> OutString(left);
> OutChar(CR);
> OutChar(LF);
> OutString("Time...");
> OutChar(CR);
> OutChar(LF);
> itoa(timer, time, 10);
> OutString(timer);
> OutChar(CR);
> OutChar(LF);
>
> // Sets for falling edge
> TCTL2 = 0x20;
>
Setting TCTL2 to 0x20, will disable input captures for IC2 and IC3, as
there control bits will be zero.

> // If falling edge is detected
> } else {
> // Measures the pulse width
> if (startPulse < TIC1) {
> pulseWidth = TIC1 - pulseWidth;
> } else {
> pulseWidth = 65536 - startPulse + TIC1;
> }
> // Pin 7 on Port A latched low (set as input)
> PACTL &= 0x78;
> // Sets for rising edge
> TCTL2 = 0x10;
>
As above
> }
> // Sets flag to indicate IC1 occured
> TFLG1 = IC1;
> }
>
> void init(void) {
> // Disables all interrupts
> asm("sei");
> // Disables the watchdog timer (Bit 3 high)
> CONFIG = 0x04;
> // Sets the baud value
> BAUD = BAUD9600;
> // Sets RS232 to recieve data
> SCCR1 = 0x00;
> SCCR2 = 0x0C;
> // Sets the variables
> time = 0;
> leftTicks = 0;
> rightTicks = 0;
> leftRevs = 0;
> rightRevs = 0;
> // Clears / enables the interrupts
> TFLG1 = OC4;
> TMSK2 = 0x00;
> TMSK1 |= OC4;
> TFLG1 = IC3;
> TMSK1 |= IC3;
> TFLG1 = IC2;
> TMSK1 |= IC2;
> TFLG1 = IC1;
> TMSK1 |= IC1;
>
> // Sets the TCTL values
> TCTL1 = OM4; // Sets output low
> TCTL2 = 0x10; // Sets rising edge
>
> // Sets cycle to every ms
> TOC4 = TCNT + TICK1uS;
> // Enables all interrupts
> asm("cli");
> } >
Also, as other people have pointed out, way too much stuff in the
interrupt routines.

Cheers
David



>>> That is not my final code. However, when only the code for IC2
exists, it still does not work. IC1 works when IC2 is not present. I
am beginning to think that the Pins on the microStamp11 for IC2 and
IC3 are bad. My IC2 code is nearly identical to IC1, and there is no
reason for it not to be working (hardware wise as well). Thank you!
Do you have any additional input on this?
---Richard <<< --- In m68HC11@m68H..., David Simpson <david@a...> wrote:
>
> Hi Richard, > richard.danna wrote:
> > // Sets IC1 interrupt vector
> > extern void IC1han();
> > #pragma abs_address:0xffee;
> > void (*IC1_handler[])() = {IC1han};
> > #pragma end_abs_address
> > /* Name: IC1han
> > * Args: none
> > * Desc: IC1 interrupt handler for PA2 (6)
> > */
> > #pragma interrupt_handler IC1han()
> > void IC1han(void) {
> > // If rising edge is detected
> > if (TCTL2 == 0x10) {
> >
> TCTL2 won't be 0x10 if you have enabled caputure on IC2 or IC3. You
> should only check for the two bits associated with IC1
>
> > // Begins timing the pulse
> > startPulse = TIC1;
> >
> > // Pin 7 on Port A latched high (set as output)
> > PACTL |= 0x80;
> > // Increments the number of left tick marks
> > leftTicks = leftTicks + 1;
> > // Sets the left tick mark string
> > itoa(left, leftTicks, 10);
> > // Manages tick mark information
> > if (leftTicks == 45) {
> > leftRevs = leftRevs + 1;
> > itoa(lRev, leftRevs, 10);
> > leftTicks = 1;
> > itoa(left, leftTicks, 10);
> > }
> >
> > // Writes to the screen indicating tick mark
> > OutString("Left...");
> > OutChar(CR);
> > OutChar(LF);
> > OutString(left);
> > OutChar(CR);
> > OutChar(LF);
> > OutString("Time...");
> > OutChar(CR);
> > OutChar(LF);
> > itoa(timer, time, 10);
> > OutString(timer);
> > OutChar(CR);
> > OutChar(LF);
> >
> > // Sets for falling edge
> > TCTL2 = 0x20;
> >
> Setting TCTL2 to 0x20, will disable input captures for IC2 and IC3,
as
> there control bits will be zero.
>
> > // If falling edge is detected
> > } else {
> > // Measures the pulse width
> > if (startPulse < TIC1) {
> > pulseWidth = TIC1 - pulseWidth;
> > } else {
> > pulseWidth = 65536 - startPulse + TIC1;
> > }
> > // Pin 7 on Port A latched low (set as input)
> > PACTL &= 0x78;
> > // Sets for rising edge
> > TCTL2 = 0x10;
> >
> As above
> > }
> > // Sets flag to indicate IC1 occured
> > TFLG1 = IC1;
> > }
> >
> > void init(void) {
> > // Disables all interrupts
> > asm("sei");
> > // Disables the watchdog timer (Bit 3 high)
> > CONFIG = 0x04;
> > // Sets the baud value
> > BAUD = BAUD9600;
> > // Sets RS232 to recieve data
> > SCCR1 = 0x00;
> > SCCR2 = 0x0C;
> > // Sets the variables
> > time = 0;
> > leftTicks = 0;
> > rightTicks = 0;
> > leftRevs = 0;
> > rightRevs = 0;
> > // Clears / enables the interrupts
> > TFLG1 = OC4;
> > TMSK2 = 0x00;
> > TMSK1 |= OC4;
> > TFLG1 = IC3;
> > TMSK1 |= IC3;
> > TFLG1 = IC2;
> > TMSK1 |= IC2;
> > TFLG1 = IC1;
> > TMSK1 |= IC1;
> >
> > // Sets the TCTL values
> > TCTL1 = OM4; // Sets output low
> > TCTL2 = 0x10; // Sets rising edge
> >
> > // Sets cycle to every ms
> > TOC4 = TCNT + TICK1uS;
> > // Enables all interrupts
> > asm("cli");
> > }
> >
> >
> >
> Also, as other people have pointed out, way too much stuff in the
> interrupt routines.
>
> Cheers
> David
>




richard.danna wrote:
>>>> That is not my final code. However, when only the code for IC2
>>>>
> exists, it still does not work. IC1 works when IC2 is not present. I
> am beginning to think that the Pins on the microStamp11 for IC2 and
> IC3 are bad. My IC2 code is nearly identical to IC1, and there is no
> reason for it not to be working (hardware wise as well). Thank you!
> Do you have any additional input on this?
> ---Richard <<< >
Hi Richard,

Please post you final code so we can have a look at it. It is very hard
to guess what is wrong if we don't exactly what you have coded.

Cheers
David


>>> The TCTL2 was the problem. I feel awfully ignorant right now. :)
Thank you all for the help. IC1, IC2, and IC3 are all working now,
and I have made my interrupt handlers as short as possible. Timing
does not seem to be an issue anymore, for it is correctly counting
the encoder module data. I am going to take all of the suggestions
made by everyone and implement them into my code. I can now breathe a
sigh of relief. Now, I get to work on the OOBot40-3 or the PC-104.
Woohoo! Anyone familiar with either of those? *L*
---Richard <<< --- In m68HC11@m68H..., David Simpson <david@a...> wrote:
>
> richard.danna wrote:
> >>>> That is not my final code. However, when only the code for IC2
> >>>>
> > exists, it still does not work. IC1 works when IC2 is not
present. I
> > am beginning to think that the Pins on the microStamp11 for IC2
and
> > IC3 are bad. My IC2 code is nearly identical to IC1, and there is
no
> > reason for it not to be working (hardware wise as well). Thank
you!
> > Do you have any additional input on this?
> > ---Richard <<<
> >
> >
> >
> Hi Richard,
>
> Please post you final code so we can have a look at it. It is very
hard
> to guess what is wrong if we don't exactly what you have coded.
>
> Cheers
> David
>




richard.danna wrote:
>>>>The TCTL2 was the problem. I feel awfully ignorant right now. :)
>

As Will Rogers used to say, "Everyone is ignorant, just about
different things." This is just one less thing you are ignorant
about.

> Thank you all for the help. IC1, IC2, and IC3 are all working now,
> and I have made my interrupt handlers as short as possible. Timing

This, in itself, is a valuable lesson. My first interrupt handler
(written in 1982 or so) was short and did next to nothing, and
worked. My second one was more elaborate, and did much more
work, and occasionally my application failed. Every interrupt handler
I've written since (and I have written a few) have been short.
I put just enough into them to make the hardware happy, and then
get out. I've fixed three complex embedded applications which had long
standing rare failure modes by following this dictum. In a
multitasking environment, I let the task level do most of the work.
In other environments, I let the main loop check a flag set by
the handler. In any case, the handler does as little as it can.

There are circumstances where that is not best. No rule is hard
and fast. Sometimes it is best to do all the work in the handler.
This is not usually the case.

[snip]

Mike
--
p="p=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p,34,p,34);}
This message made from 100% recycled bits.
You have found the bank of Larn.
I can explain it for you, but I can't understand it for you.
I speak only for myself, and I am unanimous in that!