RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
Soft-PWM with SPI, interrupt driven; thoughts? |
Posted: Mon Jan 23, 2012 8:22 pm |
|
|
Background:
I want to do some software PWM to drive a power LED (Cree XM-L), using SPI to enable/disable certain pins on a TI TLC5917 - it's basically 8x constant-current sinks, and by writing a byte via SPI you can specify which pins to turn on/off. It can be enabled/disabled as a whole via tying the OE pin to ground/releasing it, but seems like this could cause issues by accidentally making it go into various other modes instead.
I'm currently using a PWM module to produce sound, running at about 30kHz, way too fast for my needs for the LED. The sound duty is being set on a timer interrupt, running at 16kHz, so my thinking is I could make a software PWM utilising this interrupt, if a duty of 0 - 100, should give 160Hz PWM, which is more like the figure I'm after. System is a semi machine-state thing, interrupt just increments where the cycle is up to, actual actions are implemented in the Main if they are required.
Enabling/disabling the TLC5917 sinks involves writing the byte via SPI, then toggling a "latch enable" line high-low. By changing the byte, any number of sinks can be enabled, allowing for a wide range of current profiles. By ganging together say 3x TLC5917s, and setting them for 120mA sinking, you could sink anywhere from 0mA to almost 3A, and each SPI byte pushes the previous byte onto the next chip in the line.
OK, background hopefully set, now onto the question; does the following pseudo-code make sense, and is it feasible? Any tweaking of the conditions to make it more efficient? Am I missing anything blatantly obvious?
VARIABLES / DEFINES
Code: | #define LED_LE PIN_whatever; //Latch-Enable pin
int ledOnLevel = 11111111; //byte for all current-sinks enabled - full power, can edit to change maximum current available
int ledDuty = 60; //0-100 duty, to be variable at a later date
int ledINTCount = 0; //count interrupts, 100 interrupts per cycle
int1 ledWritten = false; //boolean to stop wasteful multiple spi_writes - write once to enable, once to disable
int ledChips = 1; //how many TLC5917s, can be multiple in parallel
int ledChipCount = 0; //for cycling through chips
int i=0; //generic, for "for" loops etc |
INTERRUPT - 16kHz
Code: | if(ledINTCount < 99)
ledIntCount++; //increment
else
ledINTCount = 0; //reset |
VOID MAIN
Code: | if(ledDuty < ledINTCount) //duty period
{
if(!ledWritten)
for(ledChipCount=0; ledChipCount<ledChips; ledChipCount++)
spi_write(ledOnLevel); //set desired pins to Enabled, for all chips
ledWritten = true;
output_high(LED_LE); //toggle Latch_Enable to write data to current sinks
delay_us(10); //I never like to use delays; any options here?
output_low(LED_LE);
}
else if(ledWritten)
for(ledChipCount=0; ledChipCount<ledChips; ledChipCount++)
spi_write(0); //set all pins to Disabled, for all chips
ledWritten = true;
output_high(LED_LE);
delay_us(10); //I never like to use delays; any options here?
output_low(LED_LE); |
|
|