Robofun 機器人論壇
標題:
arduino due 如何控制 TLC5940
[打印本頁]
作者:
zasdfeer13
時間:
2016-11-2 17:57
標題:
arduino due 如何控制 TLC5940
我最近有在使用TLC5940這顆IC
可是我GOOGLE都是使用UNO或是MAGE2560去控制的
有沒有大神可以教教我,如何用DUE的SPI去控制TLC5940操控LED燈
我對這顆IC也還不是很熟,最讓我困擾的是他的GSCLK的控制的部分,有使用過TLC5940的大神可以教教我嗎
或是參考個CODE
作者:
超新手
時間:
2016-11-3 07:03
奇怪?我在 google 中打入
arduino due tlc5940
就可以找到library了
library 中就有範例
一般來說,直接使用 library 即可
並不需要知道細部控制方法
作者:
zasdfeer13
時間:
2016-11-5 17:30
本帖最後由 zasdfeer13 於 2016-11-6 16:54 編輯
我之前有使用過他的library,但是我是打算使用48顆TLC5940串接去控制256顆RGB LED ,
他的library串接到第4顆之後就會有clock不足的問題,
不知道是不是我使用的問題,我是希望可以透過SPI去提高傳送的速度
但是這顆TLC5940最重要的GSCLK的控制,我還是一直搞不懂,下面是我的Code,
參考外國的一個
http://www.kevindarrah.com/downl ... imersCountersV6.ino
的Code去改的
但是它是透過UNO去控制,主要的Timer還有中斷的部分我沒有辦法理解,我只能照我理解的部分改成DUE能使用的,目前串到第5顆TLC的時候就會產生不對的閃爍,希望可以能找到完整的GSCLK的寫法。
我們是透過串接48顆TLC5940跟2顆74595去控制16*16*16的LED立方體。
下面是我目前的Code
#include <SPI.h>//Serial Peripheral Interface Library
//****************************************************************************************************
//****************************************************************************************************
byte ch=0, chbit=0, spibit=0, spibyte=0;// variables used by tlc sub routine
int SINData;//variable used to shift data to the TLC
byte transferbyte[1152];// bytes that are sent out to the tlc5940 via SPI
// 48 because 16 channels @ 12bits gives 384bits, 384/8 = 48 bytes, 12 bit to 8 bit conversion
int i, j, k, l=10,m,n,x=0; //misc variables
int green, oldgreen= 2048;//for random animation
int red, oldred = 2048;//for random animation
int blue, oldblue = 2048;//for random animation
int comeback=0, pick_color=0;//for random animation
bool ledOn = false;
//************************************************************************************************** 開空間
byte low_numberToDisplay[9] = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 };
byte high_numberToDisplay[9] = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 };
//*************************************************************************************************
//************************************************************************************************* 74595
byte channelR,channelG,channelB;
char LEDZ=0;
//*************************************************************************************************
//****************************************************************************************************
#define XLAT (1<<25) //TLC 24 due2
#define GSCLK (1<<28) //TLC 18 due 3
#define SIN (1<<26) //TLC 26 due75
#define SCLK (1<<27) //TLC 25 due76
#define BLANK (1<<25) //TLC 23 due5
//****************************************************************************************************
//****************************************************************************************************
void setup(){// MAIN SETUP MAIN SETUP MAIN SETUP MAIN SETUP MAIN SETUP
REG_PIOB_OWER = XLAT; REG_PIOB_OER = XLAT;
REG_PIOA_OWER = SIN; REG_PIOA_OER = SIN;
REG_PIOA_OWER = SCLK; REG_PIOA_OER = SCLK;
REG_PIOC_OWER = GSCLK; REG_PIOC_OER = GSCLK;
REG_PIOC_OWER = (1<<22); REG_PIOC_OER = (1<<22);//74595 latch
REG_PIOD_OWER = (1<<8); REG_PIOD_OER = (1<<8);//74595clk
REG_PIOD_OWER = (1<<7); REG_PIOD_OER = (1<<7);//74595data
//Set up the SPI
SPI.setBitOrder(MSBFIRST);//Most Significant Bit First
SPI.setDataMode(SPI_MODE0);// Mode 0 Rising edge of data, keep clock low
SPI.setClockDivider(3);//Run the data in at 84MHZ
for(i=0; i<1152; i++)//clear out Gray Scale Data
transferbyte[i]=0;
for(i=0; i<768; i++)//wipe out the data in tlc
tlc(i, 0);// This is how you update the LEDs, tlc is a subroutine with two inputs
// tlc(Channel, Value) Channel in this case is 0-32 and value is 0-4095 duty cycle
//4095 is 100% ON
REG_PIOC_OWER = BLANK; REG_PIOC_OER = BLANK;//BLANK We set this pin up here, so it remains in a high impedance
// state throughout the setup, otherwise the LEDs go crazy! even if you write this HIGH
}// END OF SETUP END OF SETUP END OF SETUP END OF SETUP END OF SETUP END OF SETUP END OF SETUP
//****************************************************************************************************
//****************************************************************************************************
void loop(){// MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP
VccControl();
for(i=0;i<96;i++)
{
tlc(i,k);
}
ID();
/*k=k+l;
if (k <= 0 || k >= 4090) {
l = -l ;
}*/
}// loop close loop close loop close loop close
//****************************************************************************************************
//****************************************************************************************************
// INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS
// INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS INTERRUPTS
//****************************************************************************************************
//****************************************************************************************************
void ID(){
SPI.begin();// start the SPI back up
for(SINData=1151; SINData>=0; SINData--)// send the data out!
SPI.transfer(transferbyte[SINData]);// The SPI port only understands bytes-8 bits wide
SPI.end();//end the SPI so we can write to the clock pin
REG_PIOB_SODR = 0x1 << 25;// write XLAT HIGH to latch in data from the last data stream
REG_PIOC_CODR = 0x1 << 25;// write blank LOW to start the next cycle
for(i=0;i<4096;i++){
REG_PIOC_SODR = 0x1 << 28;
REG_PIOC_CODR = 0x1 << 28;
}
REG_PIOC_SODR = 0x1 << 25;//Blank goes HIGH to reset the 4096 counter in the TLC
REG_PIOB_CODR = 0x1 << 25;//XLAT can go low now
}
//****************************************************************************************************
void tlc(int channel, int value){// TLC to UPDATE TLC to UPDATE TLC to UPDATE TLC to UPDATE
// This routine needs to happen as fast as possible!!!
//delayMicroseconds(10);//to control speed if necessary
//Limit check
if(value>4095)
value=4095;
if(value<0)
value=0;
// We need to convert the 12 bit value into an 8 bit BYTE, the SPI can't write 12bits
//We figure out where in all of the bytes to write to, so we don't have to waste time
// updating everything
//12 bits into bytes, a start of 12 bits will either at 0 or 4 in a byte
spibit=0;
if(bitRead(channel, 0))//if the read of the value is ODD, the start is at a 4
spibit=4;
//This is a simplification of channel * 12 bits / 8 bits
spibyte = int(channel*3/2);//this assignes which byte the 12 bit value starts in
for(chbit=0; chbit<12; chbit++, spibit++) // start right at where the update will go
{
if(spibit==8)//during the 12 bit cycle, the limit of byte will be reached
{
spibyte++;//roll into the next byte
spibit=0;//reset the bit count in the byte
}
if(bitRead(value, chbit)) //check the value for 1's and 0's
{
bitSet(transferbyte[spibyte], spibit);//transferbyte is what is written to the TLC
}
else
{
bitClear(transferbyte[spibyte], spibit);
}
}//0-12 bit loop
}// END OF TLC WRITE END OF TLC WRITE END OF TLC WRITE END OF TLC WRITE END OF TLC WRITE
//*******************************************************************************************
void VccControl(){
REG_PIOC_CODR = 0x1 << 22;//74595 LATCH LOW
switch(LEDZ)
{
case 0: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[1]);break;
case 1: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[2]);break;
case 2: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[3]);break;
case 3: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[4]);break;
case 4: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[5]);break;
case 5: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[6]);break;
case 6: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[7]);break;
case 7: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[8]);break;
case 8: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[1]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 9: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[2]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 10: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[3]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 11: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[4]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 12: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[5]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 13: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[6]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 14: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[7]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
case 15: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[8]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
}
REG_PIOC_SODR = 0x1 << 22;//74595 LATCH HIGH
LEDZ++;
if(LEDZ==16)
{
LEDZ=0;
}
}
複製代碼
作者:
zasdfeer13
時間:
2016-11-6 16:08
本帖最後由 zasdfeer13 於 2016-11-6 16:09 編輯
昨天我又將我的code針對TLC5940的datasheet做了微調。
123.jpg
(95.68 KB, 下載次數: 378)
下載附件
2016-11-6 15:57 上傳
SPI.begin();// start the SPI back up
for(SINData=1151; SINData>=0; SINData--)// send the data out!
SPI.transfer(transferbyte[SINData]);// The SPI port only understands bytes-8 bits wide
SPI.end();//end the SPI so we can write to the clock pin
REG_PIOB_SODR = 0x1 << 25;// write XLAT HIGH to latch in data from the last data stream
REG_PIOC_CODR = 0x1 << 25;// write blank LOW to start the next cycle
for(i=0;i<4096;i++){
REG_PIOC_SODR = 0x1 << 28;
REG_PIOC_CODR = 0x1 << 28;
}
REG_PIOC_SODR = 0x1 << 25;//Blank goes HIGH to reset the 4096 counter in the TLC
REG_PIOB_CODR = 0x1 << 25;//XLAT can go low now
複製代碼
先將資料透過SPI由SIN輸入通道,然後將XLAT給HIGH去鎖定通道的資料
將BLANK給LOW去重置GSCLK,再給4096的GSCLK,
將BLANK給HIGH送出資料
目前這樣可以串連6顆TLC5940沒有問題,但是串第7顆時出現閃爍的情況,不知道我的理解有沒有錯誤,或是有更簡易的寫法去控制
作者:
超新手
時間:
2016-11-6 16:42
for(SINData=1151; SINData>=0; SINData--)
為什麼是1151?
作者:
zasdfeer13
時間:
2016-11-6 16:50
本帖最後由 zasdfeer13 於 2016-11-6 16:53 編輯
回復
5#
超新手
因為要接48顆TLC5940,一顆TLC5940有16個通道,一個通道要12bit
16*12bit=192bit=24byte
24byte*48
=1152byte 所以我開了一個1152byte 的空間去儲存資料
這是根據以下的程式碼去做設定的
void tlc(int channel, int value){// TLC to UPDATE TLC to UPDATE TLC to UPDATE TLC to UPDATE
// This routine needs to happen as fast as possible!!!
//delayMicroseconds(10);//to control speed if necessary
//Limit check
if(value>4095)
value=4095;
if(value<0)
value=0;
// We need to convert the 12 bit value into an 8 bit BYTE, the SPI can't write 12bits
//We figure out where in all of the bytes to write to, so we don't have to waste time
// updating everything
//12 bits into bytes, a start of 12 bits will either at 0 or 4 in a byte
spibit=0;
if(bitRead(channel, 0))//if the read of the value is ODD, the start is at a 4
spibit=4;
//This is a simplification of channel * 12 bits / 8 bits
spibyte = int(channel*3/2);//this assignes which byte the 12 bit value starts in
for(chbit=0; chbit<12; chbit++, spibit++) // start right at where the update will go
{
if(spibit==8)//during the 12 bit cycle, the limit of byte will be reached
{
spibyte++;//roll into the next byte
spibit=0;//reset the bit count in the byte
}
if(bitRead(value, chbit)) //check the value for 1's and 0's
{
bitSet(transferbyte[spibyte], spibit);//transferbyte is what is written to the TLC
}
else
{
bitClear(transferbyte[spibyte], spibit);
}
}//0-12 bit loop
複製代碼
作者:
超新手
時間:
2016-11-7 10:33
本帖最後由 超新手 於 2016-11-8 08:08 編輯
那 spibyte 應該宣告成 int , 而不是 byte
歡迎光臨 Robofun 機器人論壇 (https://robofun.net/forum/)
Powered by Discuz! X3.2