Implementing a LCD Screen.. in C

Discussion in 'Embedded Systems and Microcontrollers' started by jenxin, Dec 2, 2012.

  1. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    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.

    Code ( (Unknown Language)):
    1. ;  SPI Setup
    2. ;
    3.  
    4.     LDAA    #$22
    5.     STAA     SPIB        ; SPI clocks a 1/24 of E-Clock
    6.         MOVB   #$3B, DDRM        ; Setup PortM data direction
    7. ;
    8. ; Setup for Master, enable, and high speed SPI
    9. ;
    10.     LDAA    #$50
    11.         STAA     SPCR1
    12.     LDAA    #$00
    13.     STAA    SPCR2     ; No need for this since SPRC2 = $00 at RESET
    14. ;
    15. ; Done with SPI Setup
    16. ;
    17. ;
    18. ; Better Setup Control Lines too
    19. ;
    20. ;
    21.         BSET PortM, RCK      ; Set RCK to Idle HIGH
    22.         BCLR PortM, ENABLE   ; ENABLE to Idle LOW
    23. ;
    24. ;
    25. ; Done with Control Lines
    26.  
    27. Command    
    28.  
    29. spi_a:    BRCLR   SPSR,$20,spi_a         ; Wait for register empty flag (SPIEF)
    30.     STAA    SPDR            ; Output command  via SPI to SIPO
    31. CKFLG1  BRCLR SPSR,$80, CKFLG1          ; Wait for SPI Flag
    32.     LDAA    SPDR
    33.         NOP                             ; Wait
    34.         BCLR    PortM, RCK              ; Pulse RCK
    35.     NOP
    36.     NOP
    37.         BSET    PortM, RCK              ; Command now available for LCD
    38.     BCLR    PortM, RS            ; RS = 0 for commands
    39.     NOP
    40.     NOP                ; Probably do not need to wait
    41.     NOP                ; but we will, just in case ...
    42.     BSET    PortM, ENABLE        ; Fire ENABLE
    43.     NOP                ; Maybe we will wait here too ...
    44.     NOP
    45.     BCLR    PortM, ENABLE        ; ENABLE off
    46.     JSR    delay
    47.     RTS
    48.  
    49. Print    
    50. spi_b:    BRCLR   SPSR,$20,spi_b
    51.      STAA    SPDR            ; Output data via SPI to SIPO
    52. CKFLG2  BRCLR   SPSR, $80, CKFLG2       ; Wait for SPI Flag
    53.     LDAA    SPDR
    54.         NOP                             ; Wait
    55.         BCLR    PortM, RCK              ; Pulse RCK
    56.         NOP
    57.     NOP
    58.         BSET    PortM, RCK              ; Data now available for LCD
    59.         BSET    PortM, RS        ; RS = 1 for data
    60.     NOP
    61.     NOP
    62.     BSET    PortM, ENABLE
    63.     NOP
    64.     NOP
    65.     BCLR    PortM, ENABLE
    66.     JSR    delay
    67.     RTS
     
  2. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,004
    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.
     
  3. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,004
    Also be aware that I am not sure how popular the HCS12 is around here. The pic and a few others are pretty popular.
     
  4. jenxin

    Thread Starter New Member

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

    I've tried this but not working.

    Code ( (Unknown Language)):
    1. void InitLCD(void)
    2. {
    3.   char a = 0x38;
    4.   Command(a);
    5.   delay3();
    6.   a = 0x0C;
    7.   Command(a);
    8.   Clear();
    9. }
    10. void Command(char a)
    11. {
    12.   while(!(SPISR & 0x20));
    13.   SPIDR = a;
    14.   while(!(SPISR & 0x80));
    15.   a = SPIDR;
    16.   asm(nop);
    17.   PORTM = PORTM & RCK;
    18.   asm(nop);
    19.   asm(nop);
    20.   PORTM = PORTM | RCK;
    21.   PORTM = PORTM & RS;
    22.   asm(nop);
    23.   asm(nop);
    24.   asm(nop);
    25.   PORTM = PORTM | ENABLE;
    26.   asm(nop);
    27.   asm(nop);
    28.   PORTM = PORTM & ENABLE;
    29.   delay();
    30. }
    31. void Print(char a)
    32. {
    33.   while(!(SPISR & 0x20));
    34.   SPIDR = a;
    35.   while(!(SPISR & 0x80));
    36.   a = SPIDR;
    37.   asm(nop);
    38.   PORTM = PORTM & RCK;
    39.   asm(nop);
    40.   asm(nop);
    41.   PORTM = PORTM | RCK;
    42.   PORTM = PORTM | RS;
    43.   asm(nop);
    44.   asm(nop);
    45.   asm(nop);
    46.   PORTM = PORTM | ENABLE;
    47.   asm(nop);
    48.   asm(nop);
    49.   PORTM = PORTM & ENABLE;
    50.   delay();
    51. }
    52. void Clear(void)
    53. {
    54.   char a = 0x01;
    55.   Command(a);
    56.   delay();
    57. }
     
  5. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    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.
     
  6. jenxin

    Thread Starter New Member

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

    Code ( (Unknown Language)):
    1. void delay3(void)
    2. {
    3.   int y = 0x0F;
    4.   while (y!=0){
    5.     int x = 0xFFFF;
    6.     while(x!=0){
    7.       x--;
    8.     }
    9.     y--;
    10.   }
    11. }
    Code ( (Unknown Language)):
    1. DELAY3    PSHA        ; Store registers
    2.           PSHY        ;
    3.           LDAA    #$0F  ; 15x
    4. AA6:        LDY    #$FFFF    ; Approx 65535 times..
    5. A6:          DEY              ; 1 Clock Cycle
    6.             BNE    A6      ; 3 Clock Cycles
    7.             DECA        ; 1 Clock Cycle
    8.             BNE    AA6        ; 3 Clock cycles
    9.             PULY        ;
    10.             PULA        ; Get registers
    11.             RTS         ; ((4*65535)+1+3)*15 ~ 164ms
     
  7. MrChips

    Moderator

    Oct 2, 2009
    12,440
    3,361
    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:

    Code ( (Unknown Language)):
    1.  
    2.    PORTM = PORTM | RS;
    3.  
    4. becomes
    5.  
    6.   PORTM |= RS;
    7.  
    8. and
    9.  
    10.   PORTM = PORTM & ~ENABLE;
    11.  
    12. becomes
    13.  
    14.   PORTM &= ~ENABLE;
    15.  
    16.  
     
  8. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,004

    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++);
     
  9. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    I assume that the objective of these lines was to create a pulse:
    Code ( (Unknown Language)):
    1.  
    2.   PORTM = PORTM | ENABLE;
    3.   asm(nop);
    4.   asm(nop);
    5.   PORTM = PORTM & ENABLE;
    6.  
    This must fail. You should be able to see why.
     
  10. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    You can use

    Code ( (Unknown Language)):
    1. PORTM&=(0xFF-ENABLE);
     
  11. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    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..?
     
  12. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    Yes I have a debugger, and sure I can do that also. Currently it runs through all the code, just not working properly.
     
  13. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    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.
     
  14. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    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
     
  15. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    And I see, I had to AND with the compliment of enable.
     
  16. jenxin

    Thread Starter New Member

    Nov 26, 2012
    27
    0
    Alright, I fixed it. Thanks! But am still curious on the above question.. Now it prints out just fine.
     
Loading...