/* Initialize LCD controller and flash HELLO on LCD. * * The LCD controller of Wytec EduPad board is connected to * a shift register on SSI2 of Tiva LaunchPad. PORTC 6 is used * for slave select of the shift register. * * The connections between the shift register and LCD are * Bit 0 - RS (register select) * Bit 1 - E (enable) * Bit 2 - * Bit 4 - Data 4 * Bit 5 - Data 5 * Bit 6 - Data 6 * Bit 7 - Data 7 * * Built and tested with Keil MDK-ARM v5.24a and TM4C_DFP v1.1.0 */ #include "TM4C123.h" #define RS 1 // BIT0 mask for reg select #define EN 2 // BIT1 mask for E void delayMs(int n); void LCD_nibble_write(char data, unsigned char control); void LCD_command(unsigned char command); void LCD_data(char data); void LCD_init(void); void SSI2_Write(unsigned char data); int main(void) { LCD_init(); // initialize LCD controller while(1) { // Write "HELLO" on LCD LCD_data('H'); LCD_data('E'); LCD_data('L'); LCD_data('L'); LCD_data('O'); delayMs(1000); // clear LCD display LCD_command(1); delayMs(1000); } } // initialize SSI2 then initialize LCD controller void LCD_init(void) { SYSCTL->RCGCSSI |= 0x04; // enable clock to SSI2 SYSCTL->RCGCGPIO |= 0x02; // enable clock to GPIOB SYSCTL->RCGCGPIO |= 0x04; // enable clock to GPIOC // PORTB 7, 4 for SSI2 TX and SCLK GPIOB->AMSEL &= ~0x90; // turn off analog of PORTB 7, 4 GPIOB->AFSEL |= 0x90; // PORTB 7, 4 for alternate function GPIOB->PCTL &= ~0xF00F0000; // clear functions for PORTB 7, 4 GPIOB->PCTL |= 0x20020000; // PORTB 7, 4 for SSI2 function GPIOB->DEN |= 0x90; // PORTB 7, 4 as digital pins // PORTC 6 for SSI2 slave select GPIOC->AMSEL &= ~0x40; // disable analog GPIOC->DATA |= 0x40; // set PORTC6 idle high GPIOC->DIR |= 0x40; // set PORTC6 as output for CS GPIOC->DEN |= 0x40; // set PORTC6 as digital pins SSI2->CR1 = 0; // make it master SSI2->CC = 0; // use system clock SSI2->CPSR = 16; // clock prescaler divide by 16 gets 1 MHz clock SSI2->CR0 = 0x0007; // clock rate div by 1, phase/polarity 0 0, mode freescale, data size 8 SSI2->CR1 = 2; // enable SSI2 delayMs(20); // LCD controller reset sequence LCD_nibble_write(0x30, 0); delayMs(5); LCD_nibble_write(0x30, 0); delayMs(1); LCD_nibble_write(0x30, 0); delayMs(1); LCD_nibble_write(0x20, 0); // use 4-bit data mode delayMs(1); LCD_command(0x28); // set 4-bit data, 2-line, 5x7 font LCD_command(0x06); // move cursor right LCD_command(0x01); // clear screen, move cursor to home LCD_command(0x0F); // turn on display, cursor blinking } void SSI2_Write(unsigned char data) { GPIOC->DATA &= ~0x40; // assert chip select SSI2->DR = data; // write data while (SSI2->SR & 0x10) ; // wait for transmit done GPIOC->DATA |= 0x40; // deassert chip select } void LCD_nibble_write(char data, unsigned char control) { data &= 0xF0; // clear lower nibble for control control &= 0x0F; // clear upper nibble for data SSI2_Write (data | control); // RS = 0, R/W = 0 SSI2_Write (data | control | EN); // pulse E delayMs(0); SSI2_Write (data); } void LCD_command(unsigned char command) { LCD_nibble_write(command & 0xF0, 0); // upper nibble first LCD_nibble_write(command << 4, 0); // then lower nibble if (command < 4) delayMs(2); // command 1 and 2 needs up to 1.64ms else delayMs(1); // all others 40 us } void LCD_data(char data) { LCD_nibble_write(data & 0xF0, RS); // upper nibble first LCD_nibble_write(data << 4, RS); // then lower nibble delayMs(1); } /* delay n milliseconds (50 MHz CPU clock) */ void delayMs(int n) { int i, j; for(i = 0 ; i< n; i++) for(j = 0; j < 6265; j++) {} /* do nothing for 1 ms */ }