//***************************************************************************** // Last Rev: 1/31/2010 // Lab 2 LCD Code // Purpose: This code demonstrates communication to the LCD screen on the // MCUSLK project board. #include /* common defines and macros */ #include /* derivative information */ #pragma LINK_INFO DERIVATIVE "mc9s12c32" #define ENABLE_BIT 0x80 #define RS_BIT 0x40 void LCDInit(void); void LCDdelay(unsigned long ms); void spiWR(unsigned char data); void LCDWR(unsigned char data); void LCDChar(unsigned char letter); void LCDString(char *pt); void LCDClear(void); void LCDCursorOn(void); void LCDCursorOff(void); void main(void) { EnableInterrupts; LCDInit(); LCDClear(); LCDString("ECE5780\nLab2"); LCDCursorOff(); for(;;) {} /* loop forever */ /* please make sure that you never leave this function */ } //**************************************************************************** // See document AN1774.pdf pg 11 // Purpose: These set of instructions initialize the LCD screen // after power ON. The necessary 4bit data mode is set // and requires two writes for each write. //**************************************************************************** void LCDInit() { //set up SPI to write to LCD SPICR1 = 0x5E; //Data Sheet - PG419 //bit7 - SPI Interrupt Enable Bit //bit6 - SPI System Enable Bit //bit5 - SPI Transmit Interrupt Enable //bit4 - SPI Master/Slave Mode Select Bit //bit3 - SPI Clock Polarity Bit //bit2 - SPI Clock Phase Bit //bit1 - Slave Select Output Enable //bit0 - LSB-First Enable SPICR2 = 0x10; //bit 4 - Mode Fault Enable Bit //bit 3 - Output Enable in the Bidirectional Mode of Operation //bit 1 - SPI Stop in LCDdelay Mode Bit //bit 0 - Serial Pin Control Bit 0 //MISO - Master In, Serial Out //MOSI - Master Out, Serial In //baud rate = 8 MHz / 640 = 12.5 KHz //0100 0110 //baud rate = 8 MHz / 8 = 1 MHz //0111 0000 SPIBR = 0x70; LCDdelay(10); LCDWR(0x03); // Set interface is 8bits LCDdelay(10); LCDWR(0x03); // Set interface is 8 bits LCDdelay(10); LCDWR(0x03); // Set interface is 8 bits LCDdelay(1); LCDWR(0x02); // Set interface is 4 bits LCDWR(0x02); // Set interface is 4 bits LCDWR(0x08); // Specify Display Lines and Fonts LCDdelay(10); // 1 = # of lines, 0 Font //Display OFF LCDWR(0x00); LCDWR(0x08); LCDdelay(10); //Clear display LCDWR(0x00); LCDWR(0x01); LCDdelay(16); //Entry mode Set LCDWR(0x00); LCDWR(0x06); LCDdelay(10); //Turn display on with blinking cursor LCDWR(0x00); LCDWR(0x0F); } //****************************************************************************** //Purpose: This function clears the data from the LCD screen and returns // the cursor back to home. //****************************************************************************** void LCDClear() { //Clear LCDWR(0x00); LCDWR(0x01); LCDdelay(10); //Return the cursor home LCDWR(0x00); LCDWR(0x02); LCDdelay(10); } //****************************************************************************** //Purpose: LCDCursorOff turns off the cursor indicator of the LCD display // proceeds to send the new data. //****************************************************************************** void LCDCursorOff(){ LCDWR(0x00); LCDWR(0x0C); } //****************************************************************************** //Purpose: LCDCursorOn turns on the cursor indicator of the LCD display // //****************************************************************************** void LCDCursorOn(){ LCDWR(0x00); LCDWR(0x0F); } //****************************************************************************** //Purpose: spiWR waits for the SPI to report it's ready to accept new data and then // proceeds to send the new data. //****************************************************************************** void spiWR(unsigned char data) { while (!(SPISR & 0x20)); //Loop until SPTEF = 1 SPIDR = data; //Send data out to 74HC595 Chip } //****************************************************************************** //Purpose: LCDString accepts a string and sends each character // to the LCDChar function to output the character onto the LCD screen. //****************************************************************************** void LCDString(char *pt){ int temp = 0; int j = 0; while(*pt) { if(*pt == '\n') { for(j = 0; j < (40-temp); j++) { LCDChar(' '); } pt++; temp=0; } else { LCDChar(*pt); pt++; temp++; } } } //****************************************************************************** //Purpose: LCDChar sends the proper communication over the SPI to the // 74HC95 chip. The chip in turn communicates with the LCD module as // specified in the AN1774 document. //****************************************************************************** void LCDChar(unsigned char outchar){ // Output the higher four bits. spiWR((0x0F&(outchar>>4)) & ~ENABLE_BIT | RS_BIT); // Place data onto bus LCDdelay(1); spiWR((0x0F&(outchar>>4)) | ENABLE_BIT | RS_BIT); // Set EN LCDdelay(1); // LCDdelay for 1 ms. spiWR((0x0F&(outchar>>4)) & ~ENABLE_BIT | RS_BIT); // Clear EN. LCDdelay(1); // Output the lower four bits. spiWR((0x0F&(outchar)) & ~ENABLE_BIT | RS_BIT); // Place lower four bits onto bus. LCDdelay(1); spiWR((0x0F&(outchar)) | ENABLE_BIT | RS_BIT); // Set EN LCDdelay(1); // LCDdelay for 1ms. spiWR((0x0F&(outchar)) & ~ENABLE_BIT | RS_BIT); // Clear EN LCDdelay(1); } //****************************************************************************** //Purpose: Displays a character from 1 to 9 //****************************************************************************** void LCDNum(int val) { //Add the offset in the ascii table //to get the character code unsigned char outchar=48+val; //print out the new character LCDChar(outchar); } //****************************************************************************** //Purpose: Displays number from 1 to 128. //****************************************************************************** void LCDDecimal(unsigned char val) { unsigned char low; unsigned char med; unsigned char high; //Get the lowest digit low=val%10; //shift right in decimal val=val/10; //Get the second digit med=val%10; ; //shift right in decimal val=val/10; //get the high digit high=val%10; //Print the digits from high to low (left to right) LCDNum(high); LCDNum(med); LCDNum(low); } //****************************************************************************** //Purpose: Displays a 5 digit integer.. //****************************************************************************** void LCDInt(unsigned int val) { unsigned char part0; unsigned char part1; unsigned char part2; unsigned char part3; unsigned char part4; //get the first digit part0=val%10; //shift right in decimal val=val/10; //get the second digit part1=val%10; //shift right in decimal val=val/10; //get the third digit part2=val%10; //shift right in decimal val=val/10; //get the fourth digit part3=val%10; //shift right in decimal val=val/10; //get the fifth digit part4=val%10; //Print the digits from high to low (left to right) LCDNum(part4); LCDNum(part3); LCDNum(part2); LCDNum(part1); LCDNum(part0); } //****************************************************************************** //Purpose: Displays two Hex digits preceded by "0x".. //****************************************************************************** void LCDHex(unsigned char val) { unsigned char upper; unsigned char lower; //Print the hex symbol LCDString("0x"); //put the high 4 bits in upper upper=val>>4; upper=upper&0x0F; //put the low 4 bits in lower lower=val&0x0F; //Print upper if(upper < 10) { //if less than 10 it is a digit LCDNum(upper); } else { //if more than 10 it is a letter //Add the ascii offset-10 of the letters upper=upper+55; LCDChar(upper); } //Print lower if(lower < 10) { //if less than 10 it is a digit LCDNum(lower); } else { //if more than 10 it is a letter //Add the ascii offset-10 of the letters lower=lower+55; LCDChar(lower); } } //****************************************************************************** //Purpose: LCDWR sends a 4-bit messages to the LCD module. Used to send // setup instructions to the LCD module. //****************************************************************************** void LCDWR(unsigned char data) { spiWR(data & ~ENABLE_BIT); LCDdelay(1); spiWR(data | ENABLE_BIT); // Set EN LCDdelay(1); spiWR(data & ~ENABLE_BIT); // Clear EN LCDdelay(1); } //****************************************************************************** //Purpose: LCDdelay is a custom delay function that loops for a number of cycles // based on the number of miliseconds specified in its parameter. //****************************************************************************** void LCDdelay(unsigned long ms) { char i; for (i=0;i < ms; i++) { asm { PSHX LDX #$640 Loop: NOP NOP DBNE X, Loop PULX } } }