RobG 1,892 Posted July 10, 2012 Share Posted July 10, 2012 That's a good point, I have had issues with male-female jumper wires that I got from eBay. Also, your LEDs are powered from another source, is the GND connected? I know it's silly but there were cases where people forgot to connect GNDs. Quote Link to post Share on other sites
pillum 0 Posted July 10, 2012 Author Share Posted July 10, 2012 Lol, well...I removed everything and connected everything from scratch the dunno maybe like 10th time and now it works.. This time I used Launchpad's Vcc for the LEDs, though. Trying with external power source now. Thanks all for your help, especially kylej1050, cde and RobG ! :clap: edit: Tried external power source, works too! Since I changed all wires and reconnected them from scratch, i think there was some fault in the wiring. edit2: strange, it works sometimes and sometimes not.... :eh: . now its not working anymore it blinks sometimes and sometimes its off and then on for a long time edit3: i think the led is broken..used a different led, its not blinking Quote Link to post Share on other sites
RobG 1,892 Posted July 10, 2012 Share Posted July 10, 2012 Sounds like a wire connection issue. You may want to use 3 male headers with soldered wires, that will eliminate flaky jumper wires. I do that all the time, saved me some headaches pillum 1 Quote Link to post Share on other sites
pillum 0 Posted July 11, 2012 Author Share Posted July 11, 2012 That sounds like a very good idea! Thank you :!: Quote Link to post Share on other sites
cde 334 Posted July 11, 2012 Share Posted July 11, 2012 Could also be a bad breadboard? The contacts in breadboards can lose their springyness and stop making contact properly. And double check that you connected the grounds between the launchpad and external power supplies. Quote Link to post Share on other sites
RobG 1,892 Posted July 11, 2012 Share Posted July 11, 2012 ...Your code keeps the processor very busy. I would recommend using a timer to output your clock signal while the MSP goes about other business... You could also output your SMCLK to one pin and use timer to count to 0xFFF and pulse BLANK on interrupt. P1DIR |= BIT4; // port 1.4 configured as SMCLK out P1SEL |= BIT4; Quote Link to post Share on other sites
pillum 0 Posted July 11, 2012 Author Share Posted July 11, 2012 Doesn't the clock signal need to be synchronized then? Because now I'm resetting the PWM counter after 4095 rounds of gsdata upload and not after 4095 cycles. Isn't the MSP430G2553 also able to use the USCI HW to control the TLC5940 via SPI? Also, how do I change the Grayscale data with an USB connection to my PC? Is there already a lib for serial connection like with arduino? Quote Link to post Share on other sites
RobG 1,892 Posted July 11, 2012 Share Posted July 11, 2012 No, GSCLK and SCLK are two independent clock signals and do not have to be synchronized. Use P1.4 (SCLK out) for GSCLK, set timer to upmode, 1:1 SMCLK, and CCR to 0xFFF. In timer's ISR, pulse BLANK, P1.3 for example. P1.0 -> XLAT P1.5 (USCI SCLK) -> SCLK P1.7 (SIMO) -> SIN P1.6 (SOMI) -> SOUT (optional) P1.1 UART RX P2.0 -> VPRG (optional) P2.1 -> DCPRG (optional) Use UCA0 in UART mode to receive data from PC, UCB0 in SPI mode to send data to TLC. pillum 1 Quote Link to post Share on other sites
pillum 0 Posted July 12, 2012 Author Share Posted July 12, 2012 No, GSCLK and SCLK are two independent clock signals and do not have to be synchronized.Use P1.4 (SCLK out) for GSCLK, set timer to upmode, 1:1 SMCLK, and CCR to 0xFFF. I should use SCLK pin for GSCLK? I'm not sure I understand what you want to do.. In timer's ISR, pulse BLANK, P1.3 for example. but XLAT isn't? Is pulsing BLANK really so resource intensive that you need an timer interrupt for it? In the flowchart they pulse GSCLK only after data transfer is complete, does this really not need to be synchronized or was this just arbitrary that they made it like this? Quote Link to post Share on other sites
RobG 1,892 Posted July 12, 2012 Share Posted July 12, 2012 Here is the implementation of what I was suggesting. Send byte through UART to light up the LED. Upper nibble controls LED #, lower nibble brightness (0-15) So, to set LED#1 to max, you send 0x1F, LED#16 to 50%, send 0xF7 LED#4 '0' = 0%, '7' = 50%, '?' = 100% LED#5 '@ = 0%, 'G' = 50%, 'O' = 100% LED#6 'P' = 0%, 'W' = 50%, '_' = 100% and so on. BTW, DCPRG and VPRG are grounded. #include #define RX_PIN BIT1 #define SCLK_PIN BIT5 #define MOSI_PIN BIT7 #define GSCLK_PIN BIT4 #define BLANK_PIN BIT0 #define XLAT_PIN BIT2 typedef unsigned char u_char; u_char leds[16] = { 0, }; void updateTLC(); void main(void) { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_16MHZ; // 16MHz clock DCOCTL = CALDCO_16MHZ; P1OUT &= ~(BLANK_PIN + XLAT_PIN); P1DIR |= BLANK_PIN + XLAT_PIN; P1DIR |= GSCLK_PIN; // port 1.4 configured as SMCLK out P1SEL |= GSCLK_PIN; // setup timer CCR0 = 0xFFF; TACTL = TASSEL_2 + MC_1 + ID_0; // SMCLK, up mode, 1:1 CCTL0 = CCIE; // CCR0 interrupt enabled // setup UCA0 P1SEL |= RX_PIN; P1SEL2 |= RX_PIN; UCA0CTL1 |= UCSSEL_2; UCA0BR0 = 0x82; // 9600@16MHz UCA0BR1 = 0x06; UCA0MCTL = UCBRS_6; UCA0CTL1 &= ~UCSWRST; IE2 |= UCA0RXIE; // setup UCB0 P1SEL |= SCLK_PIN + MOSI_PIN; P1SEL2 |= SCLK_PIN + MOSI_PIN; UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 0x01; // 1:1 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // clear SW updateTLC(); _bis_SR_register(GIE); } void updateTLC() { u_char ledCounter = 8; while (ledCounter-- > 0) { UCB0TXBUF = leds[(ledCounter << 1) + 1] << 4 ; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = leds[ledCounter << 1]; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = 0; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? } P1OUT |= XLAT_PIN; P1OUT &= ~XLAT_PIN; } #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR(void) { u_char byte = UCA0RXBUF; // copy RX buffer u_char led = byte >> 4; // upper 4 bits are LED # leds[led] = byte & 0x0F; // lower 4 bits are brightness 0-15 // update TLC updateTLC(); } #pragma vector = TIMER0_A0_VECTOR __interrupt void Timer_A0(void) { P1OUT |= BLANK_PIN; P1OUT &= ~BLANK_PIN; } pillum 1 Quote Link to post Share on other sites
RobG 1,892 Posted July 12, 2012 Share Posted July 12, 2012 No, GSCLK and SCLK are two independent clock signals and do not have to be synchronized.Use P1.4 (SCLK out) for GSCLK, set timer to upmode, 1:1 SMCLK, and CCR to 0xFFF. I should use SCLK pin for GSCLK? I'm not sure I understand what you want to do.. MSP430 SMCLK out -> TLC GSCLK MSP430 UCB0 SCLK -> TLC SCLK In timer's ISR, pulse BLANK, P1.3 for example. but XLAT isn't? Is pulsing BLANK really so resource intensive that you need an timer interrupt for it? GSCLK and BLANK are used for PWM. GSCLK clocks the PWM counter, BLANK turns LEDs off and sets PWM counter to 0. When PWM counter reaches 0xFFF, it stops. If you do not pulse BLANK at that time, LEDs will remain off. Pulsing BLANK will restart PWM count. Instead of pulsing GSCLK and keeping track in code, you use timer module. 4096 pulses would require 20k+ clock cycles per PWM cycle! This way, you need only ~20 of them (per PWM cycle.) In the flowchart they pulse GSCLK only after data transfer is complete, does this really not need to be synchronized or was this just arbitrary that they made it like this? XLAT is used for latching data. Since new data replaces old one when XLAT goes high, latching should happen when PWM counter is inactive (BLANK is 1.) You could move updateTLC() and XLAT to timer's ISR, but I think the effect of latching in the middle of PWM cycle is not significant. Doing it that way means new data will be sent to TLC every PWM cycle, where my original code sends data only when something changes. Something like this: #include #define RX_PIN pillum 1 Quote Link to post Share on other sites
pillum 0 Posted July 12, 2012 Author Share Posted July 12, 2012 Here is the implementation of what I was suggesting.Send byte through UART to light up the LED. Upper nibble controls LED #, lower nibble brightness (0-15) So, to set LED#1 to max, you send 0x1F, LED#16 to 50%, send 0xF7 LED#4 '0' = 0%, '7' = 50%, '?' = 100% LED#5 '@ = 0%, 'G' = 50%, 'O' = 100% LED#6 'P' = 0%, 'W' = 50%, '_' = 100% and so on. u_char ledCounter = 8; while (ledCounter-- > 0) { UCB0TXBUF = leds[(ledCounter << 1) + 1] << 4 ; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = leds[ledCounter << 1]; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = 0; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? } Now you're confusing me more. I thought this is serial and not random access. I update the grayscale data serially, that means one after another. But you're specify WHICH led to update. Where you got that from? You got any documentation on that? Also you're transmitting 3 bytes per LED (counting last '\0'), I only do 12bits. Quote Link to post Share on other sites
RobG 1,892 Posted July 12, 2012 Share Posted July 12, 2012 Now you're confusing me more. I thought this is serial and not random access.I update the grayscale data serially, that means one after another. But you're specify WHICH led to update. Where you got that from? You got any documentation on that? Also you're transmitting 3 bytes per LED (counting last '\0'), I only do 2 bytes. Brightness data for all LEDs is stored in leds[]. In this example, I am only using 4 bits for 16 levels of brightness. Sending one byte via UART updates data in leds[] for only one LED. updateTLC() updates all LEDs, sends 192 bits. TLC's GS register is 12 bits, UCB0 can only send 8 bits at a time. In my code, I am sending GS data for 2 LEDs in each iteration, 24 bits, 3 bytes. Total of 8 iterations. So for example, LED 15 and 14 is at max, 0x0F in leds[]. 00001111 and 00001111 First byte, I am taking leds[15] and shifting it 4 times to the left (basically multiplying it by 16 to get 12 bit value.) 11110000 Next byte contains 4 lower bits of LED 15 and 4 upper bits of LED 14. Since we have only 16 levels, 4 lower bits are always 0, so we send only leds[14] (we don't have to shift it because they are in the right position. 00001111 Last byte, all 0s since we have 16 levels only. In the end, we send: 111100000000 111100000000. Repeat that 7 more times for the remaining 14 LEDs If you want to have more levels, for example 256, all you need to do is change updateTLC() UCB0TXBUF = leds[(ledCounter << 1) + 1] ; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = leds[ledCounter << 1] >> 4; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = leds[ledCounter << 1] << 4; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? pillum 1 Quote Link to post Share on other sites
pillum 0 Posted July 12, 2012 Author Share Posted July 12, 2012 Ah ok, I get it now. I was just confused by the fact that you're counting 8 leds with ledcounter and sending 3 bytes each. Thanks for explaining Quote Link to post Share on other sites
pillum 0 Posted August 4, 2012 Author Share Posted August 4, 2012 Cr*p...happens again. This time everythings soldered so no flaky breadboard connection. Do I need to update DC register before updating GS register? Also, do I need the first cycle flag when not updating it? VPRG and DCPRG are grounded and not controlled by MSP this time since I'm using the DC data from EEPROM. Sniffer tells me, that there is a (clocked) current flowing through OUTn (strangely also on TLCs not connected to the MSP). But the LEDs are pretty dark to off using the same old resistor with value of 1.91kOhm Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.