/* www.microDigitalEd.com * p3_2.c: Initialize and display "Hello" on the LCD using 8-bit data mode. * * Data pins use Port 4; control pins use Port 3. * Polling of the busy bit of the LCD status register is used for timing. * * Tested with Keil 5.20 and MSP432 Device Family Pack V2.2.0. */ #include "msp.h" #define RS 0x20 /* P3.5 mask */ #define RW 0x40 /* P3.6 mask */ #define EN 0x80 /* P3.7 mask */ void delayMs(int n); void LCD_command(unsigned char command); void LCD_command_noPoll(unsigned char command); void LCD_data(unsigned char data); void LCD_init(void); void LCD_ready(void); int main(void) { LCD_init(); while(1) { LCD_command(1); /* clear display */ delayMs(500); LCD_command(0x80); /* set cursor at beginning of first line */ LCD_data('H'); /* write the word "Hello" */ LCD_data('e'); LCD_data('l'); LCD_data('l'); LCD_data('o'); delayMs(500); } } void LCD_init(void) { P3->DIR |= RS | RW | EN; /* make P3 pins output for control */ P4->DIR = 0xFF; /* make P4 pins output for data */ delayMs(30); /* initialization sequence */ LCD_command_noPoll(0x30); /* LCD does not respond to status poll yet */ delayMs(5); LCD_command_noPoll(0x30); delayMs(1); LCD_command_noPoll(0x30); /* busy flag cannot be polled before this command */ LCD_command(0x38); /* set 8-bit data, 2-line, 5x7 font */ LCD_command(0x06); /* move cursor right after each char */ LCD_command(0x01); /* clear screen, move cursor to home */ LCD_command(0x0F); /* turn on display, cursor blinking */ } /* This function waits until LCD controller is ready to * accept a new command/data before returns. * It polls the busy bit of the status register of LCD controller. * In order to read the status register, the data port of the * microcontroller has to change to an input port before reading * the LCD. The data port of the microcontroller is return to * output port before the end of this function. */ void LCD_ready(void) { char status; /* change to read configuration to poll the status register */ P4->DIR = 0; /* Port 4 as input port */ P3->OUT &= ~RS; /* RS = 0 for status */ P3->OUT |= RW; /* R/W = 1, LCD output */ do { /* stay in the loop until it is not busy */ P3->OUT |= EN; /* pulse E high */ delayMs(0); status = P4->IN; /* read status register */ P3->OUT &= ~EN; /* clear E */ delayMs(0); } while (status & 0x80); /* check busy bit */ /* return to default write configuration */ P3->OUT &= ~RW; /* R/W = 0, LCD input */ P4->DIR = 0xFF; /* Port 4 as output */ } /* This function waits for LCD controller ready before issuing * the next command. */ void LCD_command(unsigned char command) { LCD_ready(); /* wait for LCD controller ready */ P3->OUT &= ~(RS | RW); /* RS = 0, R/W = 0 */ P4->OUT = command; /* put command on data bus */ P3->OUT |= EN; /* pulse E high */ delayMs(0); P3->OUT &= ~EN; /* clear E */ } /* This function is used at the beginning of the initialization * when the busy bit of the status register is not readable. */ void LCD_command_noPoll(unsigned char command) { P3->OUT &= ~(RS | RW); /* RS = 0, R/W = 0 */ P4->OUT = command; /* put command on data bus */ P3->OUT |= EN; /* pulse E high */ delayMs(0); P3->OUT &= ~EN; /* clear E */ } /* This function waits for LCD controller ready before issuing * the next data. */ void LCD_data(unsigned char data) { LCD_ready(); /* wait for LCD controller ready */ P3->OUT |= RS; /* RS = 1 */ P3->OUT &= ~RW; /* R/W = 0 */ P4->OUT = data; /* put data on bus */ P3->OUT |= EN; /* pulse E */ delayMs(0); P3->OUT &= ~EN; } /* delay milliseconds when system clock is at 3 MHz */ void delayMs(int n) { int i, j; for (j = 0; j < n; j++) for (i = 250; i > 0; i--); /* Delay */ }