Jump to content
Sign in to follow this  
Ingenious9

MSP430 Countdown using 16bit Shift Register

Recommended Posts

Hi,

I've just started playing with the MSP430 (MSP430G2252) and i'm having lots of problems with getting myself up to speed. If anyone could help me out on the basic, it would be greatly appreciated... my background is in the hardware and i am no expert at programming

For the beginning of my project (just to get me working on the right track), i'm trying to make a countdown with 2x 7segment displays while using a 16bit shift register. At startup, i need to read the value of Port1 (to find out the value to start the count from), calculate the 2x8bit value to be sent to the shift register .. then send them (in the correct order) and keep the value displayed for 1sec, then using the same process, decrease the value by one till it counts down to 0sec and then would go blank until next reboot or if the reset button is pressed.

I've looked for sample codes to get started, but it's only confusing me more.


http://e2e.ti.com/blogs_/b/designproject/archive/2013/02/04/mikro-elektronika-39-s-7-segment-quot-click-board-quot-with-msp430-launchpad-and-energia.aspx
http://www.geeetech.com/wiki/index.php/Arduino_7_segment_LED_timer_with_74HC595_module
http://kimansfield.com/MSP430.html
https://github.com/powercat/msp430-7seg/blob/master/7segment_counter_4094.c
www.mikroe.com/downloads/get/1884/7seg_click_manual.pdf


Port 1, pin 0 to 5 is for used to get the value for the start of the countdown and are pulled-up by default using external resistor (pulled down using the dip switch to enabled them) ..

example: if pin 0 and pin 1 are enabled (pulled down) the countdown will count from 3 (1+2)
example: if pin 1, pin 3 and pin 4 are enabled (pulled down) the countdown will count from 26 (2+8+16)
example: if pin 0, pin 1, pin 2, pin 3 and pin 5 are enabled (pulled down) the countdown will count from 39 (1+2+4+32)

p1.0  = 1
p1.1  = 2
p1.2  = 4
p1.3  = 8
p1.4  = 16
p1.5  = 32
p1.6 = Not used

p1.7 = Not used

the Data pin is p4.3
the Latch pin is p4.0
the Clock pin is p3.3
the Reset pin is p4.2    //reset button (pulled high with external resistor, and activated when low)
the Countdown value is Port 1 .. pin 0 to 5 (6 & 7 are not used) and all pins are pulled high with external resistor, activated when low


my connections are very similar to the 2x seven segment displays and 2x 74HC595 found here: www.mikroe.com/downloads/get/1884/7seg_click_manual.pdf

The only differences are that i'm using a different shift register that has 16 outputs (16bit shift register instead of 2x8). The outputs are connected in alphabetical order to the 2x 7 segments of the display...


Display on the Right side (lower digits)
Out0 = Segment A
Out1 = Segment B
Out2 = Segment C
Out3 = Segment D
Out4 = Segment E
Out5 = Segment F
Out6 = Segment G
Out7 = Not Connected

Display on the Left side (higher digits)
Out8  = Segment A
Out9  = Segment B
Out10 = Segment C
Out11 = Segment D
Out12 = Segment E
Out13 = Segment F
Out14 = Segment G
Out15 = Not Connected


If the reset button is pressed, the program should restart and get the Port1 value and countdown.. else, it would not do anything. I already have a hardware debounce on the pin (resistor/capacitor).. I don't know if i should still need it in my program

I have an external crystal of 4.194khz connect to it, but I can remove it if not required

An example would look like this,
at startup, assuming Port1 is set to 12, you would see 12 (for 1sec), then 11 (for 1sec), 10 (for 1sec), 9 (for 1sec), 8 (for 1sec), 7 (for 1sec), 6 (for 1sec), 5 (for 1sec), 4 (for 1sec), 3 (for 1sec), 2 (for 1sec), 1 (for 1sec),  0 (for 1sec), then "Blank" it would stay blank until the reset button is pressed


I've tried to get started with the code but I am getting confused on how I can read the whole port1 and make it countdown from that value


Here's my start of the code for the Code Composer Studio but can't figure out the rest.. should i use "Do".. or "While" .. or "For" to calculate the value of the count from Port1 input (countdown value) and make it count from that value down to zero and then stay blank
========


int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog timer
  P1DIR &= ~0x63;                      // Set P1 0-5 to input direction
  P1SEL &= ~0x63;                      // initialize Port 1 (pin 0-5) to 0, selecting coundown value
  P3DIR |= 0x08;                       // Set P3.3 to output direction
  P4DIR |= 0x09;                       // Set P4.0 & P4.3 to output direction
  P4DIR &= ~0x04;                      // Set P4.2 to input direction
 

==========

I've also been trying to modify the code below for Energia to fit my needs, but I don't know how to add the Port1 input (countdown value) to it as well and make it count from that value... personnaly, i would prefer the code to be written for the Code Composer Studio since i don't know if Energia can compile for the MSP430G2252
http://e2e.ti.com/blogs_/b/designproject/archive/2013/02/04/mikro-elektronika-39-s-7-segment-quot-click-board-quot-with-msp430-launchpad-and-energia.aspx


//Define which pins will be used for controlling the Shift Register

int dataPin = P4_3;  //shift register data pin ("SDI") set to MSP430 pin 4.3
int latchPin = P4_0; //shift register latch pin ("LATCH") set to MSP430 pin 4.0
int clockPin = P3_3; //shift register clock pin ("SCK") set to MSP430 pin 3.3
int resetPin = P4_2; //Reset pin set to MSP430 pin 4.2
int countPin = P1;   //Countdown value pin set to MSP430 port 1


//corresponding digit displayed on LED:
//                     0,          1,         2,         3,         4,         5,         6,         7,         8,         9
byte counter[10] = {B01111110, B00001010, B10110110, B10011110, B11001010, B11011100, B11111100, B00001110, B11111110, B11011110};
byte blank = 0; //used as a blank to push digit to right LED

void setup() {
pinMode(dataPin, OUTPUT);  //Configure pin as output
pinMode(latchPin, OUTPUT); //Configure pin as output
pinMode(clockPin, OUTPUT); //Configure pin as output
pinMode(resetPin, INPUT);  //Configure pin as input
pinMode(countPin, INPUT);} //Configure port as input

void loop() {
for (int i = 0; i < 10; i++)
{
   digitalWrite(latchPin, LOW); //Pull latch LOW to start sending data
   shiftOut(dataPin, clockPin, MSBFIRST, counter); //Send the data  
   shiftOut(dataPin, clockPin, MSBFIRST, blank); //Send blank to push digit to the right 7 Seg LED
   digitalWrite(latchPin, HIGH); //Pull latch HIGH to stop sending data

   delay(1000);
}
}

 

============

 

 

Share this post


Link to post
Share on other sites

Several comments:

The type of loop doesn't matter in and of itself. You select based on the code structure and the concept you are expressing. There is no difference between a for loop and a while loop in practice, other than the initialization and increment are in the loop control section with the for loop, and must be placed before the loop and at the end of the loop body, respectively, with a while loop. In both cases, the condition is examined before the loop body executes, and if the condition is false, the body never executes.   With a do loop, the condition is examined at the end, and the body will execute at least once. In practice, many (most? maybe few anymore? been a while since I did compiler design...) compilers treat all of these with the preprocessor and convert them to a while... The do loop has a GOTO inserted before the loop test, the for loop by moving the increment to the end of the body.

 

If your hardware debounce is sufficient, don't put it in the code. I prefer hardware when possible, resistive pullup and a cap, with Schmidt trigger inputs. Or a commercial debounce IC. Or SPDT switch and a RS flipflop if I want to be failsafe. Software debounce can be a bit difficult to get right.

 

Xtal of 4.194KHz? Odd value. Is it MHz? or 4.192KHz (still an odd value)?

 

If it is KHz, I would structure the code around the hardware timer (TimerA) and use interrupts. I would NEVER use the delay() function unless I had to. Generally this is only when you are doing timing to the processor cycle, rather than to human timeframe. If you want to avoid interrupts, you can set up the timer and watch the counter value, or, better yet, set it up to count cycles and watch for rollover. As I said, easiest way is set up the timer properly and use interrupts.

 

The Prefered crystal (due to cheapness, availability, and ease of use) for human scale timing is the 32.768KHz watch type (often called 32KHz) as this is 2^15, making for easy divide down to 1s. The internal oscillator drive is also designed for this crystal on the G2252, and has internal trim capacitors to insure oscillation. Uses two I/O pins (P2.7 and 8)

 

If you are using the G2252, what are port 3 and 4? The data sheet only shows ports 1 and 2

 

 

 

As a side note, I don't use Energia. I have played with it on Arduinos, but generally prefer native C.

 

 

 

Last note: the included code should really not be pasted in the text. You can select a code block element from the buttons at the top of the window when entering you message (the <> button, second row next to the cartoon speech ballon). You may already have got the note from a moderator, but if not, you can fix it by editing message.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×