Forums

Re: HC11 IC2 and IC3 Interrupt Problems (Possibly dealing with Imag...

Started by BobG...@... January 6, 2006

In a message dated 1/6/06 1:41:38 P.M. Eastern Standard Time,
richard.danna@rich... writes:

#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);
===========================
Dont try to write from inside interrupt handler. Not enough time. Just
increment a variable or something. Int hand needs to get in and out faster than
encoder edges.... microseconds...


>>> I will essentially just increment two variables per interrupt
handler in the end. I am including all of the other stuff for
testing purposes only. Yes, my encoders are in the microSecond
range, so I realize that in order to keep up with the encoder, I
need to have minimal code in the handlers, despite the fact that
this is a reasonably low-speed robot application. Thanks for
responding. Do you have any idea about the IC2 and IC3 issue? Even
when I comment out the code for IC1, IC2 does not work. It is set up
in the exact same manner as IC1. All of the hardware is correct and
functional, and the vector address is set for IC2. I am bumfuzzled
as my grandfather would say about this problem.
---Richard <<< --- In m68HC11@m68H..., BobGardner@a... wrote:
>
>
> In a message dated 1/6/06 1:41:38 P.M. Eastern Standard Time,
> richard.danna@y... writes:
>
> #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); >
> ===========================
> Dont try to write from inside interrupt handler. Not enough time.
Just
> increment a variable or something. Int hand needs to get in and
out faster than
> encoder edges.... microseconds... >
>


richard.danna wrote:
> in the exact same manner as IC1. All of the hardware is correct and
> functional, and the vector address is set for IC2. I am bumfuzzled
> as my grandfather would say about this problem.
> ---Richard <<<

Hello Richard,

Have you tried swapping the connections for IC1 and IC2 at the CPU
to verify that your hardware is really doing what you think it is?
If the signal starts coming through on IC2 then you can focus on
the hardware instead. If it doesn't then at least you may rule it
out for now and go back to the software.....

Robert



>>> I have already swapped the connections for IC1 and IC2. When I
moved the IC2 hardware to the IC1 connection, then it worked. I am
positive that the hardware is correct. I have taken almost every
hardware precaution necessary. The only thing that I can't do is
examine the internal components of the HC11 chip itself. *L* Any
suggestions on the software problem? :) Thanks for the reply. <<<
--- In m68HC11@m68H..., "Robert L. Doerr" <rdoerr@b...>
wrote:
>
> richard.danna wrote:
> > in the exact same manner as IC1. All of the hardware is correct
and
> > functional, and the vector address is set for IC2. I am
bumfuzzled
> > as my grandfather would say about this problem.
> > ---Richard <<<
>
> Hello Richard,
>
> Have you tried swapping the connections for IC1 and IC2 at the CPU
> to verify that your hardware is really doing what you think it is?
> If the signal starts coming through on IC2 then you can focus on
> the hardware instead. If it doesn't then at least you may rule it
> out for now and go back to the software.....
>
> Robert
>





In a message dated 1/6/06 1:41:38 P.M. Eastern Standard Time,
richard.danna@rich... writes:

// Sets cycle to every ms
TOC4 = TCNT + TICK1uS;
===========================
What value is TICK1uS? (supposed to be 1000uS right?). If it was too fast it
would hog the cpu in the isr.... looks like that's whats happening?


>>> TICK1uS is roughly equal to 128 microSeconds (error in the
comment for the code). So, are you saying that only IC1 can get
through in that time with the OC4 interrupt being triggered so
often? Why then, if I completely take out the IC1 code and only
leave in the IC2 interrupt code does the IC2 interrupt not work? I
for sure know that it is not a hardware issue (with the exception
that the HC11 is damaged itself). I do know that IC1 has priority
over IC2 (and both have priority over OC4), but if I only have IC2
in there, then it should still work over OC4 like IC1 does. For this
application I plan on having the OC4, IC1, and IC2 interrupts
enabled at all times. The OC4 is triggered I suppose every 128
microSeconds (???) as it stands now. The IC1 and IC2 will be
triggered upon the optical encoder sending a signal. In the end, the
IC1 and IC2 interrupt handlers will be extremely short (updating one
or two variables). What is a good time as opposed to the TICK1uS to
ensure that all interrupts will be seen? I still don't think that
solves my problem, but perhaps we are getting closer. Thank you for
your time. Do you have any other suggestions? I am going to attach
my full code below with the exception of the vector.c Reset vector
declaration.

<<<<<<<<<<<<<< kernel.c >>>>>>>>>>>>>>>>>>
// Includes the standard library
#include <Stdlib.h>

// IF THE PREPROCESSOR VARIABLE IS NOT DEFINED,
#ifndef __HC11_H

// THEN DEFINE IT...
#define __HC11_H 1

// Defines the IO Base for the 8K EEPROM (Leading 0)
#define _IO_BASE 0x00

// Points commands to their proper memory locations on the IO Base
#define PORTA *(unsigned char volatile *)(_IO_BASE + 0x00)
#define PORTD *(unsigned char volatile *)(_IO_BASE + 0x08)
#define DDRD *(unsigned char volatile *)(_IO_BASE + 0x09)
#define PORTCL *(unsigned char volatile *)(_IO_BASE + 0x05)
#define CFORC *(unsigned char volatile *)(_IO_BASE + 0x0B)
#define OC1M *(unsigned char volatile *)(_IO_BASE + 0x0C)
#define OC1D *(unsigned char volatile *)(_IO_BASE + 0x0D)
#define TCNT *(unsigned short volatile *)(_IO_BASE + 0x0E)
#define TIC1 *(unsigned short volatile *)(_IO_BASE + 0x10)
#define TIC2 *(unsigned short volatile *)(_IO_BASE + 0x12)
#define TIC3 *(unsigned short volatile *)(_IO_BASE + 0x14)
#define TOC1 *(unsigned short volatile *)(_IO_BASE + 0x16)
#define TOC2 *(unsigned short volatile *)(_IO_BASE + 0x18)
#define TOC3 *(unsigned short volatile *)(_IO_BASE + 0x1A)
#define TOC4 *(unsigned short volatile *)(_IO_BASE + 0x1C)
#define TOC5 *(unsigned short volatile *)(_IO_BASE + 0x1E)
#define TCTL1 *(unsigned char volatile *)(_IO_BASE + 0x20)
#define TCTL2 *(unsigned char volatile *)(_IO_BASE + 0x21)
#define TMSK1 *(unsigned char volatile *)(_IO_BASE + 0x22)
#define TFLG1 *(unsigned char volatile *)(_IO_BASE + 0x23)
#define TMSK2 *(unsigned char volatile *)(_IO_BASE + 0x24)
#define TFLG2 *(unsigned char volatile *)(_IO_BASE + 0x25)
#define PACTL *(unsigned char volatile *)(_IO_BASE + 0x26)
#define PACNT *(unsigned char volatile *)(_IO_BASE + 0x27)
#define SPCR *(unsigned char volatile *)(_IO_BASE + 0x28)
#define SPSR *(unsigned char volatile *)(_IO_BASE + 0x29)
#define SPDR *(unsigned char volatile *)(_IO_BASE + 0x2A)
#define BAUD *(unsigned char volatile *)(_IO_BASE + 0x2B)
#define SCCR1 *(unsigned char volatile *)(_IO_BASE + 0x2C)
#define SCCR2 *(unsigned char volatile *)(_IO_BASE + 0x2D)
#define SCSR *(unsigned char volatile *)(_IO_BASE + 0x2E)
#define SCDR *(unsigned char volatile *)(_IO_BASE + 0x2F)
#define ADCTL *(unsigned char volatile *)(_IO_BASE + 0x30)
#define ADR1 *(unsigned char volatile *)(_IO_BASE + 0x31)
#define ADR2 *(unsigned char volatile *)(_IO_BASE + 0x32)
#define ADR3 *(unsigned char volatile *)(_IO_BASE + 0x33)
#define ADR4 *(unsigned char volatile *)(_IO_BASE + 0x34)
#define OPTION *(unsigned char volatile *)(_IO_BASE + 0x39)
#define COPRST *(unsigned char volatile *)(_IO_BASE + 0x3A)
#define PPROG *(unsigned char volatile *)(_IO_BASE + 0x3B)
#define HPRIO *(unsigned char volatile *)(_IO_BASE + 0x3C)
#define INIT *(unsigned char volatile *)(_IO_BASE + 0x3D)
#define TEST1 *(unsigned char volatile *)(_IO_BASE + 0x3E)
#define CONFIG *(unsigned char volatile *)(_IO_BASE + 0x3F)

// Global disabling and enabling of interrupts
#define INTR_ON() asm("cli")
#define INTR_OFF() asm("sei")

// Defines bit functionality
#define bit(x) (1 << (x))

// Defines SCI bits
#define T8 bit(6)
#define R8 bit(7)

// Defines SPI bits
#define MSTR bit(4)
#define SPE bit(6)
#define SPIF bit(7)

// Defines BAUD prescaler bits
#define SCR0 bit(0)
#define SCR1 bit(1)
#define SCR2 bit(2)

// Defines the interrupt bits
#define OC4 bit(4)
#define IC1 bit(2)
#define IC2 bit(1)
#define IC3 bit(0)

// Defines the SCCR2 bits
#define TDRE bit(7)
#define RDRF bit(5)

// Defines the PACTL bits
#define DDRA3 bit(3)
#define DDRA7 bit(7)

// Defines the TCTL1 bits
#define OM4 bit(3)
#define OL4 bit(2)

// Defines the TMSK2 bits
#define PR0 bit(0)
#define PR1 bit(1)

#endif

// END IF

// DEFINES CONSTANTS

// Defines a baud rate of 9600
// [BW * (total bits / frame)] / (info bits / frame)
#define BAUD9600 0x30

// Defines carriage return
#define CR 0x0D

// Defines line feed
#define LF 0x0A

// Defines space
#define SP 0x20

// Defines backspace
#define BS 0x08

// Defines delete
#define DEL 0x7F

// Defines escape
#define ESC 0x1B

// Defines the hardware tick amounts (Note: powers of 2)
#define TICK1uS 256 // Roughly 1.28 microSeconds
#define TICK1mS 2048 // Roughly 1 miliSecond
#define TICKHALFmS 1024 // Roughly .5 miliSeconds

// Declares the global variables
unsigned int startPulse;
unsigned int pulseWidth;
unsigned int leftTicks;
unsigned int rightTicks;
unsigned int leftRevs;
unsigned int rightRevs;
unsigned int time;
char left[3];
char right[3];
char lRev[3];
char rRev[3];
char timer[6];

// FUNCTIONS

/* Name: init
* Args: none
* Desc: Initializes the system
*/
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 &= 0xfc;
TFLG1 = IC3;
TFLG1 = IC2;
TFLG1 = IC1;
TMSK1 = 0x17;

// 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");
}

// Sets OC4 interrupt vector
extern void OC4han();
#pragma abs_address:0xffe2
void (* OC4_handler[])()={OC4han};
#pragma end_abs_address

/* Name: OC4han
* Args: none
* Desc: OC4 interrupt handler for PA6 (Pin 2)
Creates a pulse for 128 ticks (duty cycle 50%)
*/
#pragma interrupt_handler OC4han()
void OC4han(void) {

// If output line is 0
if(TCTL1 == 0x08) {
TOC4 = TOC4 + 128;
TCTL1 |= OM4;
TCTL1 |= OL4;

// If output line is 1
} else {
TOC4 = TOC4 + 128;
TCTL1 = OM4;
}

time = time + 1;

// Sets flag to indicate OC4 occured
TFLG1 = OC4;
}

// 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;
}

// Sets IC2 interrupt vector
extern void IC2han();
#pragma abs_address:0xffec;
void (*IC2_handler[])() = {IC2han};
#pragma end_abs_address

/* Name: IC2han
* Args: none
* Desc: IC2 interrupt handler for PA1 (7)
*/
#pragma interrupt_handler IC2han()
void IC2han(void) {

// If rising edge is detected
if (TCTL2 == 0x10) {

// Begins timing the pulse
startPulse = TIC2;

// PA3 on Port A latched high (set as output)
PACTL |= 0x08;

// Increments the number of right tick marks
rightTicks = rightTicks + 1;

// Sets the right tick mark string
itoa(right, rightTicks, 10);

// Manages tick mark information
if (rightTicks == 45) {
rightRevs = rightRevs + 1;
itoa(rRev, rightRevs, 10);
rightTicks = 1;
itoa(right, rightTicks, 10);
}

// Writes to the screen indicating tick mark
OutString("Right...");
OutChar(CR);
OutChar(LF);
OutString(right);
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 < TIC2) {
pulseWidth = TIC2 - pulseWidth;
} else {
pulseWidth = 65536 - startPulse + TIC2;
}

// PA3 on Port A latched low (set as input)
PACTL &= 0x87;

// Sets for rising edge
TCTL2 = 0x10;
}

// Sets flag to indicate IC2 occured
TFLG1 = IC2;
}

//(IGNORE, FOR IT IS NOT EVEN TIED TO ANYTHING ON THE HARDWARE
// SIDE) !!!
// Sets IC3 interrupt vector
extern void IC3han();
#pragma abs_address:0xffea;
void (*IC3_handler[])() = {IC3han};
#pragma end_abs_address

/* Name: IC3han
* Args: none
* Desc: IC3 interrupt handler for PA0 (8)
*/
#pragma interrupt_handler IC3han()
void IC3han(void) {

// If rising edge is detected
if (TCTL2 == 0x10) {

// Begins timing the pulse
startPulse = TIC3;

// PA3 on Port A latched high (set as output)
PACTL |= 0x08;

// Increments the number of right tick marks
rightTicks = rightTicks + 1;

// Sets the right tick mark string
itoa(right, rightTicks, 10);

// Manages tick mark information
if (rightTicks == 45) {
rightRevs = rightRevs + 1;
itoa(rRev, rightRevs, 10);
rightTicks = 1;
itoa(right, rightTicks, 10);
}

// Writes to the screen indicating tick mark
OutString("Right...");
OutChar(CR);
OutChar(LF);
OutString(right);
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 < TIC3) {
pulseWidth = TIC3 - pulseWidth;
} else {
pulseWidth = 65536 - startPulse + TIC3;
}

// PA3 on Port A latched low (set as input)
PACTL &= 0x87;

// Sets for rising edge
TCTL2 = 0x10;
}

// Sets flag to indicate IC3 occured
TFLG1 = IC3;
}

/* Future SCI Interrupt work // Sets SCI interrupt vector
extern void SCIhan();
#pragma abs_address:0xffd6;
void (*SCI_handler[])() = {SCIhan};
#pragma end_abs_address

/* Name: SCIhan
* Args: none
* Desc: SCI interrupt handler for RS232
/
#pragma interrupt_handler SCIhan()
void SCIhan(void) {
}

*/

/* Name: pause
* Args: short duration
* Desc: Pauses for a short amount of time
*/
void pause(short duration) {
time = 0;
while (time <= duration) {
}
}

/* Name: disableSCI
* Args: none
* Desc: Disables RS232 communication
*/
void disableSCI(void) {

// Sets RS232 to recieve data
SCCR2 = 0x00;
SCSR = 0xC0;
pause(10);
}

/* Name: enableSCI
* Args: none
* Desc: Enables RS232 communication
*/
void enableSCI(void) {
SCCR2 = 0x0C;
pause(10);
}

/* Name: OutChar
* Args: char data
* Desc: Sends a character via RS232
*/
void OutChar(char data) {

// While no overrun error occurs
while ((SCSR & 0x80) == 0) {
}
SCDRa;
}

/* Name: OutString
* Args: char *pt
* Desc: Sends a string via RS232
*/
void OutString(char *pt) {

// Declares the local variables
char letter;

// While no overrun error occurs
while (letter = *pt++) {
OutChar(letter);
}
}

/* Name: OutuDec
* Args: unsigned short number
* Desc: Sends a number via RS232
*/
void OutUDec(unsigned short number) {

// Breaks number down if greater than 10
if(number >= 10) {
OutUDec(number / 10);
OutUDec(number % 10);
} else {
OutChar(number + '0');
}
}

/* Name: InChar
* Args: none
* Desc: Waits to recieve a character via RS232
*/
char InChar(void) {

// Waits until a character is sent
while ((SCSR & RDRF) == 0) {
}
return (SCDR);
}

/* Name: InString
* Args: char *string, unsigned int max
* Desc: Waits to recieve a string via RS232
*/
void InString(char *string, unsigned int max) {

// Declares the local variables
unsigned int length = 0;
unsigned char charact;

// Loops until cr is found
while ((charact = InChar()) != CR) {
if (charact == BS) {
if (length) {
string--;
length--;
OutChar(BS);
}
}
else if (length < max) {
*string++ = charact;
length++;
OutChar(charact);
}
}
*string = 0;
}

/* Name: InuDec
* Args: none
* Desc: Sends a number via RS232
*/
unsigned short InUDec(void) {

// Declares the local variables
unsigned short number = 0;
unsigned short length = 0;
unsigned char charact;

// Loops until cr is found
while ((charact = InChar()) != CR) {
if (charact >= '0' && charact <= '9') {
number = 10 * number + charact - '0';
length++;
OutChar(charact);
}
else if (charact == BS && length) {
number /= 10;
length--;
OutChar(charact);
}
}
return number;
}

/* File: Interrupt.c
* Copy: Copyright (c) 2006 Richard F. D'Anna
* BlazerID: ricky
* Vers: 1.0.0 - 01/06/06 - rfd, Original Coding.
* Desc: BlazEx Code for the MicroStamp11
*/

<<<<<<<<<<<<< Interrupt.c >>>>>>>>>>>>>>>>>>>>>
// Includes the MicroStamp11 custom header file
#include "kernel.c"
// Includes the vector declarations
#include "vector.c"

/* Name: main()
* Args: none
* Desc: Creates a constant looping main function
*/
void main(void) {

// Initializes the system
init();

// Sets all of the pins on Port A to logic high
PORTA = 0xff;

// Loops endlessly
while(1) {
}
}

---Richard <<< --- In m68HC11@m68H..., BobGardner@a... wrote:
>
>
> In a message dated 1/6/06 1:41:38 P.M. Eastern Standard Time,
> richard.danna@y... writes:
>
> // Sets cycle to every ms
> TOC4 = TCNT + TICK1uS; >
> ===========================
> What value is TICK1uS? (supposed to be 1000uS right?). If it was
too fast it
> would hog the cpu in the isr.... looks like that's whats
happening?
>