Port of Building a Low Power Compact LCD Display to TI's MSPM0 controller. I use EasyL1105: A Dev Board for the TI ARM Cortex-M0+ L-Series . This port can be used on any MSPM0 launchpad or board.
LCD
It's a low power 3 character i2c display. There is no backlight. It uses reflected ambient light.
Ref | Code | Mnfr Part # |
LCD1 | 1838930 | LCD-S301C31TR |
Check the original post for the schematic, PCB and BOM.
Connections
Only power and i2c is needed. The EasyL1105 has the necessary pull-up resistors.
signal | LCD board | MSPM0 | EasyL1105 |
---|---|---|---|
GND | 1 | J1-1 | |
I2C SDA | 2 | SDA/PA0 | J1-8 |
I2C SCL | 3 | SCL/PA1 | J11-7 |
3V3 | 4 and 5 | J1-11 |
MSPM0 configuration
This only needs the i2c peripheral. I'm using buffered FIFO, transmit only.
I managed to get the clock up to 800 kHz, and it still worked reliable. I haven't checked yet how (or if) I can configure the controller to go to 1 MHz.
Software
We just need a simple send-only i2c conversation. The only changes I've made to the original code, is
- replace Linux i2c commands with those of the MSPM0 driver library.
- use efficient sprintf() string format lib for lower range microcontrollers to replace the standard lib's sprintf().
#include "printf.h" /* I2C Target address */ #define LCD_ADDR (0x38) // Four possible values for DEVICE_ADDRESS // R1 R2 R3 R4 DEVICE_ADDRESS // Fit FIT 0x60 // Fit Fit 0x61 // Fit Fit 0x62 // Fit Fit 0x63 // Commands (these can be 'continued' by setting the MSB // jc20161120 R1 and R4 mounted on my board #define DEVICE_ADDR 0x62 #define BLINK_OFF 0x70 #define BANK_CMD 0x78 // BANK_CMD bit values #define WR_BANK_A 0x00 #define WR_BANK_B 0x02 #define DISP_BANK_A 0x00 #define DISP_BANK_B 0x01 // ... void i2c_write(int address, unsigned char* buf, unsigned int length) { // Fill FIFO with data. This example will send a MAX of 8 bytes since it // doesn't handle the case where FIFO is full DL_I2C_fillControllerTXFIFO(I2C_INST, buf, length); // Wait for I2C to be Idle while (!( DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; // Send the packet to the controller. // This function will send Start + Stop automatically. DL_I2C_startControllerTransfer(I2C_INST, address, DL_I2C_CONTROLLER_DIRECTION_TX, length); // Poll until the Controller writes all bytes while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) ; // Trap if there was an error if (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_ERROR) { __BKPT(0); } // Wait for I2C to be Idle while (!( DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; // Add delay between transfers // delay_cycles(1000); } // ... int main(void) { SYSCFG_DL_init(); int i; double v; unsigned char text[4]; char_prog_t *progval; unsigned char mode, device, bank, blinkmode; mode=0xc9; // Set static mode, display enabled, continuation enabled device=DEVICE_ADDR | 0x80; // Select the device, continuation enabled bank=BANK_CMD | 0x80 | WR_BANK_A | DISP_BANK_A; blinkmode=BLINK_OFF | 0x80; buf[0] = mode; buf[1] = device; buf[2] = blinkmode; buf[3] = bank; buf[4] = 0x00; // pointer while (true) { for (i = 0; i < 1000; i++) { sprintf(text, "%3d", i); print_line(text); // if (i == 101) { // delay_cycles(100000); // } } } return 0; }
I disabled floating point and exponential format in the printf lib, to reduce code size.
PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS=0
PRINTF_SUPPORT_DECIMAL_SPECIFIERS=0
The LCD, and software, can render numbers with decimal point. If you want to use that, remove the above 2 symbol definitions.
You can then format the LCD text with:
sprintf(text, "%4.1f", v);
although it's just a 3 digit display, it can be used in some interesting low power applications. In a sensor based application, you could make an interface with this display and some buttons. Each button representing an attribute. When you hold the button, the LCD can show the related attribute or value. E;G.: a design that always is in deep sleep, except when it needs to take a sample, or when you press a button to get info... The only time it consumes significant energy is when setting or changing a value. Keeping that value on display costs almost nothing. |
The full code, with binaries (both bootloader and debugger/programmer), is attached: i2c_lcd_EasyL1105_20251010.zip
Thank you for reading.