/* * Initialize LCD controller and flash HELLO on LCD. * The LCD controller of Wytec EduBase board is connected to * a shift register on SPI0 of FRDM-KL25Z. PTA13 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 - Backlight enable * Bit 4 - Data 4 * Bit 5 - Data 5 * Bit 6 - Data 6 * Bit 7 - Data 7 * * For simplicity, all delay below 1 ms uses 1 ms. * */ #include "MKL25Z4.h" #define RS 1 // BIT0 mask for reg select #define EN 2 // BIT1 mask for E #define BL 4 // BIT2 mask for backlight 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 SPI0_init(void); void SPI0_write(unsigned char data); int main(void) { // initialize LCD controller LCD_init(); 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) { SPI0_init(); 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 SPI0_init(void) { SIM->SCGC5 |= 0x1000; /* enable clock to Port D */ PORTD->PCR[1] = 0x200; /* make PTD1 pin as SPI SCK */ PORTD->PCR[2] = 0x200; /* make PTD2 pin as SPI MOSI */ PORTD->PCR[0] = 0x100; /* make PTD0 pin as GPIO */ SIM->SCGC4 |= 0x400000; /* enable clock to SPI0 */ SPI0->C1 = 0x10; /* disable SPI and make SPI0 master */ SPI0->BR = 0x60; /* set Baud rate to 1 MHz */ SPI0->C1 |= 0x40; /* Enable SPI module */ SIM->SCGC5 |= 0x0200; /* enable clock to Port A */ PORTA->PCR[13] = 0x100; /* make PTA13 pin as GPIO */ PTA->PDDR |= 1 << 13; /* make PTA13 as output pin for /SS */ PTA->PSOR = 1 << 13; /* make PTA13 idle high */ } void SPI0_write(unsigned char data) { volatile char dummy; PTA->PCOR = 1 << 13; /* assert /SS */ while(!(SPI0->S & 0x20)) { } /* wait until tx ready */ SPI0->D = data; /* send data byte */ while(!(SPI0->S & 0x80)) { } /* wait until tx complete */ dummy = SPI0->D; /* clear SPRF */ PTA->PSOR = 1 << 13; /* deasssert /SS */ } void LCD_nibble_write(char data, unsigned char control) { data &= 0xF0; // clear lower nibble for control control &= 0x0F; // clear upper nibble for data SPI0_write(data | control | BL); // RS = 0, R/W = 0 SPI0_write(data | control | EN | BL); // pulse E delayMs(0); SPI0_write(data | BL); SPI0_write(BL); } 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 (141.94MHz CPU clock) void delayMs(int n) { int i, j; for(i = 0 ; i < n; i++) for(j = 0; j < 7000; j++) {} /* do nothing */ }