Implementing a LCD Screen.. in C

Thread Starter

jenxin

Joined Nov 26, 2012
27
Hi, after my last project was completed(thanks!) Another one comes up.
This is easy for me to implement in assembly, but I have no clue at all on how to do this in C.
Note* my past 10 projects in this class has been in assembly.. And I have never taken a programming class other then java, but C looks fairly similar.

My question is how I can implement a Seiko L1642 LCD screen. I used to be able to do this in ASM easily. Note I am using the built in SPI system in my microcontroller, HCS12(68HC12) 32PIN.

Previously been driving my LCD with a 74HC595N and the SPI subsystem.
I'm not too sure on how to convert the BSETs and BCLRs and BRCLR.

This was all I needed to initialize my LCD screen.

Rich (BB code):
;  SPI Setup
;

    LDAA    #$22
    STAA     SPIB        ; SPI clocks a 1/24 of E-Clock
        MOVB   #$3B, DDRM        ; Setup PortM data direction 
;
; Setup for Master, enable, and high speed SPI
;
    LDAA    #$50
        STAA     SPCR1
    LDAA    #$00
    STAA    SPCR2     ; No need for this since SPRC2 = $00 at RESET
;
; Done with SPI Setup
;
;
; Better Setup Control Lines too
;
;
        BSET PortM, RCK      ; Set RCK to Idle HIGH
        BCLR PortM, ENABLE   ; ENABLE to Idle LOW
;
;
; Done with Control Lines

Command    

spi_a:    BRCLR   SPSR,$20,spi_a         ; Wait for register empty flag (SPIEF)
    STAA    SPDR            ; Output command  via SPI to SIPO
CKFLG1  BRCLR SPSR,$80, CKFLG1          ; Wait for SPI Flag
    LDAA    SPDR
        NOP                             ; Wait
        BCLR    PortM, RCK              ; Pulse RCK
    NOP
    NOP
        BSET    PortM, RCK              ; Command now available for LCD
    BCLR    PortM, RS            ; RS = 0 for commands
    NOP
    NOP                ; Probably do not need to wait
    NOP                ; but we will, just in case ...
    BSET    PortM, ENABLE        ; Fire ENABLE
    NOP                ; Maybe we will wait here too ...
    NOP
    BCLR    PortM, ENABLE        ; ENABLE off
    JSR    delay
    RTS

Print    
spi_b:    BRCLR   SPSR,$20,spi_b
     STAA    SPDR            ; Output data via SPI to SIPO
CKFLG2  BRCLR   SPSR, $80, CKFLG2       ; Wait for SPI Flag
    LDAA    SPDR
        NOP                             ; Wait
        BCLR    PortM, RCK              ; Pulse RCK
        NOP
    NOP
        BSET    PortM, RCK              ; Data now available for LCD
        BSET    PortM, RS        ; RS = 1 for data
    NOP
    NOP
    BSET    PortM, ENABLE
    NOP
    NOP
    BCLR    PortM, ENABLE
    JSR    delay
    RTS
 

spinnaker

Joined Oct 29, 2009
7,830
If it works in assembler why covert to C? You know you can call assembler fro C right?


Assuming you still want to convert to C:

First forget about directly converting your code to C. Use it more as a block diagram other than a direct translation.

Your first mission is to simply get the SPI bus to work in C. It really helps if you have a scope or even better a logic analyzer. You could also use a nice and simple SPI device like a shift register and some LEDs or some other simple chip.

Many compilers have an SPI library. Others will argue against using them but I say why not use the tools others have provided. You wouldn't write your own OS to display something on the LCD in Windows, why would then do the same type of thing in mcus?

Once you have the SPI bus initialized and sending data you can move on. Remember you can still use your existing code as a guide. Your code, library documentation and data sheet are all sources of valuable documentation.
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
The professor wants us to write in C.. :\

I've tried this but not working.

Rich (BB code):
void InitLCD(void)
{
  char a = 0x38;
  Command(a);
  delay3();
  a = 0x0C;
  Command(a);
  Clear();
}
void Command(char a)
{
  while(!(SPISR & 0x20));
  SPIDR = a;
  while(!(SPISR & 0x80));
  a = SPIDR;
  asm(nop);
  PORTM = PORTM & RCK;
  asm(nop);
  asm(nop);
  PORTM = PORTM | RCK;
  PORTM = PORTM & RS;
  asm(nop);
  asm(nop);
  asm(nop);
  PORTM = PORTM | ENABLE;
  asm(nop);
  asm(nop);
  PORTM = PORTM & ENABLE;
  delay();
}
void Print(char a) 
{
  while(!(SPISR & 0x20));
  SPIDR = a;
  while(!(SPISR & 0x80));
  a = SPIDR;
  asm(nop);
  PORTM = PORTM & RCK;
  asm(nop);
  asm(nop);
  PORTM = PORTM | RCK;
  PORTM = PORTM | RS;
  asm(nop);
  asm(nop);
  asm(nop);
  PORTM = PORTM | ENABLE;
  asm(nop);
  asm(nop);
  PORTM = PORTM & ENABLE;
  delay();
}
void Clear(void)
{
  char a = 0x01;
  Command(a);
  delay();
}
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
I am aware that there are many libraries, but the professor hasn't provided us with any info on how to use them besides. As this project is due tuesday, i thought it'd be much easier to use what I have then figure out how to use some of these libraries.
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
Also, would this be equivalent?? Trying to change my previous delays into C also.. ugh.

Rich (BB code):
void delay3(void)
{
  int y = 0x0F;
  while (y!=0){
    int x = 0xFFFF;
    while(x!=0){
      x--;
    }
    y--;
  }
}
Rich (BB code):
DELAY3    PSHA        ; Store registers
          PSHY        ;
          LDAA    #$0F  ; 15x
AA6:        LDY    #$FFFF    ; Approx 65535 times.. 
A6:          DEY              ; 1 Clock Cycle
            BNE    A6      ; 3 Clock Cycles
            DECA        ; 1 Clock Cycle
            BNE    AA6        ; 3 Clock cycles
            PULY        ;
            PULA        ; Get registers
            RTS         ; ((4*65535)+1+3)*15 ~ 164ms
 

MrChips

Joined Oct 2, 2009
30,810
The elegant way to SET and CLR a bit is by using structures and unions.

The obvious way to set is to OR with a bit mask.
To clear, AND with the 1's complement of the bit mask.

Note that in C there is a simplified syntax:

Rich (BB code):
   PORTM = PORTM | RS;

becomes

  PORTM |= RS;

and

  PORTM = PORTM & ~ENABLE;

becomes

  PORTM &= ~ENABLE;
 

spinnaker

Joined Oct 29, 2009
7,830
Also, would this be equivalent?? Trying to change my previous delays into C also.. ugh.

Rich (BB code):
void delay3(void)
{
  int y = 0x0F;
  while (y!=0){
    int x = 0xFFFF;
    while(x!=0){
      x--;
    }
    y--;
  }
}
Rich (BB code):
DELAY3    PSHA        ; Store registers
          PSHY        ;
          LDAA    #$0F  ; 15x
AA6:        LDY    #$FFFF    ; Approx 65535 times.. 
A6:          DEY              ; 1 Clock Cycle
            BNE    A6      ; 3 Clock Cycles
            DECA        ; 1 Clock Cycle
            BNE    AA6        ; 3 Clock cycles
            PULY        ;
            PULA        ; Get registers
            RTS         ; ((4*65535)+1+3)*15 ~ 164ms

DO you have a debugger? It is a really big help for stepping through your code to see what it is doing.

I would use a for statement instead. Depening on your compiler you could do something like this.

#define MAX_DELAY 10000


for (unsigned int i=0; i<= MAX_DELAY; i++);
 

John P

Joined Oct 14, 2008
2,026
I assume that the objective of these lines was to create a pulse:
Rich (BB code):
  PORTM = PORTM | ENABLE;
  asm(nop);
  asm(nop);
  PORTM = PORTM & ENABLE;
This must fail. You should be able to see why.
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
I assume that the objective of these lines was to create a pulse:
Rich (BB code):
  PORTM = PORTM | ENABLE;
  asm(nop);
  asm(nop);
  PORTM = PORTM & ENABLE;
This must fail. You should be able to see why.
Why would that fail? Sorry I am new to C.(this is my first C program) You need to create the pulse though since this is connected to a SIPO SR. Else how am I going to shift the bits over..?
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
DO you have a debugger? It is a really big help for stepping through your code to see what it is doing.

I would use a for statement instead. Depening on your compiler you could do something like this.

#define MAX_DELAY 10000


for (unsigned int i=0; i<= MAX_DELAY; i++);
Yes I have a debugger, and sure I can do that also. Currently it runs through all the code, just not working properly.
 

John P

Joined Oct 14, 2008
2,026
Write down the values of PORTM and ENABLE, both before and after the two operations.

Seriously, you must understand how logical manipulations like this work, if you want your device to function properly.
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
What I don't get is if for example,
#define RCK 0x08
value at PORTM is $0414

I do the following,
PORTM |= RCK , and I'm getting $0C1C

why is it doing it for 2 bytes instead of 1? I want it to be 041C
 

Thread Starter

jenxin

Joined Nov 26, 2012
27
Write down the values of PORTM and ENABLE, both before and after the two operations.

Seriously, you must understand how logical manipulations like this work, if you want your device to function properly.
And I see, I had to AND with the compliment of enable.
 
Top