Jump to content
Sign in to follow this  
L.R.A

TLC5940 - i just can't get it to work

Recommended Posts

EDIT: final answer, i'm stupid. Well turns out after 1, almost 2 entire days of going arround i found out the problem: 1 broken wire inside the insulation... yay

 

With this i can now make the final codding. But ill leave this here if anyone wants to see. I noticed a lack of post about TLC5940.

 

 

Hi guys, so i'm just being realy stupid or my chip is burnt.

 

So i'm trying a basic thing with the TLC5940. I connect the pins so it's in grayscale mode, connect SIN to VCC and then i do the suposed cycle of the PWM and CLK and then BLANK and XTAL.

But i just can't get the leds to turn on. 

 

I use PWM outputs for the CLK and GSCLK. I use a interrupt on the timer to count the rising edges of the both PWMS.

Just to test i have the CLK at 20Khz and after 192 ticks i disable the PWM

For the GSCLK i have it at 8Khz and after 4096 ticks i disable that PWM

 

When i have the 192 CLK ticks and 4096 GSCLK ticks i just do:

Turn on BLANK

Turn on XTAL

Turn off XTAL

Turn off BLANK

 

and reset the counters and enable back the PWMs

 

 

Can someone with more experience help me figuring out what i am doing rong?

The code is made in energia so that's why it has void setup and void loop

#include "inc/hw_ints.h"
#include "driverlib/interrupt.c"
#include "driverlib/sysctl.c"
#include "driverlib/Timer.c"
#include"inc/tm4c123gh6pm.h"


//Defines to help with digital output
#define XLAT GPIO_PORTF_BASE, GPIO_PIN_3
#define XLATon GPIO_PIN_3
#define XLAToff 0x04

#define BLANK GPIO_PORTF_BASE, GPIO_PIN_1
#define BLANKon GPIO_PIN_1
#define BLANKoff 0x01

//This are the CLK and GSCLK counters
uint32_t  contaPWM =0;
uint32_t  contaCLK =0;


void setup()
{
//Configures PF_1
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
// 
//Configures PF_3
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);
//
  PWMoutInit();
  CLKInit();
}

void loop()
{
  if( (contaPWM == 4096) && (contaCLK == 192) ){
    GPIOPinWrite(BLANK,BLANKon); //Turns on BLANK
    delay(1);
    GPIOPinWrite(XLAT,XLATon); //Turns on XTAL
    delay(1);
    GPIOPinWrite(XLAT,XLAToff); //Turns off XTAL
    delay(1);    
    GPIOPinWrite(BLANK,BLANKoff); //Turns off BLANK


//Reset counters and enables both timers for he PWM
    contaPWM=0;
    contaCLK=0;
    TimerEnable(TIMER1_BASE, TIMER_A);
    TimerEnable(TIMER0_BASE, TIMER_;
  }
}


//This fuction configures the PWM for the CLK
void CLKInit(){

  unsigned long ulPeriod, dutyCycle;
  ulPeriod = 4000; // 20 Khz
  dutyCycle = ulPeriod/2;

  // Configure PB4 as T1CCP0
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);    
  GPIOPinConfigure(GPIO_PB4_T1CCP0);              
  GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_4);  
  //

  // Configure timer
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);                        
  TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);   
  TimerLoadSet(TIMER1_BASE, TIMER_A, ulPeriod -1);                     
  TimerMatchSet(TIMER1_BASE, TIMER_A, dutyCycle); // PWM    

  //Configures Interrupt on the timer
  TimerIntRegister(TIMER1_BASE,TIMER_A,CLKint);
  TimerControlEvent(TIMER1_BASE,TIMER_A,TIMER_EVENT_POS_EDGE);
  TimerIntEnable(TIMER1_BASE,TIMER_CAPA_EVENT);

  //turn on pwm  
  TimerEnable(TIMER1_BASE, TIMER_A);
  //  


}

//This fuction configures PWM for GSCLK
void PWMoutInit(){

  unsigned long ulPeriod, dutyCycle;
  ulPeriod = 10000; // 8 Khz
  dutyCycle = ulPeriod/2; 

  // Configure PB7 as T0CCP1
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);    
  GPIOPinConfigure(GPIO_PB7_T0CCP1);              
  GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_7);  
  //

  // Configure timer
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);                        
  TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);   
  TimerLoadSet(TIMER0_BASE, TIMER_B, ulPeriod -1);                     
  TimerMatchSet(TIMER0_BASE, TIMER_B, dutyCycle); // PWM  

  //Configures Interrupt on the timer
  TimerIntRegister(TIMER0_BASE,TIMER_B,BLANKint);
  TimerControlEvent(TIMER0_BASE,TIMER_B,TIMER_EVENT_POS_EDGE);
  TimerIntEnable(TIMER0_BASE,TIMER_CAPB_EVENT);

  //turn on pwm
  TimerEnable(TIMER0_BASE, TIMER_;
  // 
}

//The interrupts for both timers 
void CLKint(){

  if(contaCLK < 192){
    contaCLK++;
  }
  else { 
    TimerDisable(TIMER1_BASE, TIMER_A);  //turns off PWM timer of CLK
  }

  TimerIntClear(TIMER1_BASE, TIMER_CAPA_EVENT);    // Clear TIMER_CAPA_EVENT immediately.  

}
void BLANKint(){

  if(contaPWM < 4096){
    contaPWM++;
  }
  else { 
    TimerDisable(TIMER0_BASE, TIMER_;    //turns off PWM timer of GSCLK
  }
  TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT);    // Clear TIMER_CAPB_EVENT immediately.
}




Share this post


Link to post
Share on other sites

Hi,

If you serch with Google for "TLC5940 arduino" you will find out several sources for libraries already made for this device. All you need to do is to write a small number of functions to adapt to specific TM4C peripherals.

Also could be already ported for Energia by someone else.

L

Share this post


Link to post
Share on other sites

Hi,

If you serch with Google for "TLC5940 arduino" you will find out several sources for libraries already made for this device. All you need to do is to write a small number of functions to adapt to specific TM4C peripherals.

Also could be already ported for Energia by someone else.

L

 

When i searched for TLC5940 on the forum i found notigh about it :/

I was just trying to get the basic features to work wich was not even working

Also i want to have more control over what i am doing with it

Share this post


Link to post
Share on other sites

HI,

I understand you - what I would do would to port some arduino libraries - here is what I got: http://code.google.com/p/tlc5940arduino/ but I did not checked it yet to see all the implications. 

L

 

I could try to help a bit since sometimes i have dead time (no access to an osciloscope or waiting for someone opinion)

I will see the library files, it will probably help me too

 

For now i have it fully working in digital.

With brightness control i'm having issues but i belive it's the way i change the SIN but i will only have access to a osciloscope monday. I'll try to enable the AHB bus in that port

Share this post


Link to post
Share on other sites

Hi,

Looking into your code, I am a little bit puzzled - do you use Tiva libraries or there are some (unknown to me) special functions - ref GPIOPinWrite - if this is from Tiva, then you should have three arguments - GPIOPinWrite(uint32_t ui32Port, uint8_t ui8Pins, uint8_t ui8Val) so your definition for XLATon and XLAToff are wrong being the same (should be as it is now for XLATon and 0 for XLAToff). If this is another function,which I don't know, then I apologize...

L

Share this post


Link to post
Share on other sites

@@Lyon The code is being gratuitously tricky: the "first argument" is a preprocessor token that expands to two arguments.

 

@L.R.A Don't do that sort of thing; it misleads the people who are trying to help you.

Share this post


Link to post
Share on other sites

@@Lyon The code is being gratuitously tricky: the "first argument" is a preprocessor token that expands to two arguments.

 

@L.R.A Don't do that sort of thing; it misleads the people who are trying to help you.

 

Sorry about that, i was just trying to write the code faster so added those 

 

Going to try to use less of those confusing defines

Share this post


Link to post
Share on other sites

Hi,

Oh, I see it now - but anyway I was complaining about XLAToff value, which is wrong.

And doing such shortcuts will stop the user to change several pins states in a single expression/time if on the same port.

L

Share this post


Link to post
Share on other sites

Hi,

Oh, I see it now - but anyway I was complaining about XLAToff value, which is wrong.

And doing such shortcuts will stop the user to change several pins states in a single expression/time if on the same port.

L

yes i am aware of that but i am so acostume to using arduino ou energia that i prefer that way, at least to start off with it.

After getting a proto-code working then i will try to improve it. Probably gona use the AHB and direct access for the Serial data

 

I alredy got i to work basic PWM in all the ports without dot correction. Just trying to get the code more readable and then ill post

Share this post


Link to post
Share on other sites

well, hello again.

I've been working on trying to get this working decent.

 

First i am using the new launchpad. The one with tm4c1294ncpdt. 

 

 

So i abandoned the idea of having 2 PWM, 1 for the GSCLK and 1 for the SCLK since this would mean having 2 interrupts that could have conflit with ne another.

Then i also set all the GPIO for SIN, XLAT and BLANK to the AHB bus and control them with direct register access

For greater speed i also only use a 256bit resolution for the PWM. This makes it 16x more fast. To me this is ok since i don't need tha much resolution. 

 

Problem i am having now, i can't seem to get it to work with a PWM over 400Khz-600Khz.

 

So here is the code, any ideas and sugestions would be great:

/*
This is for tm4c1294ncpdt to control a TLC5940 grayscale mode
In this version of the code:

I use only 1 timer (T2CCP0) for both SCLK and GSCLK
  There's just 1 PWM output (PA_4)
  1 interrupt for each rising edge of the PWM
  
The update of data to the TLC5940 is done by changing the variable "updating"
  The timer interrupt will react acordingly to that variable
  If you want to send data the interrupt will start the SOUT sequence after the resolution-194 number of edges
  
I use the AHB bus for the GPIO PE_1, PE_2 and PE_3 that are
  respectively SOUT, XLAT and BLANK
  And i control them with direct register access
  
The PWM i use only has 256 bits of resolution
  This makes it possible to have a faster refresh rate
   I didn't realy need much resolution
   You can change the "define resolution" to watever value betwen 194 and 4096


*/


#include "inc/hw_ints.h"
#include "driverlib/interrupt.c"
#include "driverlib/sysctl.c"
#include "driverlib/Timer.c"
#include"inc/tm4c1294ncpdt.h"

#define resolution 256

/*
 XLAT - PE_2
 BLANK - PE_3
 CLK -  PA_4 T2CCP0
 GSCLK - PA_4 T2CCP0
 SOUT -  PE_1
 
 */
void PWMInit(uint32_t freq);  //Configures output port for GSCLK PWM and corresponding timer
void PWMint();  //Interrupt function for GSCLK rising edge
void DectoBool();  //Converts a int to bool
void SetAllOFF();
void ChangeValue(int valor, int pos);  //Changes a port value
void send();  //Initiates CLK and updating of PWM values

bool DataPacket [16][12];
volatile byte updating = 1;
volatile uint32_t  contaPWM =0;
volatile uint32_t  contaCLK =0;

void setup()
{  

  //Serial.begin(115220);
  IntPrioritySet(INT_TIMER2A,0xC1);

  PWMInit(400000); //0,00512

  SetAllOFF();
  send();
  ChangeValue(resolution-1,1); 
  send();
}

void loop()
{

  for(int i=0; i <resolution; i+=1){
    ChangeValue(i,2);
    send();
     delay(10); 
  }
  for(int i=resolution-1; i >= 0; i-=1){
    ChangeValue(i,2);
    send();
    delay(10); 
  } 
  for(int i=0; i <resolution; i+=1){
    ChangeValue(i,3);
    send();
     delay(10); 
  }
  for(int i=resolution-1; i >= 0; i-=1){
    ChangeValue(i,3);
    send();
    delay(10); 
  } 
}

void PWMInit(uint32_t freq){

  //Configure port E1:
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
  SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOE);
  GPIOPinTypeGPIOOutput(GPIO_PORTE_AHB_BASE , GPIO_PIN_1); 
  GPIOPadConfigSet(GPIO_PORTE_AHB_BASE,  GPIO_PIN_1,  GPIO_STRENGTH_8MA,  GPIO_PIN_TYPE_STD);  

  //Configure port E2: 
  // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
  GPIOPadConfigSet(GPIO_PORTE_AHB_BASE,  GPIO_PIN_2,  GPIO_STRENGTH_8MA,  GPIO_PIN_TYPE_STD); 
  GPIOPinTypeGPIOOutput(GPIO_PORTE_AHB_BASE, GPIO_PIN_2); 
  //  

  //Configure port E3:
 // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
 // SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOE);
  GPIOPinTypeGPIOOutput(GPIO_PORTE_AHB_BASE , GPIO_PIN_3); 
  GPIOPadConfigSet(GPIO_PORTE_AHB_BASE,  GPIO_PIN_3,  GPIO_STRENGTH_8MA,  GPIO_PIN_TYPE_STD);  
  //


  unsigned long ulPeriod, dutyCycle;
  ulPeriod = 120000000/freq ;
  dutyCycle = ulPeriod/2; 

  // Configure PA4 as T2CCP0
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);    
  GPIOPinConfigure(GPIO_PA4_T2CCP0);              
  GPIOPinTypeTimer(GPIO_PORTA_BASE, GPIO_PIN_4);  
  //

  // Configure timer
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);                        
  TimerConfigure(TIMER2_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);   
  TimerLoadSet(TIMER2_BASE, TIMER_A, ulPeriod -1);                     
  TimerMatchSet(TIMER2_BASE, TIMER_A, dutyCycle); // PWM  

  //Configura Interrupt on the timer
  TimerIntRegister(TIMER2_BASE,TIMER_A,PWMint);
  TimerControlEvent(TIMER2_BASE,TIMER_A,TIMER_EVENT_POS_EDGE);
  TimerIntEnable(TIMER2_BASE,TIMER_CAPA_EVENT);

  //Turn on PWM
   TimerEnable(TIMER2_BASE, TIMER_A);
  // 
}

void PWMint(){
  if(updating !=2){
    if(contaPWM < resolution){
      contaPWM++;
    }
    else if(updating==1){
      TimerDisable(TIMER2_BASE, TIMER_A); 
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_3 << 2))) = GPIO_PIN_3;
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_3 << 2))) = 0;
      TimerEnable(TIMER2_BASE, TIMER_A); 
      contaPWM=0;
      updating=2;
    }
    else{
      TimerDisable(TIMER2_BASE, TIMER_A); 
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_3 << 2))) = GPIO_PIN_3;
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_3 << 2))) = 0;
      TimerEnable(TIMER2_BASE, TIMER_A); 
      contaPWM=0;
    }
  }
  else{
    int linha= (contaPWM-(resolution-194))/12;
    int coluna=  (contaPWM-(resolution-194)) - (12*((contaPWM-(resolution-194))/12));
    
    if(contaPWM < (resolution-193)){
      contaPWM++;
    }
    else if(contaPWM == (resolution-193)){
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_1 << 2))) = 0;
      contaPWM++;
    } 
    else if(contaPWM < resolution){
      if(DataPacket[linha][coluna]==1)
        HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_1 << 2))) = GPIO_PIN_1;
      else
        HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_1 << 2))) = 0;
      contaPWM++;
    } 
    else{
      //Turn off PWM, pulse XLAT while BLANK is off, Turn BLANK on and Turn back on the PWM
      TimerDisable(TIMER2_BASE, TIMER_A); 
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_3 << 2))) = GPIO_PIN_3;
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_2 << 2))) = GPIO_PIN_2;
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_2 << 2))) = 0;
      HWREG(GPIO_PORTE_AHB_BASE + ((GPIO_PIN_3 << 2))) = 0;
      TimerEnable(TIMER2_BASE, TIMER_A); 
      contaPWM=0;     
      updating=0;
    }

  }

  TimerIntClear(TIMER2_BASE, TIMER_CAPA_EVENT);    // Clear TIMER_CAPA_EVENT immediately.    

}

void DectoBool(int value, bool Bit[]){
  for(int i = 11; i >= 0; i--){
    Bit[i] = 0b1 & value;
    value = value >> 1;   
  }
}

void SetAllOFF(){
  //while(updating !=0);

  for(int i=0; i < 16; i++)
    DectoBool(0, DataPacket[i]);
}

void ChangeValue(int value, int pos){
  //while(updating !=0);
  if (pos > 15 || pos < 0) return;
  /*  if( (value!=0) && (value!=4095))
   if( (value >0) && (value <= 10) );
   value = (0b111 << (value-1));*/

  if(value > resolution) value = resolution;
  if(value < 0) value = 0;
  //  Serial.println(value);
  DectoBool(value, DataPacket[15-pos]);
  /*  for(int j=0; j <16; j++){
   for(int i=0; i < 12; i++){
   Serial.print(DataPacket[j][i]);
   }
   Serial.println();
   }
   Serial.println();*/
}

void send(){
  updating=1;
  while(updating !=0); 
}






Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×