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
  1. #include <SPI.h>//Serial Peripheral Interface Library
  2. //****************************************************************************************************

  3. //****************************************************************************************************
  4.   byte ch=0, chbit=0, spibit=0, spibyte=0;// variables used by tlc sub routine
  5.   int SINData;//variable used to shift data to the TLC
  6.   byte transferbyte[1152];// bytes that are sent out to the tlc5940 via SPI
  7.   // 48 because 16 channels @ 12bits gives 384bits, 384/8 = 48 bytes, 12 bit to 8 bit conversion
  8.   int i, j, k, l=10,m,n,x=0; //misc variables
  9.   int green, oldgreen= 2048;//for random animation
  10.   int red, oldred = 2048;//for random animation
  11.   int blue, oldblue = 2048;//for random animation
  12.   int comeback=0, pick_color=0;//for random animation
  13.   bool ledOn = false;
  14. //************************************************************************************************** 開空間
  15.   byte low_numberToDisplay[9]  = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 };

  16.   byte  high_numberToDisplay[9] = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 };
  17. //*************************************************************************************************
  18. //************************************************************************************************* 74595
  19.   byte channelR,channelG,channelB;
  20.   char LEDZ=0;
  21. //*************************************************************************************************

  22.   //****************************************************************************************************
  23.   #define XLAT (1<<25) //TLC 24  due2
  24.   #define GSCLK (1<<28) //TLC 18 due 3
  25.   #define SIN (1<<26)  //TLC 26  due75
  26.   #define SCLK (1<<27) //TLC 25 due76
  27.   #define BLANK (1<<25) //TLC 23  due5

  28.   //****************************************************************************************************

  29.   //****************************************************************************************************
  30. void setup(){//   MAIN SETUP   MAIN SETUP   MAIN SETUP   MAIN SETUP   MAIN SETUP
  31.   REG_PIOB_OWER = XLAT; REG_PIOB_OER = XLAT;     
  32.   REG_PIOA_OWER = SIN; REG_PIOA_OER = SIN;   
  33.   REG_PIOA_OWER = SCLK; REG_PIOA_OER = SCLK;
  34.   REG_PIOC_OWER = GSCLK; REG_PIOC_OER = GSCLK;

  35.   REG_PIOC_OWER = (1<<22); REG_PIOC_OER = (1<<22);//74595 latch
  36.   REG_PIOD_OWER = (1<<8); REG_PIOD_OER = (1<<8);//74595clk
  37.   REG_PIOD_OWER = (1<<7); REG_PIOD_OER = (1<<7);//74595data
  38.   
  39.   //Set up the SPI
  40.   SPI.setBitOrder(MSBFIRST);//Most Significant Bit First
  41.   SPI.setDataMode(SPI_MODE0);// Mode 0 Rising edge of data, keep clock low
  42.   SPI.setClockDivider(3);//Run the data in at 84MHZ

  43.   
  44.   for(i=0; i<1152; i++)//clear out Gray Scale Data
  45.   transferbyte[i]=0;   
  46.   for(i=0; i<768; i++)//wipe out the data in tlc
  47.   tlc(i, 0);// This is how you update the LEDs, tlc is a subroutine with two inputs
  48.   // tlc(Channel, Value)  Channel in this case is 0-32 and value is 0-4095 duty cycle
  49.   //4095 is 100% ON
  50.   REG_PIOC_OWER = BLANK; REG_PIOC_OER = BLANK;//BLANK  We set this pin up here, so it remains in a high impedance
  51.   // state throughout the setup, otherwise the LEDs go crazy!  even if you write this HIGH



  52.    
  53. }// END OF SETUP END OF SETUP END OF SETUP END OF SETUP END OF SETUP END OF SETUP END OF SETUP
  54.   //****************************************************************************************************

  55.   //****************************************************************************************************
  56. void loop(){//   MAIN LOOP   MAIN LOOP   MAIN LOOP   MAIN LOOP   MAIN LOOP   MAIN LOOP


  57.     VccControl();

  58.    
  59.     for(i=0;i<96;i++)
  60.     {
  61.      tlc(i,k);
  62.     }
  63.     ID();
  64.    
  65.    
  66.     /*k=k+l;
  67.    if (k <= 0 || k >= 4090) {
  68.     l = -l ;
  69.   }*/
  70.   


  71.   


  72. }//      loop close      loop close      loop close      loop close
  73.   //****************************************************************************************************

  74.   //****************************************************************************************************
  75. // INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS  

  76. // INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS   INTERRUPTS  
  77.   //****************************************************************************************************

  78.   //****************************************************************************************************
  79. void ID(){
  80.   
  81.   SPI.begin();// start the SPI back up
  82.   for(SINData=1151; SINData>=0; SINData--)// send the data out!
  83.   SPI.transfer(transferbyte[SINData]);// The SPI port only understands bytes-8 bits wide
  84.   SPI.end();//end the SPI so we can write to the clock pin
  85. REG_PIOB_SODR = 0x1 << 25;// write XLAT HIGH to latch in data from the last data stream
  86. REG_PIOC_CODR = 0x1 << 25;// write blank LOW  to start the next cycle

  87. for(i=0;i<4096;i++){
  88.     REG_PIOC_SODR = 0x1 << 28;
  89.     REG_PIOC_CODR = 0x1 << 28;
  90.     }
  91. REG_PIOC_SODR = 0x1 << 25;//Blank goes HIGH to reset the 4096 counter in the TLC
  92. REG_PIOB_CODR = 0x1 << 25;//XLAT can go low now
  93.   
  94.   
  95. }
  96.   //****************************************************************************************************


  97. void tlc(int channel, int value){// TLC to UPDATE TLC to UPDATE TLC to UPDATE TLC to UPDATE
  98. // This routine needs to happen as fast as possible!!!
  99. //delayMicroseconds(10);//to control speed if necessary
  100. //Limit check
  101.   if(value>4095)
  102.   value=4095;
  103.   if(value<0)
  104.   value=0;
  105.   
  106.    // We need to convert the 12 bit value into an 8 bit BYTE, the SPI can't write 12bits
  107.    
  108.    //We figure out where in all of the bytes to write to, so we don't have to waste time
  109.    // updating everything
  110.    
  111.    //12 bits into bytes, a start of 12 bits will either at 0 or 4 in a byte
  112.     spibit=0;
  113.     if(bitRead(channel, 0))//if the read of the value is ODD, the start is at a 4
  114.     spibit=4;
  115.    
  116.     //This is a simplification of channel * 12 bits / 8 bits
  117.     spibyte = int(channel*3/2);//this assignes which byte the 12 bit value starts in
  118.   
  119.     for(chbit=0; chbit<12; chbit++, spibit++) // start right at where the update will go
  120.     {         
  121.         if(spibit==8)//during the 12 bit cycle, the limit of byte will be reached
  122.         {
  123.         spibyte++;//roll into the next byte
  124.         spibit=0;//reset the bit count in the byte
  125.         }
  126.   
  127.         
  128.         if(bitRead(value, chbit))         //check the value for 1's and 0's
  129.         {
  130.            bitSet(transferbyte[spibyte], spibit);//transferbyte is what is written to the TLC
  131.         }
  132.         else
  133.         {
  134.            bitClear(transferbyte[spibyte], spibit);
  135.         }
  136.     }//0-12 bit loop

  137.   
  138.   }//  END OF TLC WRITE  END OF TLC WRITE  END OF TLC WRITE  END OF TLC WRITE  END OF TLC WRITE
  139.   //*******************************************************************************************


  140. void VccControl(){
  141.   
  142. REG_PIOC_CODR = 0x1 << 22;//74595 LATCH LOW
  143.   switch(LEDZ)
  144.   {
  145.     case   0: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[1]);break;  
  146.     case   1: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[2]);break;                 
  147.     case   2: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[3]);break;  
  148.     case   3: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[4]);break;
  149.     case   4: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[5]);break;  
  150.     case   5: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[6]);break;
  151.     case   6: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[7]);break;  
  152.     case   7: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[0]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[8]);break;
  153.     case   8: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[1]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;  
  154.     case   9: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[2]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
  155.     case  10: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[3]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;  
  156.     case  11: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[4]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
  157.     case  12: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[5]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;  
  158.     case  13: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[6]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
  159.     case  14: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[7]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;  
  160.     case  15: shiftOut(11, 12, MSBFIRST, high_numberToDisplay[8]); shiftOut(11, 12, MSBFIRST, low_numberToDisplay[0]);break;
  161.   }
  162.   
  163.   REG_PIOC_SODR = 0x1 << 22;//74595 LATCH HIGH

  164.   LEDZ++;
  165.   if(LEDZ==16)
  166.   {
  167.     LEDZ=0;
  168.   }




  169. }

複製代碼

作者: zasdfeer13    時間: 2016-11-6 16:08
本帖最後由 zasdfeer13 於 2016-11-6 16:09 編輯

昨天我又將我的code針對TLC5940的datasheet做了微調。





  1.   SPI.begin();// start the SPI back up
  2.   for(SINData=1151; SINData>=0; SINData--)// send the data out!
  3.   SPI.transfer(transferbyte[SINData]);// The SPI port only understands bytes-8 bits wide
  4.   SPI.end();//end the SPI so we can write to the clock pin
  5. REG_PIOB_SODR = 0x1 << 25;// write XLAT HIGH to latch in data from the last data stream
  6. REG_PIOC_CODR = 0x1 << 25;// write blank LOW  to start the next cycle

  7. for(i=0;i<4096;i++){
  8.     REG_PIOC_SODR = 0x1 << 28;
  9.     REG_PIOC_CODR = 0x1 << 28;
  10.     }
  11. REG_PIOC_SODR = 0x1 << 25;//Blank goes HIGH to reset the 4096 counter in the TLC
  12. REG_PIOB_CODR = 0x1 << 25;//XLAT can go low now
  13.   
  14.   
複製代碼




先將資料透過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 的空間去儲存資料

這是根據以下的程式碼去做設定的


  1. void tlc(int channel, int value){// TLC to UPDATE TLC to UPDATE TLC to UPDATE TLC to UPDATE
  2. // This routine needs to happen as fast as possible!!!
  3. //delayMicroseconds(10);//to control speed if necessary
  4. //Limit check
  5.   if(value>4095)
  6.   value=4095;
  7.   if(value<0)
  8.   value=0;
  9.   
  10.    // We need to convert the 12 bit value into an 8 bit BYTE, the SPI can't write 12bits
  11.    
  12.    //We figure out where in all of the bytes to write to, so we don't have to waste time
  13.    // updating everything
  14.    
  15.    //12 bits into bytes, a start of 12 bits will either at 0 or 4 in a byte
  16.     spibit=0;
  17.     if(bitRead(channel, 0))//if the read of the value is ODD, the start is at a 4
  18.     spibit=4;
  19.    
  20.     //This is a simplification of channel * 12 bits / 8 bits
  21.     spibyte = int(channel*3/2);//this assignes which byte the 12 bit value starts in
  22.   
  23.     for(chbit=0; chbit<12; chbit++, spibit++) // start right at where the update will go
  24.     {         
  25.         if(spibit==8)//during the 12 bit cycle, the limit of byte will be reached
  26.         {
  27.         spibyte++;//roll into the next byte
  28.         spibit=0;//reset the bit count in the byte
  29.         }
  30.   
  31.         
  32.         if(bitRead(value, chbit))         //check the value for 1's and 0's
  33.         {
  34.            bitSet(transferbyte[spibyte], spibit);//transferbyte is what is written to the TLC
  35.         }
  36.         else
  37.         {
  38.            bitClear(transferbyte[spibyte], spibit);
  39.         }
  40.     }//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