Interfacing with 48 channel pwm driver lt8500

26 Apr 2012

Hey all, I am having a horrible time trying to interface with the LT8500 part.. it is a new chip that can do 48 channels of pwm right off the chip. datasheet: http://www.linear.com/product/LT8500 The trick is, that it wants a strange data set. It wants 48 12-bit data fields and an 8 bit command field. This means that I am changing spi modes from 12 to 8 to write a whole 584 bit stream.

I have verified with a scope that I can get the mbed to switch modes, it drops a 12 pulse spi clock then a 8 pulse command clock.

I can't get the part to actually do anything however. This is really grinding my gears. I am tempted to just bit bang the interface but that seems to be way more effort than needed.

I have a logic analyzer on order and I should be able to get crazy with it soon.

I have been able to verify that SOMETHING is being shifted out of the out pin, but it is not the right data.

Here is my code:

  1. include "mbed.h"

Ticker PWMCLK; DigitalOut myClock(p20); DigitalOut myled(LED1); DigitalOut led3(LED3); DigitalOut led2(LED2); SPI spi(p11, p12, p13); mosi, miso, sclk DigitalOut LDI(p16); Serial pc(USBTX, USBRX); tx, rx

const int spiFormat=0; const int spiFreq = 1000000;

void Pulse() { myClock=!myClock; led2=myClock; }

void send(){ LDI=0; LDI=1; wait_us(2); LDI=0;

}

void WriteValues(int value){ spi.format(12,spiFormat); spi.frequency(spiFreq); int p =0 ; for (int i = 0;i<48;i++) { p=spi.write(i*100); pc.printf("I just wrote this value: %d and read this one : %d \n",i*100, p); } }

int WriteCommand(int Command){ spi.format(8,spiFormat); spi.frequency(spiFreq); int spiread = 0; switch (Command) { case 1:output enable spiread = spi.write(0x30); case 2: correction frame spiread = spi.write(0x20); case 3: asychronus update frame spiread = spi.write(0x10); default: spiread = spi.write(0x00); defaults to sych update } send(); return spiread; }

int main() { LDI=1; wait(0.1); LDI=0; wait(0.1); myClock =1; PWMCLK.attach_us(&Pulse,5); WriteValues(89); WriteCommand(2); WriteValues(287); WriteCommand(3); WriteValues(4000); command = WriteCommand(1); /* spi.format(12,spiFormat); int command =0; spi.frequency(spiFreq); for (int i = 0;i<48;i++) { pc.printf("value No %d = %X\n", i,spi.write(368)); }

  • /

pc.printf("command = %X\n", command);

int counter=0; led3=1; while(1) { int readspi =0; if (counter >3000) counter = 0; else counter++; WriteValues(counter); if (counter==0) readspi = WriteCommand(1); else readspi = WriteCommand(3); myled=1; pc.printf("Derp = %X\n", readspi);

wait(0.2);

} }

26 Apr 2012

I think you make your live unnecessary complicated bij switching SPI modes (I was not aware that it was possible to have a other mode as 8bit SPI). In my opnion you should send a 73 byte (584 bit) data frame to the chip containing all necessary information in the correct place.

26 Apr 2012

Just a thought have you provided a clock source fro the PWM clock pin ??

26 Apr 2012

I agree with Marco, the part is clearly treating the buffer as a contiguous block of 584bits, so just send 73 bytes. It means doing some bitwise arithmetic to get your 12-bit PWM values, but trying to change the word length mid-stream is asking for trouble.

I may be reading it wrong, but I think you also have the wrong SPI mode. SDI needs to be stable during the LOW phase of the clock, and change during the HI phase - I believe Mode 2 is the right one (SPI confuses me sometimes so I might be wrong about that.)

Like Anthony, I'm also not seeing where you're feeding a clock into the LT8500 "PWMCK" (pin 39). Unless you've already got a hardware clock I would suggest using a 50% duty cycle PwmOut running at whatever frequency is needed.

Finally, the datasheet says you should drive LDIBLANK low, then wait for SDO to go low before sending the first frame. Easiest would be a busyloop checking that pin:

DigitalIn sdoPin(p11);
while (sdoPin) {};
27 Apr 2012

still no luck. I can't figure it out. maybe it is a msb/lsb issue? perhaps I should check SPI with my uchameleon. I am getting data shifted out.. just not sure if it is correct.

27 Apr 2012
  1. include "mbed.h"

Ticker PWMCLK; DigitalOut myClock(p20); DigitalOut myled(LED1); DigitalIn checkPin(p19); DigitalOut led3(LED3); DigitalOut led2(LED2); PwmOut twentyone(p21); SPI spi(p11, p12, p13); mosi, miso, sclk DigitalOut LDI(p16); Serial pc(USBTX, USBRX); tx, rx int numbits =0;

const int spiFormat=2; const int spiFreq = 100000;

void Pulse() { myClock=!myClock; led2=myClock; }

void send(){ LDI=0; wait_us(10); LDI=1; wait_us(2); LDI=0; wait_us(10);

}

void WriteValues(int value){

int p =0 ; for (int i = 0;i<72;i++) { numbits+=8; p=spi.write(100+i); pc.printf("I just wrote this value: %d and read this one : %d \n",i*100, p); } }

int WriteCommand(int Command){

int spiread = 0; switch (Command) { case 1:output enable spiread = spi.write(48); case 2: correction frame spiread = spi.write(32); case 3: asychronus update frame spiread = spi.write(16); case 4: selftest spiread = spi.write(0x50); default: spiread = spi.write(0); defaults to sych update }

send(); numbits +=8; pc.printf("I sent a total of %d bits\n",numbits); numbits=0; return spiread; }

int main() { LDI=1; twentyone.period_us(1); twentyone=0.5; wait(1);

spi.format(8,spiFormat); spi.frequency(spiFreq); LDI=0; while(checkPin){ pc.printf("I am checking da pin!\n"); }

pc.printf("found it!\n"); myClock =1; PWMCLK.attach_us(&Pulse,5); WriteValues(89); WriteCommand(2); WriteValues(287); WriteCommand(3); WriteValues(4000); int command; command = WriteCommand(1); /* spi.format(12,spiFormat); int command =0; spi.frequency(spiFreq); for (int i = 0;i<48;i++) { pc.printf("value No %d = %X\n", i,spi.write(368)); }

  • /

pc.printf("command = %X\n", command);

int counter=0; led3=1; while(1) { int readspi =0; if (counter >3000) counter = 0; else counter++; WriteValues(counter); if (counter==0){ readspi = WriteCommand(1); pc.printf("dude, wrote command 1\n"); } else readspi = WriteCommand(4); myled=1; pc.printf("Derp = %X\n", readspi);

wait(0.2);

} }

27 Apr 2012

NAILED IT!

After hooking up my scope proper-like

  1. include "mbed.h"

Ticker PWMCLK; DigitalOut myClock(p20); DigitalOut myled(LED1); DigitalIn checkPin(p19); DigitalOut led3(LED3); DigitalOut led2(LED2); PwmOut twentyone(p21); SPI spi(p11, p12, p13); mosi, miso, sclk DigitalOut LDI(p16); Serial pc(USBTX, USBRX); tx, rx int numbits =3;

const int spiFormat=0; const int spiFreq = 1000000;

void Pulse() { myClock=!myClock; led2=myClock; }

void send(){ LDI=0; wait_us(10); LDI=1; wait_us(2); LDI=0; wait_us(10);

}

void WriteValues(int value){

int p =0 ; for (int i = 0;i<72;i++) { numbits+=8; p=spi.write(value); pc.printf("I just wrote this value: %d and read this one : %d \n",i*100, p); } }

int WriteCommand(int Command){

int spiread = 0; switch (Command) { case 1:output enable spiread = spi.write(0x30); break; case 2: correction frame spiread = spi.write(0x20); break; case 3: asychronus update frame spiread = spi.write(0x10); break; case 4: selftest spiread = spi.write(0x50); break; default: spiread = spi.write(0); defaults to sych update break; }

send(); numbits +=8; pc.printf("I sent a total of %d bits\n",numbits); numbits=0; return spiread; }

int main() { LDI=1; twentyone.period_us(1); twentyone=0.5; wait(1);

spi.format(8,spiFormat); spi.frequency(spiFreq); LDI=0; while(checkPin){ pc.printf("I am checking da pin!\n"); }

pc.printf("found it!\n"); myClock =1; PWMCLK.attach_us(&Pulse,5); WriteValues(89); WriteCommand(2); WriteValues(287); WriteCommand(3); WriteValues(4000); int command; command = WriteCommand(1); /* spi.format(12,spiFormat); int command =0; spi.frequency(spiFreq); for (int i = 0;i<48;i++) { pc.printf("value No %d = %X\n", i,spi.write(368)); }

  • /

pc.printf("command = %X\n", command);

int counter=0; led3=1; while(1) { int readspi =0; if (counter >3000) counter = 0; else counter++; WriteValues(counter); if (counter==0){ readspi = WriteCommand(3); } else readspi = WriteCommand(3); myled=1; pc.printf("Derp = %X\n", readspi);

wait(0.2);

} }

27 Apr 2012

Michael Clive wrote:

NAILED IT!

Great, just a hint: use the <<code>> and <</code>> tags around your pasted sourcecode in this forum. Makes it much easier to read..

#include "mbed.h" 

Ticker PWMCLK;
DigitalOut myClock(p20);
DigitalOut myled(LED1);
DigitalIn checkPin(p19);
DigitalOut led3(LED3);
DigitalOut led2(LED2);
PwmOut twentyone(p21);
SPI spi(p11, p12, p13); //mosi, miso, sclk
DigitalOut LDI(p16);
Serial pc(USBTX, USBRX); //tx, rx int numbits =3;
 
const int spiFormat=0;
const int spiFreq = 1000000;
 
void Pulse() {
 myClock=!myClock;
 led2=myClock;
}
 
etc...
06 Apr 2018

Ticker PWMCLK; DigitalOut myClock(p20); DigitalOut myled(LED1); DigitalIn checkPin(p19); DigitalOut led3(LED3); DigitalOut led2(LED2); PwmOut twentyone(p21); SPI spi(p11, p12, p13); mosi, miso, sclk DigitalOut LDI(p16); Serial pc(USBTX, USBRX); tx, rx int numbits =3;

const int spiFormat=0; const int spiFreq = 1000000;

void Pulse() { myClock=!myClock; led2=myClock; }

void send(){ LDI=0; wait_us(10); LDI=1; wait_us(2); LDI=0; wait_us(10);

}

void WriteValues(int value){

int p =0 ; for (int i = 0;i<72;i++) { numbits+=8; p=spi.write(value); pc.printf("I just wrote this value: %d and read this one : %d \n",i*100, p); } }

int WriteCommand(int Command){

int spiread = 0; switch (Command) { case 1:output enable spiread = spi.write(0x30); break; case 2: correction frame spiread = spi.write(0x20); break; case 3: asychronus update frame spiread = spi.write(0x10); break; case 4: selftest spiread = spi.write(0x50); break; default: spiread = spi.write(0); defaults to sych update break; }

send(); numbits +=8; pc.printf("I sent a total of %d bits\n",numbits); numbits=0; return spiread; }

int main() { LDI=1; twentyone.period_us(1); twentyone=0.5; wait(1);

spi.format(8,spiFormat); spi.frequency(spiFreq); LDI=0; while(checkPin){ pc.printf("I am checking da pin!\n"); }

pc.printf("found it!\n"); myClock =1; PWMCLK.attach_us(&Pulse,5); WriteValues(89); WriteCommand(2); WriteValues(287); WriteCommand(3); WriteValues(4000); int command; command = WriteCommand(1); /* spi.format(12,spiFormat); int command =0; spi.frequency(spiFreq); for (int i = 0;i<48;i++) { pc.printf("value No %d = %X\n", i,spi.write(368)); }

/
pc.printf("command = %X\n", command);

int counter=0; led3=1; while(1) { int readspi =0; if (counter >3000) counter = 0; else counter++; WriteValues(counter); if (counter==0){ readspi = WriteCommand(3); } else readspi = WriteCommand(3); myled=1; pc.printf("Derp = %X\n", readspi);

wait(0.2);

} }

I wanted to see the formatted code.