How to display a result on built in LCD on a msp-EXP432P4111

102 Views Asked by At

I've been trying to display a simple program result on my msp-EXP432P4111 board's built in LCD display. However, I'm having trouble figuring out how to get it to work since it doesn't need pins like external LCD's do. I'm unsure if I need to do something with the physical board or reference/write something in my code to get there.

I've looked through the manual and some other sites/sources online, but I found only results for external LCD displays, which requires pins and such- there's not much information on how to get numbers to show up on the built in LCD for the board. Any help would be appreciated since I've pretty new to using the LCD at all

2

There are 2 best solutions below

0
Tim Roberts On BEST ANSWER

The MSP-EXP432P4111 user guide describes the pin and register assignments for the LCD on page 15.

https://www.digikey.com/en/htmldatasheets/production/3031551/0/0/1/msp-exp432p4111

0
Brighton Sikarskie On

I have spent a very long time trying to understand this as well. I am still learning so either I will update this in a while or someone can, but here is what I know so far :)

  1. First thing you need to make sure is that you have the SDK installed: https://www.ti.com/tool/download/SIMPLELINK-MSP432-SDK/3.40.01.02

  2. Second thing is to set up your environment to read the SDK, for example in your Makefile:

CFLAGS = -I"$(SIMPLELINK_MSP432_SDK_INSTALL_DIR)/source" \
    -I"$(SIMPLELINK_MSP432_SDK_INSTALL_DIR)/source/third_party/CMSIS/Include" \
    -D__MSP432P4111__ \
    -DDeviceFamily_MSP432P4x1xI \
    -mcpu=cortex-m4 \
    -march=armv7e-m \
    -mthumb \
    -std=c17 \
    -mfloat-abi=hard \
    -mfpu=fpv4-sp-d16 \
    -ffunction-sections \
    -fdata-sections \
    -g \
    -gstrict-dwarf \
    -Wall

LFLAGS = -Wl,-T,msp432p4111.lds \
    -Wl,-Map,"$(NAME).map" \
    -L"$(SIMPLELINK_MSP432_SDK_INSTALL_DIR)/source" \
    -l:ti/display/lib/display.am4fg \
    -l:ti/grlib/lib/gcc/m4f/grlib.a \
    -l:third_party/spiffs/lib/gcc/m4f/spiffs.a \
    -l:ti/drivers/lib/drivers_msp432p4x1xi.am4fg \
    -l:third_party/fatfs/lib/gcc/m4f/fatfs.a \
    -l:ti/devices/msp432p4xx/driverlib/gcc/msp432p4xx_driverlib.a \
    -march=armv7e-m \
    -mthumb \
    -mfloat-abi=hard \
    -mfpu=fpv4-sp-d16 \
    -static \
    -Wl,--gc-sections \
    -lgcc \
    -lc \
    -lm \
    -lnosys \
    --specs=nano.specs
  1. Third thing is the actual code, this is where I am currently and I am still learning how it works, but I was able to find the example code in the SDK that I downloaded. The path was simplelink_msp432p4_sdk_3_40_01_02/examples/nortos/MSP_EXP432P4111/driverlib/examples. Below I will post 3 example codes for the lcd_f screen. Also I have all of the examples and some of my code on my GitHub which could be helpful: https://github.com/bsikar/msp-exp432p4111. I will be updating the repo as I learn more so feel free to post questions on there.

lcd_f_animated_text:

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdbool.h>
#include <stdint.h>

/* Configuration Structure for LCD */
LCD_F_Config lcdConf = {.clockSource    = LCD_F_CLOCKSOURCE_ACLK,
                        .clockDivider   = LCD_F_CLOCKDIVIDER_32,
                        .clockPrescaler = LCD_F_CLOCKPRESCALER_1,
                        .muxRate        = LCD_F_4_MUX,
                        .waveforms      = LCD_F_STANDARD_WAVEFORMS,
                        .segments       = LCD_F_SEGMENTS_ENABLED};

int main(void) {
  /* Stop Watchdog  */
  WDT_A_holdTimer();

  /* Initializing all of the function selection bits in the pins */
  P3->SEL1  |= 0xF2;
  P6->SEL1  |= 0x0C;
  P7->SEL1  |= 0xF0;
  P8->SEL1  |= 0xFC;
  P9->SEL1  |= 0xFF;
  P10->SEL1 |= 0x3F;

  /* Setting ACLK to the reference oscillator */
  CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

  /* Initializing the LCD_F module */
  LCD_F_initModule(&lcdConf);

  /* Clearing out all memory */
  LCD_F_clearAllMemory();

  /* Initializing all of our pins and setting the relevant COM lines */
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_0, LCD_F_SEGMENT_LINE_3);
  LCD_F_setPinAsLCDFunction(LCD_F_SEGMENT_LINE_6);
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_16, LCD_F_SEGMENT_LINE_19);
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_26, LCD_F_SEGMENT_LINE_47);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_26, LCD_F_MEMORY_COM0);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_27, LCD_F_MEMORY_COM1);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_6, LCD_F_MEMORY_COM2);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_3, LCD_F_MEMORY_COM3);

  /* Set battery animation frames */
  LCD_F->ANM[0] = 0x11; /* Frame 1 */
  LCD_F->ANM[1] = 0x11; /* Frame 2 */
  LCD_F->ANM[2] = 0x31; /* Frame 3 */
  LCD_F->ANM[3] = 0x33; /* Frame 4 */
  LCD_F->ANM[4] = 0x73; /* Frame 5 */
  LCD_F->ANM[5] = 0x77; /* Frame 6 */
  LCD_F->ANM[6] = 0xF7; /* Frame 7 */
  LCD_F->ANM[7] = 0xFF; /* Frame 8 */

  /* Configuring and enabling animation */
  LCD_F_setAnimationControl(LCD_F_ANIMATION_FREQ_CLOCK_PRESCALAR_512,
                            LCD_F_ANIMATION_FREQ_CLOCK_DIVIDER_8,
                            LCD_F_ANIMATION_FRAMES_T0_TO_T7);
  LCD_F_enableAnimation();

  /* Turing the LCD_F module on */
  LCD_F_turnOn();

  /* Going into LPM0 */
  PCM_gotoLPM0();
}

lcd_f_blinking_text

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdbool.h>
#include <stdint.h>

/* Definitions for LCD Driver */
#define char1 16 // Digit A1 - L16
#define char2 32 // Digit A2 - L32
#define char3 40 // Digit A3 - L40
#define char4 36 // Digit A4 - L36
#define char5 28 // Digit A5 - L28
#define char6 44 // Digit A6 - L44

/* LCD memory map for numeric digits (Byte Access) */
const char digit[10][4] = {
    {0xC, 0xF, 0x8, 0x2}, /* "0" LCD segments a+b+c+d+e+f+k+q */
    {0x0, 0x6, 0x0, 0x2}, /* "1" */
    {0xB, 0xD, 0x0, 0x0}, /* "2" */
    {0x3, 0xF, 0x0, 0x0}, /* "3" */
    {0x7, 0x6, 0x0, 0x0}, /* "4" */
    {0x7, 0xB, 0x0, 0x0}, /* "5" */
    {0xF, 0xB, 0x0, 0x0}, /* "6" */
    {0x4, 0xE, 0x0, 0x0}, /* "7" */
    {0xF, 0xF, 0x0, 0x0}, /* "8" */
    {0x7, 0xF, 0x0, 0x0}  /* "9" */
};

/* LCD memory map for uppercase letters (Byte Access) */
const char alphabetBig[26][4] = {
    {0xF, 0xE, 0x0, 0x0}, /* "A" LCD segments a+b+c+e+f+g+m */
    {0x1, 0xF, 0x0, 0x5}, /* "B" */
    {0xC, 0x9, 0x0, 0x0}, /* "C" */
    {0x0, 0xF, 0x0, 0x5}, /* "D" */
    {0xF, 0x9, 0x0, 0x0}, /* "E" */
    {0xF, 0x8, 0x0, 0x0}, /* "F" */
    {0xD, 0xB, 0x0, 0x0}, /* "G" */
    {0xF, 0x6, 0x0, 0x0}, /* "H" */
    {0x0, 0x9, 0x0, 0x5}, /* "I" */
    {0x8, 0x7, 0x0, 0x0}, /* "J" */
    {0xE, 0x0, 0x2, 0x2}, /* "K" */
    {0xC, 0x1, 0x0, 0x0}, /* "L" */
    {0xC, 0x6, 0x0, 0xA}, /* "M" */
    {0xC, 0x6, 0x2, 0x8}, /* "N" */
    {0xC, 0xF, 0x0, 0x0}, /* "O" */
    {0xF, 0xC, 0x0, 0x0}, /* "P" */
    {0xC, 0xF, 0x2, 0x0}, /* "Q" */
    {0xF, 0xC, 0x2, 0x0}, /* "R" */
    {0x7, 0xB, 0x0, 0x0}, /* "S" */
    {0x0, 0x8, 0x0, 0x5}, /* "T" */
    {0xC, 0x7, 0x0, 0x0}, /* "U" */
    {0xC, 0x0, 0x8, 0x2}, /* "V" */
    {0xC, 0x6, 0xA, 0x0}, /* "W" */
    {0x0, 0x0, 0xA, 0xA}, /* "X" */
    {0x0, 0x0, 0x0, 0xB}, /* "Y" */
    {0x0, 0x9, 0x8, 0x2}  /* "Z" */
};

static void showChar(char c, int position);

/* Configuration Structure for LCD */
LCD_F_Config lcdConf = {.clockSource    = LCD_F_CLOCKSOURCE_ACLK,
                        .clockDivider   = LCD_F_CLOCKDIVIDER_32,
                        .clockPrescaler = LCD_F_CLOCKPRESCALER_1,
                        .muxRate        = LCD_F_4_MUX,
                        .waveforms      = LCD_F_STANDARD_WAVEFORMS,
                        .segments       = LCD_F_SEGMENTS_ENABLED};

int main(void) {
  /* Stop Watchdog  */
  WDT_A_holdTimer();

  /* Initializing all of the function selection bits in the pins */
  P3->SEL1  |= 0xF2;
  P6->SEL1  |= 0x0C;
  P7->SEL1  |= 0xF0;
  P8->SEL1  |= 0xFC;
  P9->SEL1  |= 0xFF;
  P10->SEL1 |= 0x3F;

  /* Setting ACLK to the reference oscillator */
  CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

  /* Initializing the LCD_F module */
  LCD_F_initModule(&lcdConf);

  /* Configuring blinking mode to switch between regular LCD_F memory
   * and blinking memory. Since we do not setup blinking memory, this
   * blinks between "123ABC" and a blank screen.
   */
  LCD_F_setBlinkingControl(LCD_F_BLINK_FREQ_CLOCK_PRESCALAR_4096,
                           LCD_F_BLINK_FREQ_CLOCK_DIVIDER_8,
                           LCD_F_BLINK_MODE_SWITCHING_BETWEEN_DISPLAY_CONTENTS);

  /* Clearing out all memory */
  LCD_F_clearAllMemory();
  LCD_F_clearAllBlinkingMemory();

  /* Initializing all of our pins and setting the relevant COM lines */
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_0, LCD_F_SEGMENT_LINE_3);
  LCD_F_setPinAsLCDFunction(LCD_F_SEGMENT_LINE_6);
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_16, LCD_F_SEGMENT_LINE_19);
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_26, LCD_F_SEGMENT_LINE_47);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_26, LCD_F_MEMORY_COM0);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_27, LCD_F_MEMORY_COM1);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_6, LCD_F_MEMORY_COM2);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_3, LCD_F_MEMORY_COM3);

  /* Turing the LCD_F module on */
  LCD_F_turnOn();

  /* 123ABC */
  showChar('1', char1);
  showChar('2', char2);
  showChar('3', char3);
  showChar('A', char4);
  showChar('B', char5);
  showChar('C', char6);

  while (1) { PCM_gotoLPM0(); }
}

static void showChar(char c, int position) {
  uint8_t ii;
  if (c == ' ') {
    for (ii = 0; ii < 4; ii++) { LCD_F->M[position + ii] |= 0x00; }
  } else if (c >= '0' && c <= '9') {
    for (ii = 0; ii < 4; ii++) { LCD_F->M[position + ii] |= digit[c - 48][ii]; }
  } else if (c >= 'A' && c <= 'Z') {
    for (ii = 0; ii < 4; ii++) {
      LCD_F->M[position + ii] |= alphabetBig[c - 65][ii];
    }
  } else {
    LCD_F->M[position] = 0xFF;
  }
}

lcd_f_static_text

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdbool.h>
#include <stdint.h>

/* Definitions for LCD Driver */
#define char1 16 // Digit A1 - L16
#define char2 32 // Digit A2 - L32
#define char3 40 // Digit A3 - L40
#define char4 36 // Digit A4 - L36
#define char5 28 // Digit A5 - L28
#define char6 44 // Digit A6 - L44

/* LCD memory map for numeric digits (Byte Access) */
const char digit[10][4] = {
    {0xC, 0xF, 0x8, 0x2}, /* "0" LCD segments a+b+c+d+e+f+k+q */
    {0x0, 0x6, 0x0, 0x2}, /* "1" */
    {0xB, 0xD, 0x0, 0x0}, /* "2" */
    {0x3, 0xF, 0x0, 0x0}, /* "3" */
    {0x7, 0x6, 0x0, 0x0}, /* "4" */
    {0x7, 0xB, 0x0, 0x0}, /* "5" */
    {0xF, 0xB, 0x0, 0x0}, /* "6" */
    {0x4, 0xE, 0x0, 0x0}, /* "7" */
    {0xF, 0xF, 0x0, 0x0}, /* "8" */
    {0x7, 0xF, 0x0, 0x0}  /* "9" */
};

/* LCD memory map for uppercase letters (Byte Access) */
const char alphabetBig[26][4] = {
    {0xF, 0xE, 0x0, 0x0}, /* "A" LCD segments a+b+c+e+f+g+m */
    {0x1, 0xF, 0x0, 0x5}, /* "B" */
    {0xC, 0x9, 0x0, 0x0}, /* "C" */
    {0x0, 0xF, 0x0, 0x5}, /* "D" */
    {0xF, 0x9, 0x0, 0x0}, /* "E" */
    {0xF, 0x8, 0x0, 0x0}, /* "F" */
    {0xD, 0xB, 0x0, 0x0}, /* "G" */
    {0xF, 0x6, 0x0, 0x0}, /* "H" */
    {0x0, 0x9, 0x0, 0x5}, /* "I" */
    {0x8, 0x7, 0x0, 0x0}, /* "J" */
    {0xE, 0x0, 0x2, 0x2}, /* "K" */
    {0xC, 0x1, 0x0, 0x0}, /* "L" */
    {0xC, 0x6, 0x0, 0xA}, /* "M" */
    {0xC, 0x6, 0x2, 0x8}, /* "N" */
    {0xC, 0xF, 0x0, 0x0}, /* "O" */
    {0xF, 0xC, 0x0, 0x0}, /* "P" */
    {0xC, 0xF, 0x2, 0x0}, /* "Q" */
    {0xF, 0xC, 0x2, 0x0}, /* "R" */
    {0x7, 0xB, 0x0, 0x0}, /* "S" */
    {0x0, 0x8, 0x0, 0x5}, /* "T" */
    {0xC, 0x7, 0x0, 0x0}, /* "U" */
    {0xC, 0x0, 0x8, 0x2}, /* "V" */
    {0xC, 0x6, 0xA, 0x0}, /* "W" */
    {0x0, 0x0, 0xA, 0xA}, /* "X" */
    {0x0, 0x0, 0x0, 0xB}, /* "Y" */
    {0x0, 0x9, 0x8, 0x2}  /* "Z" */
};

static void showChar(char c, int position);

/* Configuration Structure for LCD */
LCD_F_Config lcdConf = {.clockSource    = LCD_F_CLOCKSOURCE_ACLK,
                        .clockDivider   = LCD_F_CLOCKDIVIDER_32,
                        .clockPrescaler = LCD_F_CLOCKPRESCALER_1,
                        .muxRate        = LCD_F_4_MUX,
                        .waveforms      = LCD_F_STANDARD_WAVEFORMS,
                        .segments       = LCD_F_SEGMENTS_ENABLED};

int main(void) {
  /* Stop Watchdog  */
  WDT_A_holdTimer();

  /* Initializing all of the function selection bits in the pins */
  P3->SEL1  |= 0xF2;
  P6->SEL1  |= 0x0C;
  P7->SEL1  |= 0xF0;
  P8->SEL1  |= 0xFC;
  P9->SEL1  |= 0xFF;
  P10->SEL1 |= 0x3F;

  /* Setting ACLK to the reference oscillator */
  CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

  /* Initializing the LCD_F module */
  LCD_F_initModule(&lcdConf);

  /* Clearing out all memory */
  LCD_F_clearAllMemory();

  /* Initializing all of our pins and setting the relevant COM lines */
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_0, LCD_F_SEGMENT_LINE_3);
  LCD_F_setPinAsLCDFunction(LCD_F_SEGMENT_LINE_6);
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_16, LCD_F_SEGMENT_LINE_19);
  LCD_F_setPinsAsLCDFunction(LCD_F_SEGMENT_LINE_26, LCD_F_SEGMENT_LINE_47);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_26, LCD_F_MEMORY_COM0);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_27, LCD_F_MEMORY_COM1);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_6, LCD_F_MEMORY_COM2);
  LCD_F_setPinAsCOM(LCD_F_SEGMENT_LINE_3, LCD_F_MEMORY_COM3);

  /* Turing the LCD_F module on */
  LCD_F_turnOn();

  /* 123ABC */
  showChar('1', char1);
  showChar('2', char2);
  showChar('3', char3);
  showChar('A', char4);
  showChar('B', char5);
  showChar('C', char6);

  while (1) { PCM_gotoLPM0(); }
}

static void showChar(char c, int position) {
  uint8_t ii;
  if (c == ' ') {
    for (ii = 0; ii < 4; ii++) { LCD_F->M[position + ii] |= 0x00; }
  } else if (c >= '0' && c <= '9') {
    for (ii = 0; ii < 4; ii++) { LCD_F->M[position + ii] |= digit[c - 48][ii]; }
  } else if (c >= 'A' && c <= 'Z') {
    for (ii = 0; ii < 4; ii++) {
      LCD_F->M[position + ii] |= alphabetBig[c - 65][ii];
    }
  } else {
    LCD_F->M[position] = 0xFF;
  }
}