//***************************************************************************** // 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 Init(void); int ReadInput(void); //TODO: Change this so it returns char instead. void LCDInit(void); void LCDdelay(unsigned long ms); void spiWR(unsigned char data); void LCDWR(unsigned char data); void LCDChar(unsigned char letter); void LCDNum(int val); void LCDClear(void); void LCDCursorOn(void); void LCDCursorOff(void); void main(void) { //TODO: Replace the declaration below with "char value = 0x00;" instead. int value = 0; EnableInterrupts; Init(); LCDInit(); LCDClear(); value = ReadInput(); //TODO: Replace the call to LCDNum below with "LCDChar(value);" instead; LCDNum(value); LCDCursorOff(); for(;;) {} /* loop forever */ /* please make sure that you never leave this function */ } void Init() { //Set the data direction of bits 0-7 on port T to inputs. DDRT = DDRT&~(DDRT_DDRT1_MASK | DDRT_DDRT2_MASK | DDRT_DDRT3_MASK| DDRT_DDRT4_MASK| DDRT_DDRT5_MASK | DDRT_DDRT6_MASK | DDRT_DDRT7_MASK); } //TODO: Change this so it returns a char instead. int ReadInput() { /* TODO: Put Your Code HERE!!! This is the only segment that you are allowed to change other than the todo's above and your solution must be in assembly. */ asm{ //int count = 0; CLRB CLRA PSHD //Check each of the bits of the input an increment count if they are "on" //if (PTT & PTT_PTT0_MASK) BRCLR _PTT,#1,*+8 ;abs = 000b //count++; INCB STD 0,SP //if (PTT & PTT_PTT1_MASK) BRCLR _PTT,#2,*+7 ;abs = 0012 //count++; BSR *+48 ;abs = 0040 //if (PTT & PTT_PTT2_MASK) BRCLR _PTT,#4,*+7 ;abs = 0019 //count++; BSR *+41 ;abs = 0040 //if (PTT & PTT_PTT3_MASK) BRCLR _PTT,#8,*+7 ;abs = 0020 //count++; BSR *+34 ;abs = 0040 //if (PTT & PTT_PTT4_MASK) BRCLR _PTT,#16,*+7 ;abs = 0027 //count++; BSR *+27 ;abs = 0040 //if (PTT & PTT_PTT5_MASK) BRCLR _PTT,#32,*+7 ;abs = 002e //count++; BSR *+20 ;abs = 0040 //if (PTT & PTT_PTT6_MASK) BRCLR _PTT,#64,*+7 ;abs = 0035 //count++; BSR *+13 ;abs = 0040 //if (PTT & PTT_PTT7_MASK) BRCLR _PTT,#128,*+7 ;abs = 003c //count++; BSR *+6 ;abs = 0040 //return count; LDD 0,SP PULX RTS LDX 2,SP INX STX 2,SP RTS } } //**************************************************************************** // 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: 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: 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 } } }