Jump to content
43oh

Newbie having problems with interrupts and inputs.


Recommended Posts

Hello, 

 

I am basically new to msp430 and CCS, and I am having a hard time trying to understand code, interrupts and timers.

 

Background info:

 

Goal.- read and interpret a dual 7 segment LED display with 10 pins.

 

So after playing around with this part I found out that the way this works is the driver pins (9, 6) toggle each other really fast ~4khz, 9 is on while 6 is of etc.

My idea was to use the MSP430G2553 to read  A-G on PORT1 and the 2 drivers (9, 6) on PORT2. 

 

I read on interrupts and saw that there is a way to set up an interrupt for when your input signal (in this case 9 or 6 on the diagram) goes from high to low or low to high.

 

SO if I could read all A-G segments when 9 is "on" it would correspond to digit 1, when 9 goes to "off" and 6 turns "on" i would read all A-G segments again and that would correspond to digit 2... I thought it would be easy but apparently there is a lot that I am overlooking.

 

Here is my attempt to code: (worked from an example from TI Resource Explorer)

#include <msp430.h>
volatile int flag = 0;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                  // Stop Watchdog timer

	if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
	{
	  while(1);						//trap for the Digitally controlled O.
	}

	BCSCTL1 = CALBC1_1MHZ;					//set range for the O.
	DCOCTL = CALDCO_1MHZ;					//set DCO step  modulation 1MHZ

	P1DIR = 0; 						// Set P1.0 - P1.7 as input
	P2DIR = 0XF9; 						// set P2.1 AND P2.2 as inputs
	P2OUT = BIT4;						// set P2.4 to start as on
	P2IE |= BIT2; 						// P2.2 interrupt enabled
	P2IES = 1;						// Flag is set with a high-to-low transition 

	P2IFG &= ~BIT2; 						// P2.2 interrupt flag cleared

	__bis_SR_register(GIE);					 // Enable all interrupts

   while(1) //Loop forever
   {
   }
}

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
	if(P1IN == 0x79)  					//check if P1IN= 01111001 means, p1.0=1, p1.1=0, p1.2=0, p1.3=1... etc
			     {
			     	P2OUT = 0;  			// turn off bit 4 on port 2 (added to see if i recognize 01111001)
			     }
    P2IFG &= ~BIT2; // P2.1 interrupt flag cleared
}

I am attempting to read all inputs in PORT1 and check if they match 01111001 which corresponds to the digit displaying "1" inverted so my zeros mean the segment is "on"

so for example if i wanted to display "7" segments a, b, and c should be 0 the rest 1. or (01111000) I am ignoring the DP.

 

 

The code compiles but my LED at BIT4  never turns off which means the interrupt is never happening?

 

 

Any feedback is very much appreciated.

 

 

 

 

 

 

post-38121-0-14479700-1408397826_thumb.png

post-38121-0-10654300-1408397843_thumb.jpg

Link to post
Share on other sites

I'm just barely starting to learn interrupts as well, so I may or may not be useful here.

That said, have you tried it with P2OUT = 0; alone in the interrupt routine rather than checking the other pins?

That will tell you if the interrupt is firing at least.

My experience so far has been that if it's not working I probably made a mistake in anything I typed as 0b01011010 type lines. Or of course in the wiring.

 

I don't see any errors in the code itself, which is the other thing that makes me think it may be the interface between code and the outside world.

 

As a separate note, the display is being driven with 3.6v or less right?

Link to post
Share on other sites

@@bobnova thats a really good idea, I Just tried it and the LED is still on, which makes me think maybe it is blinking but its too fast that it appears to be on at all times? or maybe my interrupt its really not occurring.

 

Actually the LED is being driven by little over 4v, I am using resistors in each pin.

Link to post
Share on other sites

Based on the code I don't think the interrupt is happening, the main code should sit inside the while(1){} and never leave to turn the LED back on.

 

Just noticed this, been reading datasheets and such, you've enabled the interrupt on Port2 and have an ISR aimed at PORT1_VECTOR, I bet that's the issue. The interrupt happens alright, but it doesn't trigger any code. Change it to PORT2_VECTOR and I bet it'll work.

Link to post
Share on other sites

Yeah you are setting P1 to input (P1DIR = 0) and then P2 output but then activating interrupts on P2 when your interrupt vector is for P1. Makes no sense--decide which pins need interrupts, set their respective PxDIR bit to 0 and configure their PxIES, PxIE bits likewise. Also when PxDIR is 0, PxREN can enable pullup/pulldown resistor on the respective pin and PxOUT determines whether it's a pullup (PxOUT bit set) or pulldown (PxOUT bit cleared).

Link to post
Share on other sites

@@spirilis, @@bobnova You guys are completely right! #pragma vector=PORT2_VECTOR fixed my problem, my LED is now turning off. However I debbuged step by step and it seems that my code hangs in the interrupt its just loops in that section of the code. How would i manage to for the interrupt to cycle? My pin BIT2 on Port 2 which is an input with the interrupt is changing from high to low every ~120 microseconds and I want to check all of my PORT 1 inputs when its high.

 

I appreciate all of your help!

Link to post
Share on other sites

Make an unsigned char variable (let's call it pinData), when the interrupt fires make the first line "pinData = P1IN". Then you can disable interrupts and examine the state of the port at the moment the interrupt fired at your leisure.

Or make a variable for each of the digits, first firing grabs the first one, second firing grabs the second, then disable interrupts and look at things.

 

If you disable interrupts inside the interrupt it should return to the main code in the spot spot it was when the interrupt fired.

That's my understanding anyway.

Link to post
Share on other sites

#include <msp430.h>

volatile int digit1;
volatile char value;

void main(void)


{
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

    P1DIR =0;       // Set set all pins as inputs.
    P2DIR = 0XF9;   // set P2.1 AND P2.2 as inputs for the sqr wave
    P2OUT = BIT4;   // LED starts as "on"
    P2REN = BIT2;   // pullup
    P2IE |= BIT2;   // P2.2 interrupt enabled
    P2IES |= BIT2;  // P2.2 Hi/lo edge
    P2IFG &= ~BIT2; // P2.2 IFG cleared

    _BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt

}

// Port 1 interrupt service routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{

value=P1IN;

if(value == 0x40){digit1=0;}
if(value == 0x79){digit1=1;} 
if(value == 0x24){digit1=2; P2OUT ^=BIT4;  }  //if the value of P1IN is 0x24 or 00100100 //which corresponds to "2" in a 7 segments LED display then toggle LED.

P2IFG &= ~BIT2; // P2.2 IFG cleared
}

This is what i have come up with, Any suggestions on how to determine my interrupt frequency and clock frequency?

Link to post
Share on other sites

This is what i have come up with, Any suggestions on how to determine my interrupt frequency and clock frequency?

 

 

I maybe misunderstanding the question as only read the thread quickly.  I am guessing you need some kind of trigger from what ever is updating the display.  The way I see it if the display updates, your interrupt fires and you get the correct square wave pulses great.  But if while your in the interrupt and a new set of data is sent to the display then your code comes out of the interrupt only capturing the tail end of the pulse, you will have an incorrect value.

Link to post
Share on other sites

I don't think you'll be able to get the interrupt frequency in LPM4 as all the clocks are stopped. If you stay in a power mode that keeps the clocks running you can set up a timer to keep track of time for you. I'm slowly working my way towards getting that figured out properly, not there yet though.

 

CPU clock frequency is probably the default (1MHz?) if you haven't changed it.

 

 

Alternatively you could have the Port1 ISR toggle an output pin and then look at that pin with a scope to get the frequency, if you have a scope. If you don't have a scope, I recommend getting a scope.

Link to post
Share on other sites

@@bobnova, I have a scope and the sqr wave coming into the MSP430 in this case P2.2 (my interrupt pin) is at 4khz. Now whenever its high i want to read all pins in port 1.

 

if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
{
 while(1); //trap for the Digitally controlled O.
}
 
BCSCTL1 = CALBC1_1MHZ; //set range for the O.
DCOCTL = CALDCO_1MHZ;
 
i can set the clock at 1Mhz however what will the frequency of my interrupt be? how should i set it up so that i can not run it in LPM4
Link to post
Share on other sites

#include <msp430.h>

#ifndef TIMER0_A1_VECTOR
#define TIMER0_A1_VECTOR TIMERA1_VECTOR
#define TIMER0_A0_VECTOR TIMERA0_VECTOR
#endif

volatile int i = 0;
volatile int digit1;
volatile char value;

void main(void)


{
	WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer


		if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
		{
		  while(1);								//trap for the Digitally controlled O.
		}

		BCSCTL1 = CALBC1_1MHZ;					//set range for the O.
		DCOCTL = CALDCO_1MHZ;					//set DCO step  modulation 1MHZ

	P1DIR = 0; // Set set BIT0-6 AS INPUT BIT 7 AS OUTPUT.
	P2DIR = 0XF9; 	// set P2.1 AND P2.2 as inputs
	P2OUT = BIT4;
	P2REN = BIT2;
	P2IE |= BIT2; // P2.2 interrupt enabled
	P2IES |= BIT2; // P2.2 Hi/lo edge
	P2IFG &= ~BIT2; // P2.2 IFG cleared

	//_BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt

	  __bis_SR_register(GIE);					 // Enable all interrupts

	  while(1) //Loop forever
	     {
	     }

}

#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{

value=P1IN;


if(value == 0x40){	digit1=0;	  }
if(value == 0x79){	digit1=1;	P2OUT ^=BIT4;  } //0x79   0xb01111001
if(value == 0x24){	digit1=2;	    } // 0x24   0xb00100100

P2IFG &= ~BIT2; 
}

@@bobnova This is what i am working on at the moment and it works great if i debug step by step, I get to the for ever loop and i can only move forward if i connect P2.2 to 3volts which triggers my interrupt. then the rest of the code works, however when i connect P2.2 to my sqr wave which goes on and off at 4khz, it seems that my interrupt is never triggered.

Link to post
Share on other sites

It's triggering, it's just exiting soon enough that the debug doesn't show it being in the loop.

I changed the code slightly to have P1_0 output to an LED (red on the launchpad) and toggle every time the interrupt fires:

#include <msp430.h>

#ifndef TIMER0_A1_VECTOR
#define TIMER0_A1_VECTOR TIMERA1_VECTOR
#define TIMER0_A0_VECTOR TIMERA0_VECTOR
#endif

volatile int i = 0;
volatile int digit1;
volatile char value;

void main(void)


{
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer


        if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
        {
          while(1);                                //trap for the Digitally controlled O.
        }

        BCSCTL1 = CALBC1_1MHZ;                    //set range for the O.
        DCOCTL = CALDCO_1MHZ;                    //set DCO step  modulation 1MHZ

    P1DIR = 1; // Set set BIT0-6 AS INPUT BIT 7 AS OUTPUT.
    P2DIR = 0XF9;     // set P2.1 AND P2.2 as inputs
    P2OUT = BIT4 | BIT2;
    P2REN = BIT2;
    P2IE |= BIT2; // P2.2 interrupt enabled
    P2IES |= BIT2; // P2.2 Hi/lo edge
    P2IFG &= ~BIT2; // P2.2 IFG cleared

    //_BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt

      __bis_SR_register(GIE);                     // Enable all interrupts

      while(1) //Loop forever
         {
         }

}

#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{

value=P1IN;

P1OUT ^= 0x01;
if(value == 0x40){    digit1=0;      }
if(value == 0x79){    digit1=1;    P2OUT ^=BIT4;  } //0x79   0xb01111001
if(value == 0x24){    digit1=2;        } // 0x24   0xb00100100

P2IFG &= ~BIT2;
}



Here's the output on my scope, with a ~4kHz square wave coming in from a Tiva-C launchpad I pressed into service to generate said signal:

post-28741-0-17400900-1408558544_thumb.jpg

That's 100

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...