PIC BASIC TLC5940 code


Closed Thread
Results 1 to 10 of 10
  1. #1
    Join Date
    Aug 2009
    Posts
    5

    Default PIC BASIC TLC5940 code

    Hello,

    I'm trying to setup a PIC using a TLC5940 chip to fade an LED array. I'm writing the code in BASIC. I've been trying to convert over some example code from an Arduino setup but haven't had much luck.

    I think I'm pretty close to getting it, the PIC is shifting out the information and I can see the LEDs blinking on and off, but I don't think I'm getting the BLANK, LATCHING, CLOCKING sequence correct... not sure what the problem is, it should just be a straight conversion.

    Any help would really be great. Thanks!

    Chip specs:
    http://www.ti.com/lit/gpn/tlc5940

    Arduino example code from here:
    http://pixelriot.com/pmatp/node/15

    BASIC code and example Arduino code is attached.

    EDIT: Also, going through the spec sheet it says "Only 3 pins are needed to input data into the device. The rising edge of the SCLK signal shifts the data from the SIN (in my code "SER") pin to the internal register. After all data is clocked in, a high-level pulse of XLAT signal latches the serial data to the internal registers.." So it seems like there should be a method of sending data using only 3 pins, however whenever I search on the internet for examples they always have a much more complicated setup to send data to the TLC5940. There are 2 basic modes Dot Correction Mode and GreyScale mode. I want to use GreyScale mode because it allows you a wider range of fading LEDs. What is the simplest operation to set the LED current for each pin??

    I tried this method (below), which turns on the LEDs but it's not steady. Which leads me to believe I'm not latching correctly or in the right order..

    high BLANK

    for z = 0 to 15
    shiftout SER, SCLK, 1, [4000]
    next z

    high XLAT
    LOW XLAT
    low blank
    Attached Files Attached Files
    Last edited by eletrokat; - 16th August 2009 at 12:17.

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Just a guess.
    Try
    Code:
    pulsout XLAT
    shiftout SER, SCLK, 1, [4000]
    I have not read the data sheet or tried your device. But the above works for other shift registers.
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    Aug 2009
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by mackrackit View Post
    Just a guess.
    Try
    Code:
    pulsout XLAT
    shiftout SER, SCLK, 1, [4000]
    I have not read the data sheet or tried your device. But the above works for other shift registers.

    Isn't turning a pin HIGH and then LOW the same as PULSOUT?


    I've worked a bunch with other shift registers, but mostly they were binary state (ON or OFF). This is the first time I'm working with a PWM chip so I'm a little confused on how to shift out that much information and in what order it needs to be done..

  4. #4
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    I think is has more to do with when the latch is made high. I think it needs done just before the data is sent each time.

    Like I said, just a guess. Give it a try. Might get lucky.
    Dave
    Always wear safety glasses while programming.

  5. #5
    Join Date
    Aug 2009
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by mackrackit View Post
    I think is has more to do with when the latch is made high. I think it needs done just before the data is sent each time.

    Like I said, just a guess. Give it a try. Might get lucky.
    Thanks. Tried it out but I guess I'm not that lucky.
    I think it has to do with how I'm following the Timing Chart?


    Here is the Arduino I'm trying to convert to Basic.

    /*Ti 5940 16-port LED driver
    = overlapped fade across 16 LEDs at a low background level
    * Peter Mackey June 2007 Pratt Digital Arts [email protected]
    * direct adressing to PORTB, smooth flickerless fading (thanks to Amp on the Arduino forum)
    * additional logic from David Cuartielles's & Marcus Hannerstig's LEDdriver demo
    = see the TLC5940 data sheet for the logic behind these pulse sequences
    */

    //using the pin codes on the TLC5940NT to name the Arduino ports
    #define VPRG 2 //"chip pin 27 to Arduino pin 2"
    #define SIN 3
    #define SCLK 7
    #define XLAT 4
    #define BLANK 5
    #define DCPRG 6
    #define GSCLK 8 //note: but using PORTB method

    #define MSINTRVL 0 //could be used to delay updating of incrementFades()
    #define FADEMIN 100 //lowest fade level LEDs will reach (min would be 0, max 4065)
    #define FADEINCR 64 //determines how many steps it takes to run the desired range (lower=longer)

    int fadeLevel[] = {
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //stores a level for each of 16 ports
    int faderNdx = 0; //counter used in this fading sequence

    int fadeState[] = {
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //stores the direction of fading for each port 1,0,-1
    //start with first port

    int next; //used for limit checking in fading function
    float prevMillis; //used for a timing delay

    int word[] = {
    0,0,0,0,0,0,0,0,0,0,0,0}; //temp storage for reversing bits in a word (for greyscale setting)

    void setup() {
    pinMode(VPRG, OUTPUT);
    pinMode(SIN, OUTPUT);
    pinMode(SCLK, OUTPUT);
    pinMode(XLAT, OUTPUT);
    pinMode(BLANK, OUTPUT);
    pinMode(DCPRG, OUTPUT);
    pinMode(GSCLK, OUTPUT); //could also set DDRB directly

    beginSerial(9600); //in case of debugging
    Serial.println("Ready...");

    preset(); //input 'Dot Correction' data
    }

    void loop () {
    setGreys();
    feedPorts();
    if (millis() > (prevMillis+MSINTRVL)){
    incrementFades();
    prevMillis=millis();
    }
    }

    void incrementFades() {
    //a very particular sequence: fade up from LED 0 to 15 then fade down in same direction
    //overlaps incoming&outgoing adjacent ports' fade level

    for (faderNdx=0; faderNdx<=15; faderNdx++) {

    if (fadeState[faderNdx]!=0) { //if the state for this LED is not 0...
    if (fadeState[faderNdx]==1) { //then fade up...
    next = fadeLevel[faderNdx]+FADEINCR;
    if (next<4095) {
    fadeLevel[faderNdx] = next; //...by incrementing the value in the fadeLevel array
    }
    else { //set the state for this LED to fade down
    fadeLevel[faderNdx] = 4095; //be sure is at "max level"
    fadeState[faderNdx] = -1; //flip my sign
    //AND...make next neighbor begin a fade up
    if (faderNdx<15) {
    fadeState[faderNdx+1] = 1;
    }
    else {
    fadeState[0] = 1;
    }
    }//------------------------------------------------
    } //end fading up

    else { //fade down instead...........................
    next = fadeLevel[faderNdx]-FADEINCR;
    if (next>=FADEMIN) { //-----------------
    fadeLevel[faderNdx] = next;
    }
    else {
    //set me to fade down
    fadeLevel[faderNdx] = FADEMIN; //be sure at minimum level
    fadeState[faderNdx] = 0; //stop fading me until neighbor sets me to fade up
    }//------------------------------------------------
    }//end fading down

    }//end check for state not 0
    }// end of cycle thru each port
    }

    //=======5940 control======================================

    void setGreys() {
    //data for each port (12 bit word * 16 ports =192 bits in this loop)...
    //read the fadeLevel array
    for (int i=15; i>=0; i--) { // ports, count DOWN
    int datb = fadeLevel[i];

    //load fade level bits into the temp array BACKWARDS
    for (int j=11; j>=0; j--) {
    word[j]=(datb & 1); //& bitwise AND
    datb >>= 1; //shift right and assign
    // (maybe there's a slicker way to do this!? but this works...)
    }
    //send the data to the 5940
    for (int j=0; j<12; j++) {
    digitalWrite(SIN,word[j]);
    pulseSCLK();
    }
    }
    digitalWrite(XLAT, HIGH);
    digitalWrite(XLAT, LOW);
    }

    void feedPorts() {
    //The actual sequencing of the PWM data into the LEDs, must do constantly...
    digitalWrite(BLANK, HIGH);
    digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle

    for (int i=0; i<4096; i++) {
    pulseGSCLK();
    }
    }

    //DOT CORRECTION...do once
    void preset() {
    //Input 'DotCorrex' Data
    //16 outputs, 64 posssible levels of adjustment, 6 bits/chan = 96 bits total
    //[use if any LEDs in array are physically too bright]

    digitalWrite(DCPRG, HIGH); //leaving it H is my arbitrary choice (="write to register not EEPROM")
    digitalWrite(VPRG, HIGH); //=inputting data into dot correx register

    digitalWrite(BLANK, HIGH); //=all outputs off, when this goes high it resets the greyscale counter
    digitalWrite(SIN, LOW); //to start dot correction
    digitalWrite(XLAT, LOW);

    //begin loading in the dot correx data, most significant bit first...
    //but here we are not correcting anything, so LSB is going first!
    for (int i=0; i<16; i++) { //16 ports
    for (int j=0; j<6; j++) { //6 bits of data for each port
    digitalWrite(SIN, HIGH); //for now, 111111 for everybody
    pulseSCLK();
    digitalWrite(SIN, LOW);
    }
    }

    //----doing the FIRST GREYSCALE SETTING here becuz of the unique 193rd clock pulse

    digitalWrite(XLAT, HIGH); //latch the dot data into the dot correx register
    digitalWrite(XLAT, LOW);
    digitalWrite(VPRG, LOW); //entering greyscale mode

    for (int i=0; i<16; i++) { //16 ports
    int datb = 4095; //using same fade level for all ports this first time

    for (int j=0; j<12; j++) { //data for each port, all the same value to start
    digitalWrite(SIN, datb & 01);
    pulseSCLK();
    datb>>=1;
    }
    }
    digitalWrite(XLAT, HIGH); //latch the greyscale data
    digitalWrite(XLAT, LOW);
    pulseSCLK(); //193rd clock pulse only need to do the FIRST time after dot correx

    digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle... moved here
    }

    //SCLK used in dot correx and greyscale setting
    void pulseSCLK() {
    digitalWrite(SCLK, HIGH);
    digitalWrite(SCLK, LOW);
    }

    void pulseGSCLK() {
    //ultra fast pulse trick, using digitalWrite caused flickering
    PORTB=0x01; //bring PORTB0 high (pin 8), other ports go low [0x01 does only pin 8, 0x21 also lifts pin 13]
    //16nanosecs is the min pulse width for the 5940, but no pause seems needed here
    PORTB=0x20; //keep pin13 high [0x00 would be all low]
    }

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Grayscale values are 12-bits, and you need to send 16 of those values before latching the data, for a total of 192 bits.

    The code in the attachment is sending 1,536 bits (16*12*8).
    And the method you showed in post #1 would only send 128 (16*8).

    And your variable sizes aren't right. fade is a BYTE array, and can't hold 12-bit values. data1 is also a BYTE array, but you're using it like a WORD variable.

    I think something like this will work better ...
    Code:
    fade   var WORD[16]
    TempW  var WORD
    
    setGreys:
        for z = 0 to 15
            TempW = fade(z)
            shiftout ser, sclk, 1, [TempW\12]
        next z
            
        high xlat
        low xlat  
    return
    Then you could ...
    Code:
    RampCount  var WORD
    ChanCount  var BYTE
    
    RampUP:
        FOR RampCount = 0 to 4088 STEP 8
            FOR ChanCount = 0 to 15
                fade(ChanCount) = RampCount
            NEXT ChanCount
            GOSUB setGreys
            PAUSE 50
        NEXT RampCount
    RETURN
    
    RampDN:
        FOR RampCount = 4088 to 0 STEP -8
            FOR ChanCount = 0 to 15
                fade(ChanCount) = RampCount
            NEXT ChanCount
            GOSUB setGreys
            PAUSE 50
        NEXT RampCount
    RETURN
    Dot correction values are 6-bits. 16 of those would total 96-bits.
    <br>
    DT

  7. #7
    Join Date
    Aug 2009
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Thanks for the help with the variable settings. This definitely helps as I'm sure I'm shifting out the right bits now.

    I'm still not getting any response from the TLC5940 though. Now instead of randomly blinking LEDs it's just staying off. I think this is fine because I'm shifting out the right bits, but I'm still confused with the ordering of the LATCH, BLANK, SER.

    If you look at the Timing Chart in the spec sheet they show the ordering, but there is this weird thing where they have a separate pulse GSCLK in addition to the main SCLK pulse. I'm not sure why they have this and I don't know how I'm supposed to do both at the same time..

  8. #8
    Join Date
    Sep 2003
    Location
    INDIA
    Posts
    161


    Did you find this post helpful? Yes | No

    Default Any luck !

    Take a look at this forum topic , maybe it can help you understand the logic of sending data to the chip.

    http://www.picaxeforum.co.uk/showthr...?t=8616&page=3

    let us know when you succeed.

  9. #9
    Join Date
    Aug 2009
    Posts
    5


    Did you find this post helpful? Yes | No

    Default good info

    Hey thanks for that link. That's some really good info. I had to to put this chip on hold because I got swamped with other things, but I was actually going to go back at it this week. This info thread you posted will help.

    I'll post my results (or non-results) later on this week.

    Thanks.

  10. #10
    Join Date
    Mar 2010
    Location
    Minnesota, USA
    Posts
    41


    Did you find this post helpful? Yes | No

    Default My code works but it flickers because my GSCLK is too slow HELP

    How can I get this to stop flickering? It flickers even at 16MHz. With 4 MHz it taks the GSCLK about 250 ms to complete making all the GSDATA that are 0's really stand out causing a flicker.

    Is there some other way I could do the GSCLK so I am not just turning the GSCLK pin H/L 4096 times?

    Code:
    ANSEL = 0 'ALL DIGITAL
    CMCON = 7 'COMPARATORS OFF
    TRISA = %00000000
    TRISB = %00000000
    
    DPIN        CON     7
    SCLK        CON     6
    XLAT        CON     5
    BLANK       CON     2
    VPRG        var     PORTA.0
    DCPRG       var     PORTA.2
    
    
    C1          var     byte
    C2          var     byte
    C3          var     word
    
    GSDATA      var     word
    Code:
    GOSUB preset
    '***************************************************
    '*                    Main Loop                    *
    '***************************************************
    LOOP:
    FOR GSDATA = 4095 TO 0 STEP -16
        gosub setgs
        gosub lightemup
    NEXT
    FOR GSDATA = 4095 TO 0 STEP 16
        gosub setgs
        gosub lightemup
    NEXT
    goto LOOP
    '***************************************************
    '*                      Set GS                     *
    '***************************************************
    SETGS:
    for C1 = 0 to 15                        ' for 16 outputs
        shiftout dpin,sclk,1,[GSDATA\12]    ' shift out 12 bit GS Data
    next
        PORTB = %00100000                   ' high xlat
        PORTB = %00000000                   ' low xlat
    return
    '***************************************************
    '*                   LIGHT EM UP                   *
    '***************************************************
    LIGHTEMUP:
    PORTB = %00000100                       ' high blank
    PORTB = %00000000                       ' All outputs = ON 
    for C3 = 0 to 4095                      ' Generate 4096 GSCLK pulses 
        PORTA = %00001000                   ' GSCLK HIGH 
        PORTA = %00000000                   ' GSCLK LOW 
    next
    return
    '***************************************************
    '*                      Preset                     *
    '***************************************************
    PRESET:
    'HIGH DCPRG
    HIGH VPRG                               ' Put into dot correction mode
    HIGH blank                              ' All outputs OFF
    low dpin                                ' Starts dot correction
    low xlat
    For C1 = 0 to 15                        ' 16 Ports
        shiftout dpin,sclk,1,[%111111\6]    ' 6 bits of Dot Correction per port
    next
    high xlat                               ' Latch bits into dot correct register
    low xlat
    low VPRG                                ' Enter GS Mode
    for C1 = 0 to 15
        for C2 = 0 to 11
            shiftout dpin,sclk,1,[%111111111111\12] 
        next
    next
    high xlat                               ' Latch bits into GS register 
    low xlat
    high SCLK                               '193rd CLK pulse
    LOW SCLK
    low blank                               ' All outputs = ON 
    return
    NOTE: This code is basically the same as the above Adruno code but I have a different fade routine. The above code used direct PORT addressing for GSCLK like I did but they were using an 8MHz Adruno for their project and it worked fine. I don't understand why this will not work in PBP with 16 MHz running the show.
    Last edited by wolwil; - 8th May 2010 at 21:23.

Similar Threads

  1. Making Program Code Space your playground...
    By Melanie in forum Code Examples
    Replies: 15
    Last Post: - 19th July 2008, 08:26
  2. pic Basic Pro 2.50a & debug statement
    By Phil Moore in forum mel PIC BASIC Pro
    Replies: 12
    Last Post: - 17th March 2008, 09:41
  3. PIC BASIC or PIC BASIC PRO
    By kirkmans in forum USB
    Replies: 3
    Last Post: - 20th April 2007, 00:52
  4. Replies: 5
    Last Post: - 17th January 2006, 19:26
  5. Help with MPASM and PIC Basic
    By johngb in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 21st February 2003, 13:07

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts