Jump to content
43oh

TLC5940


Recommended Posts

hey,

 

i am almost done with my first project ... but now i am standing in front of a little problem ...

 

i want to control 2 TLC's ... they will be daisy-chained ... but i have only 4 Outputs left

 

1.0 green LED

1.1 TXD

1.2 RXD

1.3 reserved for TLC's

1.4 reserved for TLC's

1.5 reserved for TLC's

1.6 red LED

1.7 reserved for TLC's

XIN - quartz-crystal

XOUT - quartz-crystal

 

i dont need RST and TEST ... is there a way to take control over them?

 

is there a way to feed data to the TLC's with only 4 wires?

Link to post
Share on other sites

Well, first there is http://www.ti.com/lit/an/slva242/slva242.pdf

How to cascade the TLC5940 by TI.

 

Second, do you really need the red and green leds on the launchpad? Do you need both? Even if you do, there are better ways of doing it (Add a third tlc5940 or use a single pin to control two leds http://www.neufeld.newton.ks.us/electronics/?p=151 ).

 

But really, when you are getting atleast 32 led outputs, why bother with the two onboard leds? At the least it seems like you need 5 pins for the tlc5940, cascaded.

Link to post
Share on other sites

The idea with the LED's is nice - but with one digital output ... one of both must be on

 

i use these LEDs for startup sequence ...

- off

- DCO calibration

- UART calibration

- initialization

- ready for action

 

but i think i will reduce it to one LED - i wont need these information anymore when i wrote the software

 

---

 

Search the web for "LightPack USB" - i am doing this for the MSP430G2211 + 2 TLC5940 - better: i am almost done - waiting for my TLC's to arrive and some more (and brighter) LED's ;)

 

i cant use the TLC's outputs because i need (want) them - all! :mrgreen: and maybe later for extending it by more TLC's (Channels)

 

--- edit: i dont get 32 - 1 gets lost because chaining them ;)

Link to post
Share on other sites
The idea with the LED's is nice - but with one digital output ... one of both must be on

--- edit: i dont get 32 - 1 gets lost because chaining them ;)

 

Hmm, TI's app note and evaluation module still lets you get 16 outputs on each chip even when chaining. Output 0 - 15 (16 total).

Link to post
Share on other sites
  • 2 weeks later...

Thanks for your reply ... after waiting 2 weeks i am holding my new TLC's in my hands ... i tested them a bit and finally got them running ... as you said 2*16 channels :)

 

but i have a little problem - the following code works fine with calibrated DCO @ 1 MHz, if i try to run it on approx. 15 MHz it wont work as expected ... i think the times between latches and/or bitbanging is too short...

 

#include 

#define GSCLK_PIN BIT7	// to TLC5940 pin 18
#define SIN_PIN BIT6	// to TLC5940 pin 26
#define SCLK_PIN BIT3	// to TLC5940 pin 25
#define BLANK_PIN BIT4	// to TLC5940 pin 23
#define XLAT_PIN BIT5	// to TLC5940 pin 24
#define LED1_PIN BIT0	// Launchpad LED1 (Red)

// Useful macros
#define setHigh(n) { P1OUT |= n; }
#define setLow(n) { P1OUT &= ~n; }
#define pulse(n) { setHigh(n); setLow(n); }

void main(void) {
WDTCTL = WDTPW + WDTHOLD;

//	BCSCTL1 = RSEL0 | RSEL1 | RSEL2 | RSEL3;
//	DCOCTL = DCO0 | DCO1;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

P1DIR |= LED1_PIN;
P1OUT |= LED1_PIN;

P1DIR |= GSCLK_PIN | SIN_PIN | SCLK_PIN | BLANK_PIN | XLAT_PIN;

// Init output pins
setLow(GSCLK_PIN);
setLow(SCLK_PIN);
setLow(XLAT_PIN);
setLow(BLANK_PIN);
setLow(SIN_PIN);

unsigned int z = 0;

while (1) {
	// blank TLC
	setHigh(BLANK_PIN);
	setLow(BLANK_PIN);


	// cycle through LEDs
	for (unsigned int j = 0; j < 32; j++) {
		// cycle through bits
		for (unsigned int i = 0; i < 12; i++) {
			if ((((j % 2) == 0) && (z < 50)) || (((j % 2) == 1) && (z > 50))) {
				setHigh(SIN_PIN);
			}
			else {
				setLow(SIN_PIN);
			}

			// next bit
			pulse(SCLK_PIN);

		}

		// next LED
		pulse(GSCLK_PIN);
	}

//		setHigh(BLANK_PIN);

	// latch
	pulse(XLAT_PIN);

	z++;
	if (z > 100) z = 0;

//		while (1) { }
}
}

 

... i solved it doing the following dirty trick:

#define setHigh(n) { for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; P1OUT |= n; for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; }
#define setLow(n) { for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; P1OUT &= ~n; for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; }
#define pulse(n) { for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; setHigh(n); for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; setLow(n); for (unsigned int nothing = 0; nothing < 16; nothing++) {/* do nothing */}; }

 

but it's still flickering a bit ... there should be a more professional way to solve this?

Link to post
Share on other sites

thanks for the tips... i reworked your code a bit so that it should be less complicated now - as far as i tested it it is working really fine now :)

 

heres the reworked code:

 

#include "msp430g2211.h"

#define SetLow(port, pin) { port &= ~pin; }
#define SetHigh(port, pin) { port |= pin; }
#define Pulse(port, pin) { SetHigh(port, pin); SetLow(port, pin); }

char dcdata[] = {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63};
unsigned int gsdata[] = {4095, 2048, 512, 128, 32, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned int count = 0;

void sendDC() {
unsigned int CntrA = 0;
unsigned int CntrB = 0;
unsigned int data = dcdata[0];

// push data
while ((CntrA < 16) && (CntrB < 7)) {
	if(CntrA < 16) {
		if(CntrB < 6) {
			if(data & 0x0+020) {
				// SIN
				SetHigh(P1OUT, BIT6);
			}
			else {
				// SIN
				SetLow(P1OUT, BIT6);
			}

			data <<= 1;
			CntrB++;

			// SCLK
			Pulse(P1OUT, BIT5);
		}
		else {
			CntrA++;

			if(CntrA < 16) {
				CntrB = 1;
				data = dcdata[CntrA];

				if(data & 0x0020) {
					// SIN
					SetHigh(P1OUT, BIT6);
				}
				else {
					// SIN
					SetLow(P1OUT, BIT6);
				}

				data <<= 1;

				// SCLK
				Pulse(P1OUT, BIT5);
			}

		}
	}
}

// XLAT
Pulse(P1OUT, BIT1);
// VPRG
SetLow(P1OUT, BIT7);
// BLANK
SetHigh(P1OUT, BIT3);
// XLAT
Pulse(P1OUT, BIT1);
}

void sendGS() {
unsigned int CntrA = 0;
unsigned int CntrB = 0;
unsigned int data = gsdata[0];

// BLANK
SetLow(P1OUT, BIT3);

// push data
while ((CntrA < 16) && (CntrB < 13)) {
	if(CntrA < 16) {
		if(CntrB < 12) {
			if(data & 0x0800) {
				// SIN
				SetHigh(P1OUT, BIT6);
			}
			else {
				// SIN
				SetLow(P1OUT, BIT6);
			}

			data <<= 1;
			CntrB++;

			// SCLK
			Pulse(P1OUT, BIT5);
			// GSCLK
			Pulse(P1OUT, BIT2);
		}
		else {
			CntrA++;

			if(CntrA < 16) {
				CntrB = 1;
				data = gsdata[CntrA];

				if(data & 0x0800) {
					// SIN
					SetHigh(P1OUT, BIT6);
				}
				else {
					// SIN
					SetLow(P1OUT, BIT6);
				}

				data <<= 1;

				// SCLK
				Pulse(P1OUT, BIT5);
				// GSCLK
				Pulse(P1OUT, BIT2);
			}
		}
	}
}

// BLANK
SetHigh(P1OUT, BIT3);
// XLAT
Pulse(P1OUT, BIT1);
}

void main(void) {
WDTCTL = WDTPW + WDTHOLD;

// ~15.25 MHz
BCSCTL1 = RSEL0 | RSEL1 | RSEL2 | RSEL3;
DCOCTL = DCO0 | DCO1;

// P1.1 XLAT, P1.5 SCLK, P1.3 BLANK, P1.4 DCPRG, P1.7 VPRG, P1.6 SIN, 1.2 GSCLK
P1DIR |= (BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7);
P1OUT &= ~(BIT1|BIT2|BIT4|BIT5|BIT6|BIT7);

// BLANK, DCPRG, VPRG
P1OUT |= (BIT3|BIT4|BIT7);

sendDC();

while (1) {
	count++;
	if ((count % 100) == 0) {
		// rotate
		unsigned int t = gsdata[0];
		for (unsigned int i = 0; i < 15; i++) {
			gsdata[i] = gsdata[i+1];
		}
		gsdata[15] = t;
	}
	sendGS();
}
}

 

there are still some lines that can be optimized a bit more

 

i also found the problem: i overwrote the DC-EEPROM by accident :oops:

Link to post
Share on other sites

i improved the code a little more so it supports daisychaining up to 21 TLC's (= 4096 / 192)

 

i found another interesting document: http://www.ti.com/lit/sw/slvc106/slvc106.pdf

 

seems like the implementation is not 100% equivalent to the specifications - but it works for now :lol:

 

#include 

/*
Config
*/

#define TLC5940_N 2

/*
Ports
*/

#define PORT_XLAT P1OUT
#define PIN_XLAT BIT1

#define PORT_GSCLK P1OUT
#define PIN_GSCLK BIT2

#define PORT_BLANK P1OUT
#define PIN_BLANK BIT3

#define PORT_DCPRG P1OUT
#define PIN_DCPRG BIT4

#define PORT_SCLK P1OUT
#define PIN_SCLK BIT5

#define PORT_SIN P1OUT
#define PIN_SIN BIT6

#define PORT_VPRG P1OUT
#define PIN_VPRG BIT7

/*
DO NOT EDIT BELOW
*/

#define TLC5940_O (TLC5940_N * 16)

/*
Macros
*/

#define setLow(port, pin) { port &= ~pin; }
#define setHigh(port, pin) { port |= pin; }
#define pulse(port, pin) { setHigh(port, pin); setLow(port, pin); }

/*
Vars
*/

const char dcdata[TLC5940_O] = {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63};
unsigned int gsdata[TLC5940_O] = {4095, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0, 4095, 0, 0, 4095, 0, 0, 4095, 0, 0, 4095, 0, 0, 4095, 0, 0, 4095, 0, 0};
unsigned int count = 0;

void sendDC() {
unsigned int CntrA = 0;
unsigned int CntrB = 0;
unsigned int data = dcdata[0];

// push data
while ((CntrA < TLC5940_O) && (CntrB < 7)) {
	if(CntrA < TLC5940_O) {
		if(CntrB < 6) {
			if(data & 0x0+020) {
				// SIN
				setHigh(PORT_SIN, PIN_SIN);
			}
			else {
				// SIN
				setLow(PORT_SIN, PIN_SIN);
			}

			data <<= 1;
			CntrB++;

			// SCLK
			pulse(PORT_SCLK, PIN_SCLK);
		}
		else {
			CntrA++;

			if(CntrA < TLC5940_O) {
				CntrB = 1;
				data = dcdata[CntrA];

				if(data & 0x0020) {
					// SIN
					setHigh(PORT_SIN, PIN_SIN);
				}
				else {
					// SIN
					setLow(PORT_SIN, PIN_SIN);
				}

				data <<= 1;

				// SCLK
				pulse(PORT_SCLK, PIN_SCLK);
			}

		}
	}
}

// XLAT
pulse(PORT_XLAT, PIN_XLAT);
// VPRG
setLow(PORT_VPRG, PIN_VPRG);
// BLANK
setHigh(PORT_BLANK, PIN_BLANK);
// XLAT
pulse(PORT_XLAT, PIN_XLAT);
}

void sendGS() {
unsigned int CntrA = 0;
unsigned int CntrB = 0;
unsigned int data = gsdata[0];

// BLANK
setLow(PORT_BLANK, PIN_BLANK);

// push data
while ((CntrA < TLC5940_O) && (CntrB < 13)) {
	if(CntrA < TLC5940_O) {
		if(CntrB < 12) {
			if(data & 0x0800) {
				// SIN
				setHigh(PORT_SIN, PIN_SIN);
			}
			else {
				// SIN
				setLow(PORT_SIN, PIN_SIN);
			}

			data <<= 1;
			CntrB++;

			// SCLK
			pulse(PORT_SCLK, PIN_SCLK);
			// GSCLK
			pulse(PORT_GSCLK, PIN_GSCLK);
		}
		else {
			CntrA++;

			if(CntrA < TLC5940_O) {
				CntrB = 1;
				data = gsdata[CntrA];

				if(data & 0x0800) {
					// SIN
					setHigh(PORT_SIN, PIN_SIN);
				}
				else {
					// SIN
					setLow(PORT_SIN, PIN_SIN);
				}

				data <<= 1;

				// SCLK
				pulse(PORT_SCLK, PIN_SCLK);
				// GSCLK
				pulse(PORT_GSCLK, PIN_GSCLK);
			}
		}
	}
}

// BLANK
setHigh(PORT_BLANK, PIN_BLANK);
// XLAT
pulse(PORT_XLAT, PIN_XLAT);
}

void main(void) {
WDTCTL = WDTPW + WDTHOLD;

// ~15.25 MHz
BCSCTL1 = RSEL0 | RSEL1 | RSEL2 | RSEL3;
DCOCTL = DCO0 | DCO1;

// P1.1 XLAT, P1.5 SCLK, P1.3 BLANK, P1.4 DCPRG, P1.7 VPRG, P1.6 SIN, 1.2 GSCLK
P1DIR |= (BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7);
P1OUT &= ~(BIT1|BIT2|BIT4|BIT5|BIT6|BIT7);

// BLANK, DCPRG, VPRG
P1OUT |= (BIT3|BIT4|BIT7);

sendDC();

while (1) {
	count++;
	if ((count % 500) == 0) {
		// rotate
		unsigned int t = gsdata[0];
		for (unsigned int i = 0; i < (TLC5940_O - 1); i++) {
			gsdata[i] = gsdata[i+1];
		}
		gsdata[TLC5940_O - 1] = t;
	}
	sendGS();
}
}

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...