|
|
View previous topic :: View next topic |
Author |
Message |
horizontechno
Joined: 07 Oct 2011 Posts: 8
|
WS2811 RGB lamp IC in High speed mode |
Posted: Sun Feb 17, 2013 8:22 pm |
|
|
Hello
I try to control led 50x50 RGB with WS2811 IC inside
with PIC 18F26K22 in 64mhz.
My code working, but got some random flickering !!
I need help to make more faster code to send data to the lamp.
This is my SPI setup:
Code: | setup_spi2( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16 ); |
and my code to send SPI 12Bit to the lamp
Code: |
void xneth(){
int a1;
int a2;
int a3;
int a4;
int16 nq;
int buf;
for(nq=0;nq<512;nq++){
buf=DMX[nq];
a1=0b10001000;
if (bit_test(buf,7)) {
bit_set(a1,5);
bit_set(a1,6);
}
if (bit_test(buf,6)) {
bit_set(a1,1);
bit_set(a1,2);
}
spi_write2(a1); // 10
a2=0b10001000;
if (bit_test(buf,5)) {
bit_set(a2,5);
bit_set(a2,6);
}
if (bit_test(buf,4)) {
bit_set(a2,1);
bit_set(a2,2);
}
spi_write2(a2); // 10
a3=0b10001000;
if (bit_test(buf,3)) {
bit_set(a3,5);
bit_set(a3,6);
}
if (bit_test(buf,2)) {
bit_set(a3,1);
bit_set(a3,2);
}
spi_write2(a3); // 10
a4=0b10001000;
if (bit_test(buf,1)) {
bit_set(a4,1);
bit_set(a4,2);
}
if (bit_test(buf,0)) {
bit_set(a4,5);
bit_set(a4,6);
}
spi_write2(a4); // 10
}
delay_us(50);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Feb 18, 2013 3:37 am |
|
|
Your indenting is foul.....
However, you can save a little time, by not using the CCS functions here. Preparing the next byte 'while' the first is sending. So:
Code: |
#byte ssp2buff=getenv("SFR:SSP2BUF")
#byte ssp2stat=getenv("SFR:SSP2STAT")
#bit ssp2_has_data=ssp2stat.1
#define SPI2_PUT(x) spi2_buff=x
//clear the sspbuffer
void ssp2_clear_buff(void) {
int8 dummy;
dummy=ssp2buff;
}
//wait for SSP to complete a transfer
void wait_for_ssp2(void) {
while(!ssp2_has_data);
ssp2_clear_buff; //you must clear the buffer or overflow will trigger
}
void xneth(void) {
int a1; //why use more than one variable?
int16 nq;
int buf;
for(nq=0;nq<512;nq++){
buf=DMX[nq];
//combine loading the value with the first test.
if (bit_test(buf,7))
a1=0b11101000;
else
a1=0b10001000;
if (bit_test(buf,6)) {
bit_set(a1,1);
bit_set(a1,2);
}
wait_for_ssp2();
SPI2_PUT(a1); // 10 Now the byte is being sent, get the next ready
if (bit_test(buf,5))
a1=0b11101000;
else
a1=0b10001000;
if (bit_test(buf,4)) {
bit_set(a1,1);
bit_set(a1,2);
}
wait_for_ssp2(); //wait for the last transmission to complete
SPI2_PUT(a1); // 10
//etc..
|
What this does that is different, is just loading the hardware buffer, and then _while the SPI is sending_, gets the next value ready. Instead of waiting for the transmission to complete before proceeding. Obviously it then must wait for the transmission to complete before loading this to send.
It saves a few uSec as well, by combining the first test and loading the value to send. Saves a few bytes of RAM by just using one variable. This requires the ssp to already be setup, and enabled. You may need to set the SSPEN bit yourself. Doing this will get rid of the delays between the bytes, tightening the timings.
If I remember correctly, these chips don't use SPI as such, but a continuous clock 'stream', with varying pulse widths for 1/0. so what you are doing is generating this by using multiple bits in the SPI (Fairly sure I suggested this some time ago to another poster asking about driving something similar....). Now the stream rate is meant to be 400KHz (optionally 800kHz). You are using each half of the SPI byte, as one clock. So four SPI bits=one cycle for the LED. Now with your clock selection, 64MHz/4/16 per SPI bit. So your SPI is clocking at 1MHz. This then gives you effectively 250KHz to the chip. Not the right rate. You need to switch to using the Timer2 option to control the SPI. Up the SPI rate to 1.6MHz (SPI_CLK_T2 & setup_timer_2(T2_DIV_BY_1,9,16);). Then you will be clocking the units at the right speed. Or use setup_timer_2(T2_DIV_BY_1,5,16) which will run the unit in high speed mode (800KHz clock rate).
Best Wishes |
|
|
horizontechno
Joined: 07 Oct 2011 Posts: 8
|
More help |
Posted: Mon Feb 18, 2013 8:10 pm |
|
|
Hello Ttelmah
Thank you for your fast reply !!
I have try to change the SPI setup to Timer 2 as your email
Code: | setup_timer_2(T2_DIV_BY_1,5,16); // for 800khz |
but with this setup i got .9us bit rate ? for the 800Khz i need .250us bit rate ?
Can you help me to get the right value for the 800Khz ?
Thanks for your time
Alain |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue Feb 19, 2013 1:45 am |
|
|
For 800KHz, you want an SPI bit time of:
(1/800000)/4 = 0.3125uSec
This then gives a 'simulated' bit time of 0.3125*4 = 1.25uSec. Using four SPI bits for each of the simulated bits.
So your SPI clock needs to be 3.2MHz.
I'd forgotten on these chips, the Timer2 output is divided by two (on some of the 16bit PIC's it isn't). So currently you'd be getting:
64E6/4/6/2 = 1.3MHz, and a bit time of 0.75uSec (not 0.9.....).
You won't quite be able to get the right rate. Nearest would be using 1 or two on the divider, giving /2 or /3 of the peripheral clock, and 2.6MHz, or 4MHz. Using 4MHz, would give 1MHz simulated clock, while 2.6MHz would give 650K.
Unfortunately, from your current master clock, the 'right rate', is not quite doable. Go to 51.2MHz master clock, and it can be done, using the standard divisor, or the timer2 route.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|