This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I am new to the MSP430 family and trying to understand the coding. I am trying to use a msp430fg4618 experimenters board and count on the LCD as long as I press a button connected to P1.1 I can get it to work (maybe) It only counts when I press and hold the button. Then it takes a while to start.
Here is part of my code so far.
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
FLL_CTL0 |= XCAP18PF; // Set load cap for 32k xtal
initPortPins(); // Initialize port pins
initBasicTimer(); // Initialize basic timer
initLCD_A(); // Initialize LCD_A
static UInt8 pos = 0;
static UInt8 index = 0;
for(;;)
{
_BIS_SR(LPM3_bits + GIE); // LPM3, enable interrupts
dispChar(pos, index);
if (!(P1IN & BIT1)) // if P1.1
{
index=index+1;
if (index > 9)
{
index=0;
dispChar(pos, index);
pos = pos+1;
index=1;
}
}
}
}
Can anyone help?
Thanks
Randy
Randy Adams said:dispChar(pos, index);
if (!(P1IN & BIT1)) // if P1.1
{
index=index+1;
if (index > 9)
{
index=0;
dispChar(pos, index);
pos = pos+1;
index=1;
Hi Randy, this is not question of MSP430 but method, think what happen in your code at processor speed and how many times processor execute your lines when you press button.
You need develop a way to do action just when button is pressed and never repeat till this is released.
this is MSP430 forum, question is unrelated and can be found on C programming basis:
use a variable to store status of button and a small delay so:
int oldbuttonstate = 0; int buttonstate; // change if(!(P1IN & BIT1)) // if P1.1 to buttonstate = !(P1IN & BIT1); if( (buttonstate != oldbuttonstate) && buttonstate) // if button changed and button pressed { // button get depressed so take action and set old status oldbuttonstate=buttonstate; ..... code was on if clause } // this is where old if finished else if(!buttonstate) // if button get released oldbuttonstate=buttonstate; // reflect new state to old button state
this can cure partially your issue but need a delay to avoid another issue, think about what happen when you press button, it is not immediately closed but get closed and open few times in a few mS, this phenomena known as bouncing repeat some times and is called bouncing...
so try yourself or read about...
Randy Adams said:I will post my question in the C programming basis
Hi Randy, C forum is not on TI platform, your trouble can be instead an MSP related so .. try isolate why it require a lot of times, it need time to initialize lcd or a lot of time just when you press button?
From increasing numbers something I think can be better, Other issue are probably present.. think what is in your code and continue execute at processor speed...
What you think happen when you press button? Now it is locked and don't continue execute code but still doesn't work...
Why?
Hints:
what do pos variable and what happen to?
Is not this program destroying all memory by some mechanism?
Hi Randy,
I'm trying to make sure I understand what is happening with your code - are you wanting your display to increment the digit by 1, each time that you press the button?
I looked through your code, and it's a little bit difficult to determine the problem without seeing your ISR that you are using to wake from LPM3 (I'm guessing this would be either the port 1 ISR or a timer that does this) or your port initialization code.
I've made some assumptions about your code anyway and think I have an idea about the problem though - I think your problem could be a combination of needing a debouncing routine (which is what Roberto I think was trying to hint at), in addition to the fact that you have dispChar() happening BEFORE you have your if statement that checks the pin state to see if the button is pressed. I would guess this dispChar routine may take a fair bit of time to run and could be why you are seeing this "delay" behavior where you're having to really hold down the pin for it to register the press.
My recommendation would be to restructure the code a bit. Here's how I would do it (in pseudocode):
In main:
while(1)
{
clear buttonsPressed variable
go to LPM3 with GIE set
on wake, check "buttonpressed" variable and update the index and display the character (also do your handling I see you already have for tens digit)
(so main is relatively unaltered except for removing your P1IN checking from here and switching to check buttonspressed variable instead)
}
ISR code:
Port 1 ISR
check P1IV or P1IN to see what button was pressed
save this in a variable called "buttonpressed" for later reference in main
disable further port 1 interrupts on this pin (clear corresponding bit in P1IE) - this is for debouncing
enable WDT in interval timer mode (not reset mode) for something like 250ms or so (whatever delay you'd like - this is for debouncing delay and may take some experimentation to find right length) You could also use Timer A instead if you'd prefer.
exit ISR - don't go to active mode, just exit without clearing any LPM bits or anything - we want to sleep until the WDT finishes the debouncing delay
WDT ISR
stop the WDT
clear the port 1 IFG register (clear any flags that were set from the bouncing of the button during our delay period)
re-enable the button interrupts by setting the bit in P1IE - the debouncing period has ended so now we need to be ready for next time user pushes the button
__bic_SR_register_on_exit(LPM3_bits); - this line is what you use to say you want to wake from LPM when you exit the ISR
exit ISR
So with this code structure what happens is:
•you go to sleep
•when button is pressed - goes to Port 1 ISR and logs this in a variable called buttonspressed and disables further port interrupts, Then the debouncing period starts by starting the watchdog - exiting the ISR the part will simply return to sleep
•when the WDT expires, the debounce period is up and we clear port flags then re-enable the port interrupts. Then we wake the part to return to main
•back in main, you check the buttons pressed variable and do all of your updating of index and printing to the LCD screen.
•After this you get around to the top of the loop again - clear buttonsPressed (because we need to see the next button press now) and go back to sleep
I hope this is a helpful guide. This is essentially how button press code works in a lot of our Launchpad code examples. For example, the MSP-EXP430FR4133 Launchpad (which also has an LCD on it) has some example code here - if you look at the main.c from its out-of-box code (http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP-EXP430FR4133/latest/index_FDS.html), you can see that it employs a similar debouncing routine for it's button presses.
NOTE: MSP-EXP430FR4133 LP software link updated by MikeS to the latest on 20-Jul-2015
Regards,
Katie
Katie Pier said:I'm trying to make sure I understand what is happening with your code - are you wanting your display to increment the digit by 1, each time that you press the button?
Hi Katie, I like too much your proposal but I fear this is like using a cannon to shut pigeons.
Some part like display is not present but I suppose you can point what can happen.
Just a doubt about xtal18pF I remember this was a too high value or not?
ISR is a difficult to grasp topic to who is troubled of initial learning, I think from my experience is better start guide learner how to walk than proposing the best rocket thruster.
Yes debouncing is what it is missing and need some learning too. First close the way to button edge detect then some way to debounce and problem was learned from root. Some other issue can be present but we have to dig in.
Randy, can you explain better the delay how and when it happen? So you have to wait then it work, what are you seeing on display? is display high contrast or it is grayed?
Katie I proudly wait your opinion, and Randy too of course ;)
Randy Adams said:Katie,
I have the MSP430 Experimenters board. I started with the LDC example program and removed the extra printed functions. I then added in an simple loop to count when a button is pressed. I can send you my entire code if you would like. I think that I am not understanding the interrupts of this chip. I teach C-Programming and the Atmel Chip and can do anything I want with this chip. I hope to do the same with this chip. All I need is to get pass this program and I think I can take it and run with my other programming. Thanks
Randy
Hi Randy, sorry, I read about how and why you written this program, please accept apologizes about, so can be if you still are in trouble can help:
I wrote some short notes about LPM and interrupt but I think this can help you point to solution and introduce where trouble can b:
load code thru debugger, then locate timer interrupt service, at end there is an instruction similar to this:
__bic_SR_register_on_exit(LPM3_bits); // Clear LPM3 bits from 0(SR)
place a breakpoint just before this instruction then start single stepping program over function, so you reach the first instruction after for(;;)
here all stop, just wait for a while and you get at interrupt BP, so from there step over and I am sure you immediately grasp what happened when you loop over.
after for(;;)
_BIS_SR(LPM3_bits + GIE); // LPM3, enable interrupts
this instruction enable the interrupt but also enter immediately LPM3, this stop cpu and never get key read before timer interrupt wake up cpu,
move to end of loop to avoid long wait for cpu wake, or if you like avoid interrupt and LPM for now just comment and use loop.
also check variable pos = pos+1;
I dont know if in dispChar(pos, index); can do some damages to memory if overflow to number of digit.
Another hint, MSP is a word machine and is not so efficient with byte sized variables, use as much as possible integer or 16 bit values if you need speed and leave byte just if you are in a tight space or for character buffer.
About delay it can be on interrupt of timers, probably at end of irq service code get some decision on LPM status.
If you wish post interrupt code I can help if you like.
About this:
_BIS_SR(LPM3_bits + GIE); // LPM3, enable interrupts
this set bit of status register: GIE General Interrupt Enable
but also bit of LPM state -> Low Power Mode, LPM3 stop CPU so it stop execution from here.
if you use on interrupt it can enable interrupt to nest higher priority care about LPM can stop execution.
A special instruction is at end of service to set not status register but saved image of status register on stack to wake up or go to LPM on return.
this instruction manipulate image of status register on stack pointer, effect on status register is applied on return from service.
__bic_SR_register_on_exit(LPM3_bits); // Clear LPM3 bits from 0(SR)
this manipulate status register and execute immediately, program stop immediately if LPM is entered. Many level of LPM are available and deep one stop also clock.
_BIS_SR(LPM3_bits + GIE); // LPM3, enable interrupts
Randy Adams said:g and the Atmel Chip and can do anything I want with this chip
Another hint can be on ti site usage:
this is folder of particular device, it is divided by tabs and three document are available on first:
Data sheet, this refer to particular device, it has on feature present, pinout and pin mapping. Every device has it specific one.
Device Errata (specific issue of silicon version and possible workaround)
Family User Guide, this is specific of family of 1xx 2xx 4xx 5xx 6xx, every device has his user guide in common, so you can find here how peripheral work but just check if they are present on specific device from data sheet or better on grace. CCS has a lot of information integrated.
About TAB:
- Technical document you can find application notes and all specific, the three on top are duplicated here.
- Tools and software, here you find board toolkits and software examples.
Get from here the software examples, they where addressing all feature one at time for this processor not specific to board.
Roberto Romano said:Get from here the software examples, they where addressing all feature one at time for this processor not specific to board.
Randy, about C style, today I remembered one thing about this board:
Software if not rewritten was one of worst I seen from TI (ages 2006 till 2008), so check if on interrupt service there are some asm clause, this case the best way before get crazy about is to completely rewrite code from scratch.
I remember it was manipulating stack to force return to different routine and then performed some stack corruption too. If code was not clean and you still have old CD on box it is hard to modify and get something useful, crash of code are quite guaranteed, this manipulation was on key pressure interrupt so be careful about.
I don't know why you selected this board but if you intend use on a class evaluate launchpads, series 2G has advantage of dil, can be easily fit on a breadboard with just one resistor on reset and decoupling capacitor on power rails, price are a fraction of this one.
One other is the 5529 for computing power and USB too.
**Attention** This is a public forum