UPDATE: 07/05/09: Just as i think i cracked it, this code is still not quite there yet! I completely neglected that the blank and latch pulses have to be in synch to the gray scale clock, or else the outputs get all messed up! which is what happens below. It works to test the LEDs, but Leds can appear a lot dimmer then their actual set value because the GSCLK pulse gets truncated... -------- Finally had a breakthrough last night! After several nights of trying to piece together code from various places, I decided to try to run the TLC5940 on the atmega16 which I'm slightly more familiar with then my new 1281. I rewrote the registers for the atmega16 and stripped the code back as much as I thought I could. And it worked, so this is about as simple as I can imagine a test code for the TLC 5940 which I could not find an example of anywhere! Hopefully this might come in useful if anyone else is struggling with the same problem.
#include <avr/io.h>
#include <avr/interrupt.h>
//no operation assembly instruction
#define nop() __asm__ __volatile__("nop")
//while loop to pause if data is still sending
#define spi_wait() while (!(SPSR & (1<<SPIF))) {}
//XLAT - PB4 SS
#define xlat_high() PORTB |= (1 << PB4)
#define xlat_low() PORTB &= ~(1 << PB4)
//BLANK - PB2
#define blank_high() PORTB |= (1 << PB2)
#define blank_low() PORTB &= ~(1 << PB2)
//GSCLK - PB3 OC0
#define gsclk_high() PORTB |= (1 << PB3)
#define gsclk_low() PORTB &= ~(1 << PB3)
//SCLK - PB7 SCK
//SIN - PB5 MOSI
//this is an array of 12bits high, 12 bits low, a "test pattern"
int send[32] = {0xFF,0xF0,0x00,0xFF,0xF0,0x00,
0xFF,0xF0,0x00,0xFF,0xF0,0x00,0xFF,0xF0,0x00,
0xFF,0xF0,0x00,0xFF,0xF0,0x00,0xFF,0xF0,0x00,
0xFF,0xF0,0xFF,0xF0,0x00,0xFF,0xF0,0x00,};
void init (void);
int main(void)
{
init();
while (1)
{
// wait for any pending SPI data to finish transferring
spi_wait();
TCCR1B = 0; // stop the grayscale clock
gsclk_low();
TCCR1B |= (1 << CS10); // restart the grayscale clock
blank_high();//display off
xlat_low(); //dump old data
xlat_high(); //read shift register data into Grayscale reg
xlat_low(); //latch data
blank_low(); //display on
for(int i=0;i<24;i++) //send the next data
{
/*
SPDR = 0xFF //this was the 1st test, but it jsut gives LEDS lit
because the 5940 needs data in 12 bit chunks per LED, so i came up
with the idea to make an array of 12bits high 12bits low as a test.
*/
SPDR = (send[i]); //make this [i+1} to see the other LEDs light up.
//you could automate this without too much trouble,
// but this works very well as it is.
}
nop();
nop();
}
}
void init (void) //initialise ports
{
DDRB = 0xFF; //set port output
nop();
PORTB = 0x00; //ports initialize low
nop();
SPCR = (1 << SPE) | (1 << MSTR); //enable SPI master mode
SPSR |= (0 << SPI2X); //enable double speed SPI
SPDR = 0;
spi_wait();
sei(); //enable global interrupt
nop();
//timer0 generates grayscale clock on OC0 (PB3)
TCCR0 = 0;
TIMSK = 0;
TCNT0 = 0;
TCCR0 = (1 << COM00) | (1 << WGM01); //toggle OC0 on compare match
OCR0 = 7; // 14M by 7 = 2M
TCCR0 |= (1 << CS00); //no prescale
} |