Skocz do zawartości

TLC5920 - sterownik matrycy LED 16wierszy x 8 kolumn


FlyingDutch

Pomocna odpowiedź

Cześć,

używał może ktoś układu scalonego firmy "Texas Instruments" o symbolu TLC5920 (sprzętowy sterownik matrycy LED 16x8). Próbowałem napisać sterownik w C do tego układu (STM32F103 taktowany 72MHz) ale coś mi "nie trybi".  Dla stałych wzorów wyświetlanie matrycy jest OK. Gdy jednak próbuję wyswietlać dane z tablicy [16][9] odświeżane z około 20 Hz to wystepują błędy polegające na tym, że w niektórych wierszach minimalnie świecą się kolumny, które nie powinny.

Tutaj linki do strony produktu i data-sheet'a:

https://www.ti.com/product/TLC5920

https://www.ti.com/lit/ds/symlink/tlc5920.pdf?ts=1634571932501&ref_url=https%3A%2F%2Fwww.ti.com%2Fproduct%2FTLC5920

Jedyna biblioteka w C, którą znalzłem to ta do Arduino z tego projektu:

http://www.carbonfrog.com/Products/MC201V1.html

ale tam sposób obsługi programowej matrycy jest nieodpowiedni (i dokładność generacji przebiegów słaba). Spróbuję wygenerować "timing diagram" dla tego układu na FPGA, jak zadziała to napiszę kod drivera w języku C. Jakby ktoś używał tego scalaka to byłbym wdzięczny za jakieś użyteczne uwagi.

Pozdrawiam

Link do komentarza
Share on other sites

5 godzin temu, FlyingDutch napisał:

Gdy jednak próbuję wyswietlać dane z tablicy [16][9] odświeżane z około 20 Hz to wystepują błędy polegające na tym, że w niektórych wierszach minimalnie świecą się kolumny, które nie powinny.

Podobny problem miałem z wyświetlaczami 7-segmentowymi, kiedy częstotliwość była na tyle duża (jakieś 5-10MHz), że nie nadążało wygasić poprzedniej cyfry przed uruchomieniem następnej. W moim przypadku dodałem blanking (podobnie jak w monitorach VGA), co rozwiązało problem. 

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

Cześć,

no w końcu miałem trochę czasu, aby usiąść do zagadnienia. @H1M4W4R1 używałem kodu z podlinkowanego projektu (Arduino) i tam "blanking" niby był obsługiwany, ale ogólnie jak obejrzałem przebiegi za pomocą analizatora stanów logicznych to były one bardzo niedokładne (i nie jestem pewien, czy poprawne) Sprawdziłem także, jak generowany jest sygnał "LATCH" i czy wyście rejestru 16bitowego (wiersze) jest zatrzaskiwane w odpowiednim momencie i niby wyglądało to OK . Dzisiaj napisałem prosty kod w VHDL'u dla płytki Elbert v.2 (Spartan3A), który generuje sygnały potrzebne do obsługi wejścia szeregowego układu TLC5920 (SCLK, SIN, LATCH). Dodałem sobie IPCore z dodatkowym zegarem PLL, który na wyjśiu generuje sygnał zegarowy 50MHz (i mam dokładność generacji dowolnego sygnału wyjśiowego 20 ns). Tak wygląda układ testowy:

 

eLBERT_tlc.thumb.jpg.3919a9ccca1c3c7577ac902a0148c9bf.jpg

Na początku, zakładałem, że generację wszystkich przebiegów zrobię w jednej maszynie stanów skończonych, ale teraz generuje on jedynie sygnał "SCLK" zegara dla wejścia szeregowego wierszy. Stwierdziłem, że łatwiej będzie użyć po jednym procesie (z odpowiednimi listami wrażliwości) do generacji sygnałów "SIN" (wejście szer.) i "LATCH" - zatrzaskiwanie danych wejściowych w rejestrze szeregowo-równoległym (wiersze). Przykład generuje zapętlone przesyłanie i zatrzaskiwanie danyc (16 bit) dla jednego wiersza danych.

Oto kod dla głównego entity "programu" dla FPGA - "TLC5920Driver.vhd":

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    10:35:18 10/19/2021 
-- Design Name: 
-- Module Name:    TLC5920Driver - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity TLC5920Driver is
    Port ( clk12MHz : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           SCLKo : inout  STD_LOGIC;
           SINo : out  STD_LOGIC;
           LATCHo : out  STD_LOGIC;
           BLANKo : out  STD_LOGIC;
           DSELo : out  STD_LOGIC;
           CSEL0o : out  STD_LOGIC;
           CSEL1o : out  STD_LOGIC;
           CSEL2o : out  STD_LOGIC;
			  ERROR : out  STD_LOGIC -- Podlaczony do LED - swieci to blad
);			  
end TLC5920Driver;

architecture TLC5920Arch of TLC5920Driver is

COMPONENT PLL1
	PORT(
		CLKIN_IN : IN std_logic;          
		CLKFX_OUT : OUT std_logic;
		CLKIN_IBUFG_OUT : OUT std_logic;
		CLK0_OUT : OUT std_logic
		);
	END COMPONENT;
	
COMPONENT bit16RowREG
    Port ( clk50MHz : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           REG_O : out  STD_LOGIC_VECTOR (15 downto 0));
END COMPONENT;
	
COMPONENT OneRow_DMASM
    Port ( clk50MHz : in  STD_LOGIC;
           reset : in  STD_LOGIC;
			  a16bitReg: in  STD_LOGIC_VECTOR (15 downto 0);		  
           SCLK : inout  STD_LOGIC;
           SIN: out  STD_LOGIC;
           LATCH : out  STD_LOGIC;
           BLANK : out  STD_LOGIC;
           DSEL : out  STD_LOGIC;
           CSEL0 : out  STD_LOGIC;
           CSEL1 : out  STD_LOGIC;
           CSEL2 : out  STD_LOGIC;
			  ERROR : out  STD_LOGIC -- Podlaczony do LED - swieci to blad
			  );
END COMPONENT;
	
	--signals
	signal clk50MHzPLL :STD_LOGIC;
	signal clk50Buf,  clk50o :STD_LOGIC;
	signal s16BIT_REG: STD_LOGIC_VECTOR (15 downto 0);


begin
	 
	Clock_PLL1: PLL1 PORT MAP
		(
		CLKIN_IN => clk12MHz,
		CLKFX_OUT => clk50MHzPLL, --20ns okres
		CLKIN_IBUFG_OUT => clk50Buf,
		CLK0_OUT => clk50o
	);
	 
	REG16: bit16RowREG PORT MAP
    (
	        clk50MHz => clk50MHzPLL,
           rst => reset,
           REG_O => s16BIT_REG
	);
	
	DMASM: OneRow_DMASM PORT MAP
   (      clk50MHz  =>  clk50MHzPLL, --20ns okres
           reset => reset,
           a16bitReg =>  s16BIT_REG,
           SCLK => SCLKo,
           SIN => SINo,
           LATCH => LATCHo,
           BLANK => BLANKo,
           DSEL  => DSELo,
           CSEL0 => CSEL0o,
           CSEL1 => CSEL1o,
           CSEL2 => CSEL2o,
			  ERROR => ERROR
	);

end TLC5920Arch;

Aktualnie praktycznie cały kod generujący sygnały jest w komponencie "OneRow_DMASM":

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    11:47:33 10/19/2021 
-- Design Name: 
-- Module Name:    OneRow_DMASM - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity OneRow_DMASM is
    Port ( 
	        clk50MHz : in  STD_LOGIC; --20ns okres
           reset : in  STD_LOGIC;
           a16bitReg : in  STD_LOGIC_VECTOR (15 downto 0);
           SCLK : inout  STD_LOGIC;
           SIN : out  STD_LOGIC;
           LATCH : out  STD_LOGIC;
           BLANK : out  STD_LOGIC;
           DSEL : out  STD_LOGIC;
           CSEL0 : out  STD_LOGIC;
           CSEL1 : out  STD_LOGIC;
           CSEL2 : out  STD_LOGIC;
			  ERROR : out  STD_LOGIC -- Podlaczony do LED - swieci to blad
			  );
end OneRow_DMASM;

architecture Behavioral of OneRow_DMASM is

       type STATE is (S0_StartGen, S1_SCLK_HIGH, S2_SCLK_LOW, S10Awaria);
	
       signal CURRENT_STATE, NEXT_STATE: STATE;
		  
		 constant LICZNIK_LIMIT : integer := 1_000; -- deklaracja stalej z max wart licznika
 		
		 signal licznik : unsigned(10 downto 0) := b"00000000000"; -- definicja syg lokalnego
       --signal liczBitowSIN : unsigned(10 downto 0) := b"00000000000"; -- definicja syg lokalnego		 
		 signal liczBitowSIN : integer range 0 to 32 :=0;

begin

    SEQ: process(clk50MHz, reset)
	 begin
        if (reset = '0') then
		     licznik <= b"00000000000";
			  CURRENT_STATE <= S0_StartGen; 
			  NEXT_STATE <= S1_SCLK_HIGH;
			  --SCLK <= '0';
           --SIN  <= '0';
           --LATCH  <= '0';
           BLANK  <= '0';
           DSEL  <= '0';
           CSEL0  <= '0';
           CSEL1  <= '0';
           CSEL2  <= '0';
			  --ERROR  <= '0';
		  elsif (clk50MHz' event and clk50MHz = '1' ) then  
			  --if (licznik = b"00000000000") then
			  if (licznik = 0) then
			     CURRENT_STATE <= S0_StartGen; 
			     NEXT_STATE <= S1_SCLK_HIGH;
				  licznik <= licznik + 1;
				  --SCLK <= '1';
			   elsif ((licznik > 0) and (licznik < 10)) then
				    CURRENT_STATE <= S1_SCLK_HIGH; 
			       NEXT_STATE <= S2_SCLK_LOW;
				    licznik <= licznik + 1;
					 --SCLK <= '1';
				 elsif (licznik = 10) then	 
					 CURRENT_STATE <=  S2_SCLK_LOW; 
			       NEXT_STATE <= S0_StartGen; 
				    licznik <= licznik + 1;
					 --SCLK <= '0';
				 elsif ((licznik > 10)and (licznik < 21) ) then
				    CURRENT_STATE <= S2_SCLK_LOW;
			       NEXT_STATE <= S0_StartGen; 
				    licznik <= licznik + 1;
					 --SCLK <= '0';
				elsif (licznik = 21) then
				    licznik <= b"00000000000";
					 CURRENT_STATE <=  S0_StartGen;                                                                     
			       NEXT_STATE <= S1_SCLK_HIGH;
				else	 
                CURRENT_STATE <= NEXT_STATE;
				end if;
		  end if;
    end process; -- SEQ: 
	 
	 
	 COMB: process (CURRENT_STATE, reset)
	 begin
	     case CURRENT_STATE is
		      when S0_StartGen => 
				     SCLK <= '1';
					  ERROR <= '0';
				when S1_SCLK_HIGH =>
				    SCLK <= '1';
				when S2_SCLK_LOW =>
				    SCLK <= '0';
				when others =>  
				   ERROR <= '1'; --sygnalizacja blad
        end case;
	end process;  --COMB	

   SIN_GEN: 	process (SCLK, reset)
	   variable stanQ : STD_LOGIC := '0';
		variable ctn: integer range 0 to 10 :=0;
		--variable liczBitowSIN : integer range 0 to 32 :=0;
	   --variable a16bitRegX : STD_LOGIC_VECTOR (15 downto 0) := "1011000111100010";
	begin
	    if (reset = '0') then
		     ctn :=0;
		     liczBitowSIN <= 0;
	    elsif (SCLK' event and SCLK = '0' ) then
           SIN<= a16bitReg(liczBitowSIN);
           ctn := ctn + 1;
			  if ((ctn mod 1) = 0) then 
			       liczBitowSIN <= liczBitowSIN+1;
					 if (liczBitowSIN > 15) then
					    liczBitowSIN <= 0;
					 end if;
					 ctn :=0;
			  end if;		  
		 end if;
	end process;  --SIN_GEN
	
	LATCH_GEN: process (SCLK, reset)
	begin
	        if (reset = '0') then 
			     LATCH <= '0';
			  elsif (SCLK' event and SCLK = '1' ) then	
           if (liczBitowSIN = 15) then
			     LATCH <= '1';
			  else
			     LATCH <= '0';
			  end if;	  
		 end if;
	end process;  --LATCH_GEN
	
		  	  
end Behavioral;

Wartości danych dla "SIN" są brane z 16-to bitowego rejestru zdefiniowanego w kodzie.

Tutaj zrzut ekranu z symulacji:

tlc5920_fpga01.thumb.png.87b892f62ef224bd269bc9d4507d438c.png

A tutaj widok z analizatora stanów podłączonego do płytki FPGA Elbert v.2:

tlc5920_SCOPE.thumb.png.5145b2dadea32ef5efacd9e75af6c683.png

Zostały do wygenerowania sygnały obsługujące kolumny (wspólne segmenty) i testy układu z płytką PCB z IC TLC5920.Jak będę miał więcej czasu to opiszę to dokładniej.

BTW: czy mógłbym prosić któregoś z moderatorów o przeniesienie wątku do działu "Układy programowalne"?

Pozdrawiam

Edytowano przez FlyingDutch
update
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Cześć,

problem rozwiązany - okazało się, że była to winna zastosowanych diód LED o dużej jasności świecenia (4900 mcd podczas gdy zwykłe LED'y mają do 100 mcd).

Diody te zaczynały świecić już przy prądzie około 12 uA (mikro-Amper).Zarówno pierwotna wersja programu na STM32 jak i generacja przebiegów z układu FPGA były poprawne, po prostu układ TCL5920 był projektowany kilkanaście lat temu i wtedy nie były dostępne LED'y o takich parametrach, więć z pewnością nie był testowany dla tak małych prądów.

Temat do zamknięcia.

Pozdrawiam

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Gratuluje rozwiązania problemu.

9 minut temu, FlyingDutch napisał:

diód LED o dużej jasności świecenia (4900 mcd podczas gdy zwykłe LED'y mają do 100 mcd).

Diody te zaczynały świecić już przy prądzie około 12 uA (mikro-Amper).

Dasz namiar na te diody? Brzmi jak super dioda do jakiegoś urządzonka na baterię CR2023.

Link do komentarza
Share on other sites

1 godzinę temu, pmochocki napisał:

Gratuluje rozwiązania problemu.

Dasz namiar na te diody? Brzmi jak super dioda do jakiegoś urządzonka na baterię CR2023.

Cześć,

pewnie - jutro jak będę w pracy (były w TME - producent chiński), bo w domu nie mam symbolu. Ogólnie na TME.eu jak poszukasz w wyszukiwarce to znajdziesz diody LED o jasnościach świecenia od 30 mcd do 15000 mcd (te użyte w prototypie były akurat zielone średnica 3 mm i jasność 4900 mcd).

Pozdrawiam

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.