• AVR Freaks

LockedImplementing serial data stream for uPD7225 7/14 segment LCD driver

Author
PStechPaul
Super Member
  • Total Posts : 2428
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
2013/10/12 16:27:41 (permalink)
0

Implementing serial data stream for uPD7225 7/14 segment LCD driver

I have some 7 segment LCD displays that are controlled via a 10 pin connector and a NEC uPD7225. I am using a PIC16F684 and XC8 1.20 to control the display. The data sheet can be found at:
http://www.pacificdisplay.com/ics_app%20notes/nec/upd7225.pdf
 
I bought the displays on eBay: http://www.ebay.com/itm/Serial-12-DIGIT-7-SEG-LCD-Display-Module-KTM-S1201-NEW-/170968157104?ssPageName=ADME:X:AAQ:US:1123
Here is info on the display: http://www.pongrance.com/SLCD-data-notes.pdf
There are some demos and Arduino information at:
http://tronixstuff.wordpress.com/2013/03/11/arduino-and-ktm-s1201-lcd-modules/#comment-18059
 
My project (as it stands at this point) is attached.
 
I struggled for quite awhile with some water and conductive deposits on the boards under the connectors, as well as a faulty ribbon cable, which caused poor signals as observed on a scope, but after fixing that the display just powers up and shows all 8s with DPs. I used the Arduino code and ported it to the Microchip XC8 compiler but there were (and still are) some parts that cause warnings or errors. I used the software simulator and the trace shows what appears to be correct timing of the serial data and clock pulses, but the method of shifting the data to the port pin seems inefficient and time varies from about 25 uSec to 12 uSec with a 2 MHz instruction cycle. Here is the code:
void ktmshiftOut(byte val)  // same as shiftout command but invert Sck
{
  int i;
  for (i=0;i<8;i++)
  {
    PORTCbits.LcdSDA=!!(val & (1<< (7-i)));     //32 uSec
    PORTCbits.LcdSCL=LOW;                       //500nSec
//    delay(1);
    PORTCbits.LcdSDA=!!(val & (1<< (7-i)));     //32 uSec
    PORTCbits.LcdSCL=HIGH;
//    delay(1);
  }
  delay(1);
}

This is called by functions such as this which sends a command:
void ktmCommand(byte _cmd)
{
  PORTCbits.LcdCnD=HIGH;
  delay(1);
  PORTCbits.LcdnCs=LOW;
  delay(10);
  ktmshiftOut(_cmd);
  delay(1);
  PORTCbits.LcdnCs=HIGH; //deselect LCD to display data
  delay(10);
}

and
void ktmWriteHex(int hexVal,int pos){
   byte TextString[12]={_,_,_,_,_,_,_,_,_,_,_,_}; // Ultimate buffer of characters to write.
  // Iterate through human readable array and stuff TextString with hex values.
  TextString[pos]=hexVal;
  PORTCbits.LcdCnD=LOW;   //Put in data mode
  delay(1);
  PORTCbits.LcdnCs=LOW;
  delay(10);
  for (int i = 11; i >= 0; i --)//Put in KTM-S1201 Right Character First
  {
    ktmshiftOut(TextString[i]);
  }
  PORTCbits.LcdnCs=HIGH; //deselect LCD to display data
  delay(10);                    //always delay after LcdnCs change
}

I changed the following to be placed in flash ROM rather than RAM as originally coded for the Arduino:
static int anCount=39; // one less than actual since 0 based indexes.
const byte anConst[39]= {_A,_B,_C,_D,_E,_F,_G,_H,_I,_J,_K,_L,_M,_N,_O,_P,_Q,_R,_S,_T,_U,_V,_W,_X,_Y,_Z,_1,_2,_3,_4,_5,_6,_7,_8,_9,_0,_,_DASH,_DEGREE};
const unsigned char anHumanConst[39]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0',' ','-','*'};

They were originally static byte as shown in the KTMS1201example.ino file, and would not fit the RAM space, but it seems they should be in ROM.
 
But for now I want to see if I can make a better algorithm to shift out the bits in the byte used for the ktmShiftOut function. The following seems to work OK with 15 uSec consistent delay for each bit:
void ktmshiftOut(byte val)  // same as shiftout command but invert Sck
{
  int i;
  for (i=0;i<8;i++)
  {
    PORTCbits.LcdSDA = !!(val & 0x80);  // 5.5 uSec, 15 uSec for each loop iteration
    PORTCbits.LcdSCL=LOW;                       //500nSec
    val <<= 1;
    PORTCbits.LcdSCL=HIGH;
  }
  delay(1);
}

It seems that I need the double negation (!!) to work for setting the port pin high or low.
 
I wonder if my problem is the R/M/W problem? I'll try implementing a port buffer.
 
Thanks!
 

 
#1

3 Replies Related Threads

    Ian.M
    Super Member
    • Total Posts : 13263
    • Reward points : 0
    • Joined: 2009/07/23 07:02:40
    • Location: UK
    • Status: offline
    Re:Implementing serial data stream for uPD7225 7/14 segment LCD driver 2013/10/12 16:55:58 (permalink)
    +1 (1)
    In ktmshiftOut(), you can save a few cycles by making i an unsigned char, initialising it to 7 and using a do{ ...... }while(--i); loop.   That particular specific loop will compile to DECFSZ _i,F and a GOTOwink
     
    Its certainly worth rewriting the code to avoid RMW using a shadow register. It will  be a little slower but will be far less likely to misbehave.   However wouldn't it be simpler to upgrade to a PIC with LATx registers and/or a SPI module?
    #2
    PStechPaul
    Super Member
    • Total Posts : 2428
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: offline
    Re:Implementing serial data stream for uPD7225 7/14 segment LCD driver 2013/10/12 19:00:31 (permalink)
    0
    I do have a couple of PIC16F1825 I could use, but I have quite a few of the PIC16F684 and I wanted to use the simplest part possible. But this is really an evaluation of what I can do with this cheap ($0.99) display to add to various projects. I would like to use SPI or I2C but this display uses at least 4 I/O lines.
     
    In trying to implement the shadow register, I tried the following:
     
     
    #define LcdSCL  RC0 //Not Serial clock
    #define LcdSDA  RC1 //Serial data in
    #define LcdCnD  RC2 //Command or Not data in
    #define LcdnRes RC3 //Not reset low = reset
    #define LcdnBus RC4// Input Only, Not Busy output from LCD not used if delay(1) after LcdnCs changes
    #define LcdnCs  RC5 //Not chip select low = select
        union   {
            byte b;
            unsigned LcdSCL: 1;
            unsigned LcdSDA: 1;
            unsigned LcdCnD: 1;
            unsigned LcdnRes: 1;
            unsigned LcdnBus: 1;
            unsigned LcdnCs: 1;
        }PORTCbuff;
      PORTC = 0;
      PORTCbuff.b = PORTC;
      PORTCbuff.LcdCnD=HIGH;
      PORTC=PORTCbuff.b;

    However, this is supposed to set bit 2, but instead it sets bit 0, and the debugger shows all of the bit field members identified as PORTCbuff.RC0..5 with the same value.  I did a little searching and found a way to do this so that it works. I'm a "bit" rusty when it comes to unions, structures, and bitfields.
        union   { 
            struct {byte b;};
            struct {
            unsigned LcdSCL: 1;
            unsigned LcdSDA: 1;
            unsigned LcdCnD: 1;
            unsigned LcdnRes: 1;
            unsigned LcdnBus: 1;
            unsigned LcdnCs: 1; };
        }PORTCbuff;
     
    I'll post more if and when I get this project working. Thanks!

     
    #3
    PStechPaul
    Super Member
    • Total Posts : 2428
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: offline
    Re:Implementing serial data stream for uPD7225 7/14 segment LCD driver 2013/10/13 02:29:25 (permalink)
    0
    Hooray! Smile
     
    I got this thing working, finally. The shadow register for PORTC seemed to help, but it also caused problems in the places where I forgot to change the code. Another thing was that, after setting the proper display mode, I had to change the contrast quite a bit to see the characters. So it may have been actually working at some point and I just didn't see it. But there was also a bug that held the display in reset, which I found by checking the voltages on the pins.
     
    There were some problems with the conventions for strings and character pointers, and a weird error about sprintf that I fixed by using memcpy. Not sure why, since I have used sprintf in other projects, but I'm just happy that it now works.
     
    The project files are attached.
     
    Whew! [8D]

     
    #4
    Jump to:
    © 2019 APG vNext Commercial Version 4.5