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.

MSP432P401R: Help coding my 8 switches to control two different 7-segment LEDs using Keil

Part Number: MSP432P401R


I am trying to code my MSP432 in C to make 4 switches control one of your 7-segment LEDs and the other 4 control the other 7-segment display. It is your choice what LED behavior you want. The switch also have to be interrupt driven. Here is what i have so far:

// Basic I2C Driver.
// Runs on MSP432.
// Matt Laubhan (11/15/2015)
//

#include <stdint.h>
#include "msp.h"
#include "InputOutput.h"
#define NVIC_ISER1 (HWREG32(0xE000E104)) /* Irq 32 to 63 Set Enable Register */

//----------------------------------------
// eUSCI wait until START and address are transmitted
//----------------------------------------
void WaitStart(void)
{
while ((UCB0CTLW0 & UCTXSTT) != 0);
}

//----------------------------------------
// eUSCI wait until STOP is complete
//----------------------------------------
void WaitStop(void)
{
while ((UCB0CTLW0 & UCTXSTP) != 0);
}

//----------------------------------------
// eUSCI wait until TX is complete
//----------------------------------------
void WaitTx(void)
{
while ((UCB0IFG & UCTXIFG0) == 0);
}

//----------------------------------------
// eUSCI wait until RX is complete
//----------------------------------------
void WaitRx(void)
{
while ((UCB0IFG & UCRXIFG0) == 0);
}

//----------------------------------------
// eUSCI generate start
//----------------------------------------
void GenStart(void)
{
UCB0CTLW0 |= UCTXSTT;
}

//----------------------------------------
// eUSCI generate stop
//----------------------------------------
void GenStop(void)
{
UCB0CTLW0 |= UCTXSTP;
}

////////////////////////////////////////////////////////////////////////
//
// Enable interrupts on P4.6. Port4_IRQHandler should get called below whenever
// a one of the 8 inputs to I2C_SWITCH change--provided P4.6 is connected
// to the INT signal on I2C_0.
//
void ConfigureInterrupts()
{
// Make sure P4.6 is an input and allow it to generate interrupts.
// Needs an internal pull-up resistor too.
P4DIR &= ~BIT6;
P4IES |= BIT6;
P4IE |= BIT6;
P4REN |= BIT6;
P4OUT |= BIT6;
P4IFG &= ~BIT6;
NVIC_ISER1 |= BIT6; // IRQ 38
}

// Function prototype
extern void EnableInterrupts(void); // defined in startup_msp432.s as a subroutine

// In Keil, name the ISR exactly the following...
void PORT4_IRQHandler(void)
{
// interrupt generated on any port 4 pin
//
// if ConfigureInterrupts() is called above, maskable interrupts
// are enabled [via the EnableInterrupts() function], and
// the INT pin of I2C_0 is connected to P4.6, this ISR will be called
// whenver a DIP switch changes
//
// this eliminate the need for the MSP432 CPU to poll the switches periodically
// to see if anything has changed
//
// ordinarily, ISRs should be short and defer further processing
// tasks to the main loop--however, at this point the main loop does nothing
// so it is OK to do other processing tasks here
//

// Always clear the port-level latch.
P4IFG &= ~BIT6;

// MSP432 will now resume whatever it was doing when the interrupt
// came in
}

// No parameters
void InitI2C(void)
{
//
// Configure with the following parameters:
// * 7-bit addresses.
// * single master environment.
// * MSP432 is always master.
// * I2C mode.
// * Synchronous mode.
// * SMCLK is source.
// * Automatically trigger address ACK.
// * No interrupts.
//
UCB0CTLW0 |= UCSWRST; // hold USCI in reset.
P1SEL0 |= 0xC0; // P1.7 (SCL) and P1.6 (SDA) multiplexing.
P1SEL1 &= ~0xC0;
UCB0CTLW0 |= (UCMST | UCMODE_3 | UCSYNC | UCSSEL_2);
UCB0BRW = 400; // Divide SMCLK down by this factor to get SCL.
UCB0CTLW0 &= ~UCSWRST; // release USCI reset.
}

//
// Send a byte of data to the I2C target.
// [Note there is no error checking here.]
//
void OutI2C(unsigned char address, unsigned char data)
{
UCB0I2CSA = address; // UCB0I2CSA = <expander addr w/o R/W bit>.
UCB0CTLW0 |= UCTR; // TX.
GenStart(); // Generate a START.
WaitStart(); // Wait for START and slave address to be sent.
WaitTx(); // Wait until it is safe to write to TX buffer.
UCB0TXBUF = data; // UCB0TXBUF = <data> (prep data).
if ((UCB0IFG & UCNACKIFG) == 0) // Check for slave NACK.
{
// I2C slave responded.
WaitTx(); // Wait until data is transferred.
}
else
{
// I2C slave did not respond.
}
GenStop(); // Generate a STOP.
WaitStop(); // Wait for STOP to be sent/ready to go again.
}

//
// Receive a byte of data from the I2C target.
// [Note there is no error checking here.]
//
unsigned char InI2C(unsigned char address)
{
unsigned char retVal;

UCB0I2CSA = address; // UCB0I2CSA = <expander addr w/o R/W bit>.
UCB0CTLW0 &= ~UCTR; // RX.
GenStart(); // Generate a START.
WaitStart(); // Wait for START and slave address to be sent.
if ((UCB0IFG & UCNACKIFG) == 0) // Check for slave NACK.
{
// I2C slave responded. Get data.
WaitRx(); // Wait for data.
retVal = UCB0RXBUF; // Read UCB0RXBUF for data.
}
else
{
// I2C slave did not respond.
}
GenStop(); // Generate a STOP.
WaitStop(); // Wait for STOP to be sent/ready to go again.

return retVal;
}

int main(void)
{
const unsigned char sevSegTable[16] =
{
0x40, // 0
0x79, // 1
0x24, // 2
0x30, // 3
0x19, // 4
0x12, // 5
0x02, // 6
0x78, // 7
0x00, // 8
0x18, // 9
0x08, // A
0x03, // B
0x46, // C
0x21, // D
0x06, // E
0x0E // F
};

// Ex: address = I2C_8574 | I2C_0
// Ex: address = I2C_8574_A | I2C_3
unsigned char switchAddress = I2C_8574 | I2C_0;
unsigned char sevenSegLedAddress = I2C_8574 | I2C_3;
unsigned char sevenSegLedAddress2 = I2C_8574 | I2C_4;
unsigned char data;

ConfigureInterrupts();
EnableInterrupts();



InitI2C();
while (1)
{
data = InI2C(switchAddress);
data = sevSegTable[data & 0xF];
OutI2C(sevenSegLedAddress, data);
}

// this will never be hit (compiler will probably warn)
//return 0;
}

I just don't know how I can shift the switch address to only change one LED and the other 4 change the other. I also made a look up table so that the LED will display a hex number/letter based on the four switches.

  • Garet,
    Is this code taken from a specific example? Can you provide a link so I have some more context? I do not understand what you mean be shifting the switch address or 'the other 4 change the other'.

    Thanks,
    Chris
  • This is just a lab I'm working on and all I have to change is the main loop code. This is what I have so far. I have hardware to go along with it and the addresses below are for my switch and two different LEDs. The problem I am having though is that I have a 16 pin switch that has 8 different switch on it. When I press switches 1-4 one of my LEDs shows the correct values but if I hit switches 5-8 nothing happens to my other LED. I tried some if else statements but then the second LED would just copy the value from the first 4 switches. So I am just wondering how can I code the 1-4 and 5-8 switches separately.
  • Garet,
    It looks like your teacher has provided you with two different addresses:

    unsigned char sevenSegLedAddress = I2C_8574 | I2C_3;
    unsigned char sevenSegLedAddress2 = I2C_8574 | I2C_4;

    based upon what you receive in

    data = InI2C(switchAddress);

    Are you to make a decision (if statement) to write to one address or the other?

    THere is also an interrupt handler that really isn't doing anything. Based upon this interrupt should something change?

    Regards,
    Chris

**Attention** This is a public forum