MSP430: Trying to learn interrupts using button and LED blinking - interrupt

I'm learning the MSP430 for the first time, and trying to teach myself interrupts.
I'm trying to follow these examples 1 2 3 4.
I'm using an MSP430FR6989 eval board and writing the code in Code Composer Studio.
I'm trying to have the REDLED on the board toggle when I push the P1.1 button (ie, using an interrupt).
I'm able to blink the LEDs using separate code, so I know the board works.
This is the code that i'm trying to get to work.
#include <msp430.h>
#include "driverlib.h"
int main(void) //Main program
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR |= BIT0; // Set P1.0 to output and P1.3 to input direction
P1OUT &= ~BIT0; // set P1.0 to Off
P1IE |= BIT3; // P1.3 interrupt enabled
P1IFG &= ~BIT3; // P1.3 interrupt flag cleared
__bis_SR_register(GIE); // Enable all interrupts
while(1) //Loop forever, we'll do our job in the interrupt routine...
{}
}
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= BIT0; // Toggle P1.0
P1IFG &= ~BIT3; // P1.3 interrupt flag cleared
}
When I press the button, the LED doesn't turn on and I'm not sure why.
I'd appreciate any help!
To show a working LED Blink program as requested by user #CL
#include <msp430.h>
#include "driverlib.h"
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Disables the watchdog
PM5CTL0 &= ~LOCKLPM5; // allows output pins to be set... turning off pullups
P1DIR = BIT0; // Make a pin an output... RED LED
long x = 0; // Will be used to slow down blinking
while(1) // Continuously repeat everything below
{
for(x=0 ; x < 30000 ; x=x+1); // Count from 0 to 30,000 for a delay
P1OUT = BIT0; // Turn red LED light on
for(x=0 ; x < 30000 ; x=x+1); // Count from 0 to 30,000 for a delay
P1OUT ^= BIT0; // Turn off the red LED light
}
}

On the MSP430FR6989 LaunchPad, P1.3 is not connected to a button. Use P1.1 instead.
The button requires a pull-up resistor, so you have to configure it in P1REN and P1OUT.
It might be a good idea to configure the signal edge for the interrupt in P1IES.
You have to clear LOCKLPM5 to activate the port settings.
All this can be seen in the msp430fr69xx_p1_03.c example program.

Related

How to use STM32 to read signal from the PS2 hand controller through SPI protocol?

I have a project where I need to connect a PS2 hand controller to my microcontroller (STM32F4 series) to control a robot. I want to use the controller to read the signals from the buttons and joystick on that hand controller via SPI communication using DMA to avoid missing events from PS2. Then, I can control my robot's direction, speed, and switch between several operating modes.
Currently, I am first building a small program to test the signal transmission between the microcontroller and the ps2 controller. I created variables for each button on the handler, and then each time I press a button, the corresponding variable should increase by one. However, it seems that my MCU cannot receive the signal from the ps2 yet because when I connect and press the buttons, the program still cannot run as expected. I have also attached my main code below.
#include "main.h"
/* Private variables ---------------------------------------------------------*/
#define spi_enable HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET)
#define spi_disable HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET)
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);
uint8_t HC_PS2_RX[8];
uint8_t HC_PS2_TX[8]={0x01, 0x42};
uint8_t anl_btn=0, start=0, up=0, right=0, down=0, left=0; //buttons in uint8_t HC_PS2_RX[3]
uint8_t l2=0, r2=0, l1=0, r1=0, triag=0, o_btn=0, x_btn=0, sqr=0; //buttons in uint8_t HC_PS2_RX[4]
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
while (1)
{
spi_enable;
HAL_SPI_TransmitReceive_DMA(&hspi1, HC_PS2_TX, HC_PS2_RX, 8);
spi_disable;
}
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi){
if (HC_PS2_RX[3] == 0xF7) //press start button
start++;
else if (HC_PS2_RX[3] == 0xFE) //press ANALOG button
up++;
else if (HC_PS2_RX[3] == 0xEF) //press up button
up++;
else if (HC_PS2_RX[3] == 0xDF) //press right button
right++;
else if (HC_PS2_RX[3] == 0xBF) //press down button
down++;
else if (HC_PS2_RX[3] == 0x7F) //press left button
left++;
else if (HC_PS2_RX[4] == 0x7F) //press square button
sqr++;
else if (HC_PS2_RX[4] == 0xBF) //press X button
x_btn++;
else if (HC_PS2_RX[4] == 0xDF) //press circle button
o_btn++;
else if (HC_PS2_RX[4] == 0xEF) //press triangle button
triag++;
else if (HC_PS2_RX[4] == 0xF7) //press R1 button
r1++;
else if (HC_PS2_RX[4] == 0xFB) //press L1 button
l1++;
else if (HC_PS2_RX[4] == 0xFD) //press R2 button
r2++;
else if (HC_PS2_RX[4] == 0xFE) //press L2 button
l2++;
}
I also attached the ps2's message format that i found for anyone who wants to refer.
I'm still fairly new to embedded programming so can someone help me with suggestions on where maybe I'm going wrong, please? If you have any questions about my SPI configuration, just comment and I will clarify.
Thank you so much!

How much time does it take to get from the end of a for loop back to the beginning on an msp430?

I am asking this because the code below is what I'm using to make the 2 two leds perfectly alternate their flashing. But it doesn't really make sense as to why this works. This loop with 2 xor's has 2 states one with pin1(red lit only) active and another with both pin 6 and pin 1 active(both red and green lit). But the lights flash like they are alternating on and off perfectly between each other.
#include <msp430g2553.h>
// counter as a global variable
unsigned int i = 0;
void main(void)
{
// stop the watchdog timer
WDTCTL = WDTPW + WDTHOLD;
// set the direction register for LED1 and LED2
P1DIR |= 0x41;
// initialize LED1 and LED2 to off
P1OUT &= 0xBE;
//empty for loop is an infinite loop
for (;;)
{
P1OUT ^= 0x01;
// create a delay between toggles
for(i=0; i< 20000; i++)
{
// empty statement, do nothing
}
P1OUT ^= 0x40;
}
}
Is it possible the delay for the main for loop is causing this illusion?
The answer is that it is VERY FAST to get back to the start of the loop.
This code looks like it should alternate the LEDs to me. Your comments look like they're badly lined up though.
The main part of it is in your loop. You start out with both LEDs off. Then do this (I've changed the comments to what I think they do):
for (;;) { // infinite loop
P1OUT ^= 0x01; // toggle state of LED1
for(i=0; i< 20000; i++) // create a delay
;
P1OUT ^= 0x40; // toggle state of LED2
}
So what that does, flattening out the loop is:
LED1 LED2
off off
start into loop
Toggle LED1 on off
wait
wait
wait
Toggle LED2 on on { go back to start of loop - quickly }
Toggle LED1 off on
wait
wait
wait
Toggle LED2 off off
Toggle LED1 on off
wait
...

SDL left mouse button event without press on startup

On the start-up of my SDL program a left mouse button event is registered without me pressing the physical left mouse button. The next physical left button press is not registered. All other keys and buttons work normal. When clicking the .exe the mouse is not located within the location of the window.
Here are the specifications of that event (taken from the SDL_Event struct):
type=1025 (SDL_MOUSEBUTTONDOWN)
timestamp=24
windowID=1
which=0
button=1 (SDL_BUTTON_LEFT)
state=1
clicks=1
x=0
y=0
I am on windows 8.1 compiling with MinGW (gcc version 4.8.1).
I have SDL version 2.0.3
This is my source code:
#include <stdio.h>
#include <SDL.h>
int main(int argc, char* argv[])
{
SDL_Window* window = NULL;
SDL_Surface* screen = NULL;
SDL_Event ev;
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0);
screen = SDL_GetWindowSurface(window);
while (1) {
while (SDL_PollEvent(&ev)) {
if (ev.type == SDL_QUIT)
return 0;
else {
if (ev.type == SDL_MOUSEBUTTONDOWN) {
if (ev.button.button == SDL_BUTTON_LEFT) {
printf("MOUSE DOWN\n");
printf("type=%d\n", ev.button.type);
printf("timestamp=%d\n", ev.button.timestamp);
printf("windowID=%d\n", ev.button.windowID);
printf("which=%d\n", ev.button.which);
printf("button=%d\n", ev.button.button);
printf("state=%d\n", ev.button.state);
printf("clicks=%d\n", ev.button.clicks);
printf("x=%d\n", ev.button.x);
printf("y=%d\n\n", ev.button.y);
}
}
}
}
SDL_UpdateWindowSurface(window);
SDL_Delay(5);
}
SDL_FreeSurface(screen);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I have tried to solve it by calling SDL_PumpEvents() and SDL_FlushEvents() and while this removed the first (erroneous) event, the second press was still not registered.
Something strange I noticed was that it worked as expected when I opened the program .exe by right clicking and then pressing 'open'.
It'd be very grateful if somebody could shed light on this issue.

How can I make a screen blink in TSR program?

I have written a program which acts as a screensaver i.e after 10 seconds all the command prompt screen is cleared if no keyboard button is pressed. In short I have hooked Timer and Keyboard interrupt. But I want the program to show blinking screen i.e alternatively show all the text of command prompt and blank screen. But my current situation is that it keeps on showing a blank screen after 10 seconds if no button is pressed. How can I modify my program to show blinking screen alternating between cleared screen and textual data instead of just cleared screen. Here is my program:
#include <dos.h>
#include <conio.h>
void interrupt (*oldTimer)();
void interrupt (*oldKey)();
void interrupt newTimer();
void interrupt newKey();
char far *scr = (char far*) 0xB8000000;
int i, t=0, m=0;
char charscr[4000];
void main()
{
oldTimer=getvect(8);
oldKey=getvect(9);
setvect(8,newTimer);
setvect(9,newKey);
getch();
keep (0,1000);
}
void interrupt newTimer()
{
t++;
if((t>=182)&&(m==0))
{
for (i=0;i<4000;i++)
charscr [i]=*(scr+i);
for (i=0;i<=4000;i+=2)
{
*(scr+i)=0x20;
*(scr+i+1)=0x07;
}
t=0; m=1;
}
(*oldTimer)();
}
void interrupt newKey()
{
int w;
if(m==1)
{
for (w=0; w<4000;w++)
*(scr+w)=charscr[w];
m=0;
}
(*oldKey)();
}
Sorry for my poor indentation. I find it very hard on this site to indent the code.

Sleeping display using IOKit on Lion

I have the following code that is suppose to sleep the display on a Mac. I've tried it on Lion but it doesn't seem to do anything. I tested the code by creating a barebones window Mac app with a button in the window and an IBAction method. When the button is pressed, the function below is called, however nothing happens.
Any suggestions as to why it doesn't work?
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
int display_sleep(void)
{
io_registry_entry_t reg = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler");
if (reg)
{
IORegistryEntrySetCFProperty(reg, CFSTR("IORequestIdle"), kCFBooleanTrue);
IOObjectRelease(reg);
}
else
{
return 1;
}
return 0;
}