freakone | strona domowa

freakone.pl

04 Lipca

Driver LED MBI5168 w połączeniu z Atmegą i MSP430

Biorąc się za projekt LED-CUBE'a chciałem wykorzystać driver MBI5168 do sterowania diodami, jednak jak się okazało nie mogę tego zrobić z 2 prostych powodów:

  • Driver posiada tylko 8 wyjść - ja potrzebuję 9ciu (to jeszcze dałoby się jakoś obejść)
  • W driverze wyjścia są katodami, ja katody mam połączone jako warstwy (3) więc driver lekko by się marnował, a kostki przelutowywać mi się nie chce. Wygodniejsze i bardziej ekonomicznie będzie zastosowanie tranzystorów.


Podłączenie:


  • pin 1 - GND: masa
  • pin 2 - SDI: wejście danych
  • pin 3 - CLK: wejście zegara taktującego
  • pin 4 - sygnalizacja początku (stan wysoki) i końca (stan niski) transmisji
  • piny 5-12: wyjścia prądowe diód, tutaj podpinamy katodę diody
  • pin 13 - OE: pin służący do włączania (stan niski) i wyłączania (stan wysoki) układu
  • pin 14 - SDO: wyjście danych, używane przy łączeniu kilku driverów
  • pin 15 - R-EXT: między ten pin, a masę (pin 1) włączamy rezystor ograniczający prąd wysyłany do diód, ja zastosowałem 200omów, co daje około 15mA na diodę
  • pin 16 - VDD: +5V, tutaj podłączamy anody


Atmega 8

W przypadku atmegi zarówno driver MBI5168 jak i atmega były zasilane z jednego źródłą zasilania. SPI zostało wykonane w sposób programowy, w nagłówku pliku wpisujemy porty, do których zostały podłączone odpowiednie piny.

Program zapala wszystkie diody (jeśli mamy je podłączone), a następnie po kolei je gasi. Dane co do aktywności diód przekazujemy funkcją transmit_byte(), która jako parametr przyjmóje bajt infromacji. Każdy bit odpowiada jednemu wyjściu, OUT7 to pierwszy bit z prawej strony. Przekazując 0b00001001 otrzymamy aktywne wyjście 7 i 4.

#include <avr/io.h> 
#include <util/delay.h>

// CMD - wyjście, dane transmisji
#define CMD_SET PORTC |= (1<<4)
#define CMD_CLR PORTC &= ~(1<<4)
#define CMD_DIR DDRC |= (1<<4)

// CLK - wyjście, zegar transmisji
#define CLK_SET PORTC |= (1<<3)
#define CLK_CLR PORTC &= ~(1<<3)
#define CLK_DIR DDRC |= (1<<3)

// LE - wyjście, sygnalizacja początku transmisji
#define T_START PORTC |= (1<<2)
#define T_END PORTC &= ~(1<<2)
#define T_DIR DDRC |= (1<<2)

// OE - wyjście, włączenie i wyłączenie układu
#define MBI_OFF PORTC |= (1<<1)
#define MBI_ON PORTC &= ~(1<<1)
#define MBI_DIR DDRC |= (1<<1)

//opóźnienie
#define _NOP_ asm volatile("nop\n\t""nop\n\t" "nop\n\t" "nop\n\t" ::)

void transmit_byte(unsigned char byte)
{
	T_START;
	
   for(int i = 0; i < 8; i++, byte>>=1)
   {
       CLK_CLR;
       if(byte& 0x01) CMD_SET; else CMD_CLR;
       _NOP_;
	   _NOP_;
       CLK_SET;
   }
   CMD_SET;
   
   T_END;
}

int main()
{	
	T_DIR;
	CLK_DIR;
	CMD_DIR;
	MBI_DIR; // ustawiamy kierunki transmisji	
	
	MBI_ON; // włączamy wyświetlanie

	char dane = 0xff;
	
	while(1)
	{
		transmit_byte(dane); 
		
		for(int i = 0; i <8; i++)
		{
			dane &= ~(1 << i);
			transmit_byte(dane);
			_delay_ms(500);
		} // gasimy diody po kolei
		
		dane = 0xff; //zapalamy wszystkie diody
	}
	
	return 0;
}


LanuchPad - MSP430G2553

W tym przypadku zastosowany został sprzętowy interfejs SPI - USCI A. CLK podłączamy pod P1.4, SDI pod P1.2, a LE pod P1.6. Pin OE został na stałe podpięty do masy, co skutkuje ciągłą pracą układu. W programie wykorzystujemy programowalny przycisk Lanuchpada do gaszenia diód.
Funkcja transmit_byte, działa prawie tak samo jak w przypadku atmegi, różnica polega na tym, że bity są odwrócone (OUT0 to pierwszy bit z prawej strony).

LanuchPad i układ MBI były zasilane z osobnych źródeł - MSP pobierał prąd z USB (3.3V) natomiast MBI z zewnętrznego zasilacza ze stabilizatorem LM317.

#include <msp430.h>

void transmit_byte(unsigned char byte)
{
	P1OUT |= BIT6; // dajemy znak na rozpoczęcie transmisji

	UCA0TXBUF = byte; //umieszczemy dane w buforze
	while (!(IFG2 & UCA0TXIFG)); // czekamy na zakońćzenie transmisji

	P1OUT &= ~BIT6; // dajemy znak na koniec transmisji
}

void hw_init()
{
	WDTCTL = WDTPW + WDTHOLD;		// watchdog off
	P1DIR |= BIT6; // P1.6 - flaga rozpoczęcia/ zakończenia transmisji

	P1SEL = BIT2 + BIT4;
	P1SEL2 = BIT2 + BIT4; // P1.2 i P1.4 przełączamy na HW CLK i MOSI

	UCA0CTL0 |= UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master
	UCA0CTL1 |= UCSSEL_2;                     // SMCLK
	UCA0MCTL = 0;                             // No modulation
	UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

	P1DIR &= ~BIT3; //P1.3 jako wyjscie
	P1REN |= BIT3; // ustawiamy podciągnięcie do vcc
	P1OUT |= BIT3; // aktywujemy podciągnięćie do vcc


}

int main(void) {

	unsigned int i;

	hw_init();
	
	unsigned char dane = 0xff;
	while(1)
	{

		transmit_byte(dane);
		_delay_cycles(200000);

		for(i = 0; i < 8; i++)
		{
			while(P1IN & BIT3);
			while(!(P1IN & BIT3)); //czekamy na przycisniecie przycisku

			dane &= ~(1 << i);
			transmit_byte(dane);
		} // gasimy diody po kolei

		dane = 0xff; //zapalamy wszystkie diody
	}
}