hall zusammen es geht um ein nec signal ich habe ein signal (SIG) 32 BIT (31 downto 0), der so gebaut ist BIT =1 ist :wenn der impuls 560 us und die pausenzeit ist 1,7ms bit =0 ist:wenn der impuls 560 us und der pausen zeit 560 us 1 und 0 UNTERSCHEIDEN SICH VON DER PAUSENZEIT DER OSZILATORFREQUENZ VON MEINEM BOARD IST 30 MHZ ICH HABE SO GEMACHT ABER KLAPPT NICHT .. ... necsr <= necsr(1 downto 0) & nec when rising_edge(clk); bits <= bits (31 downto 0)& necsig when rising_edge(nec) if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt ELSE cnt <= cnt + 1 ;--hochzählen if cnt > 37500 then -- wenn der zähler 0 bit länge(freq) überschreitet necsig <= '1'; else if cnt <37500 then -- wenn zâhler kleiner als 0 bit länge necsig <= '0'; das problem ich will dass necsig zeigt ein 1 von bitanfang bis zu bitende und nicht erst wenn cnt > 37500 oder das geht nicht ? oder ich habe denkfehler bitte um hilfe ich hoffe meine frage ist klar
Eine einfache Lösung, falls ich alles richtig verstanden habe : Du wertest zu dem zeitpunkt an dem feststeht ob eine '0' oder '1' ankam für einen takt lang aus. Da du intern eh mit 30mhz arbeiten willst bringt es dir ja eh nichts wenn du zigtausend takte lang weist was da kam, du musst es ja nur einmal wissen. D.h. an der Stelle wo du den Zähler zurücksetzt würdest du die Auswertung vornehmen anhand des aktuellen necsig. bsp:
1 | process (clk) |
2 | begin
|
3 | |
4 | necsr <= necsr(1 downto 0) & nec when rising_edge(clk); |
5 | |
6 | if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler |
7 | cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt |
8 | bits <= bits (31 downto 0)& necsig ; |
9 | ELSE
|
10 | cnt <= cnt + 1 ;--hochzählen |
11 | end if; |
12 | |
13 | if cnt > 37500 then -- wenn der zähler 0 bit länge(freq) überschreitet |
14 | necsig <= '1'; |
15 | else
|
16 | necsig <= '0'; |
17 | end if; |
18 | |
19 | end process; |
allerdings wie gesagt, nur soweit ich das verstanden habe. was das rising_edge(nec) dort soll weiß ich z.b. nicht, das macht meiner Meinung nach überhaupt keinen Sinn. Ansonsten ist dein Code auch nur sehr zusammengekleckst. Aber probiers erstmal wie ich das beschrieben habe und wenn das noch nicht klappt -> bitte den gesamten code in [/vhdl] + [vhdl] posten oder als .vhd anhängen.
Muss mich echt mal anmelden...wenn dann natürlich mit clk im process :
1 | process (clk) |
2 | begin
|
3 | if rising_edge(clk) then |
4 | |
5 | necsr <= necsr(1 downto 0) & nec; |
6 | |
7 | if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler |
8 | cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt |
9 | bits <= bits (31 downto 0)& necsig ; |
10 | ELSE
|
11 | cnt <= cnt + 1 ;--hochzählen |
12 | end if; |
13 | |
14 | if cnt > 37500 then -- wenn der zähler 0 bit länge(freq) überschreitet |
15 | necsig <= '1'; |
16 | else
|
17 | necsig <= '0'; |
18 | end if; |
19 | |
20 | end if; |
21 | end process; |
> allerdings wie gesagt, nur soweit ich das verstanden habe. Das NEC Signal ist realtiv simpel, es fehlt hier noch, dass der 9ms Puls am Anfang zur Synchronisation verwendet wird. Schön erklärt ist das dort: http://www.sbprojects.com/knowledge/ir/nec.htm Ich habe das mit dem NEC-Signal auf meiner todo-Liste und werde es die Tage mal durchkneten. Allerdings zeigt der NEC-Modus auf meiner Universal-FB ein etwas anderes zetiliches Verhalten... ;-)
Das sieht ja wirklich simpel aus. Danke für den Link. Mir war bei der Fragestellung oben gar nicht bewusst das es sich um ein Standardprotokoll handelt. Hmm, den Startpulse kann man sicher auch ignorieren wenns in einen kleinen CPLD rein soll..macht den Zähler immerhin um 10 FFs kleiner. Werd mich morgen auch mal daran versuchen. Immer eine gute Übung :)
danke zusammen das ist richtig der start signal mit 9ms wollte ich gar nich daran denken,weil ich keine vorstellung habe wie ich das mache an miller :wie komme ich zu deiner todo liste miller?
> wie komme ich zu deiner todo liste miller?
Keine Chance....
Die ist in meinem Kopf ;-)
@ Iulius
Das mit dem Sync ist nicht unwichtig, sonst kannst du einen Start nur
raten. Vor allem solltest du einen sättigenden Zähler für die Bitzeit
verwenden. Denn die Zeit für eine '1' kann auch mal wesentlich länger
sein: ich messe an der FB hier bis zu 25 ms!!
Das einzige Problem das ich sehe, ist wenn ich das Gerät zum Empfangen während einer laufenden Übertragung einschalte. Auf den anderen Seite gefällt mir das so oder so nicht. Habe jetzt einen Transceiver entworfen der ~160 LE verbraucht. Davon entfallen 60 auf den Empfänger(ohne Sync) und 100 auf den Sender(ziemlich genau nach Protokoll). Irgentwie wohl doch nix für den CPLD wobei ich mich ehrlich gesagt frage wo die ganze Logik herkommt... klar Schieberegister+Zähler frisst schon einiges, aber trotzdem. Habs mal angehangen, aber naja, gefällt mir wie gesagt nicht besonders. Zu groß und zu frickelig für meinen Geschmack.
> Denn die Zeit für eine '1' kann auch mal wesentlich länger > > sein: ich messe an der FB hier bis zu 25 ms!! AN MILLER ,ICH BIN GESPANNT WIE DU DAS MACHST
Iulius C. schrieb: > Habs mal angehangen, aber naja, gefällt mir wie gesagt nicht besonders. > > Zu groß und zu frickelig für meinen Geschmack. MILLER SAGT IST SEHR EINFACH ICH HABE SCHON SEIN RC5-empfänger gesehen er hat das super gemacht und nur in ein paar zeilen aber bei rc5 die bits sind gleich fuer mich ist viel einfacher als nec-emp na ja nicht aufgeben ,programmieren braucht geduld und erfahrung ich hoffe ein ergebnis von Miller
Hi, wenn du Lothars Link oben (uebrigens danke dafuer, kann ich gut gebrauchen!) folgst, dann wirst du relativ einfach rausfinden, wie man das loesen kann... Gruss, - berndl
rc5 ist TOTAL ANDERES ALS NEC link von miller ist direkt neben seinen namen DARAUF DRÜCKEN
Hier wie versprochen meine Lösungsansätze ;-) Variante 1, Bits werden mit der steigenden Flanke vom NEC-Signal eingelesen und nach Ablauf eines Timeouts (Pause zwischen 2 Übertragunspaketen) übernommen.
1 | library IEEE; |
2 | use IEEE.std_logic_1164.all; |
3 | use IEEE.numeric_std.all; |
4 | |
5 | entity NEC_Decoder is |
6 | Port ( clk : in STD_LOGIC; |
7 | NEC : in STD_LOGIC; |
8 | RXdata : out STD_LOGIC_VECTOR (15 downto 0)); |
9 | end NEC_Decoder; |
10 | |
11 | architecture Behavioral of NEC_Decoder is |
12 | signal necsr : std_logic_vector (2 downto 0) := "000"; |
13 | constant oscclk : integer := 50000000; -- 50MHz z.B. FPGA |
14 | constant timeout : integer := (oscclk/(1000000/20000))-1; -- Timeout: 20 ms, nach Timeout werden Daten übernommen. |
15 | constant one : integer := (oscclk/(1000000/1685))-1; -- (2,25+1,12)/2 = 1685 us |
16 | signal cnt : integer range 0 to timeout := 0; |
17 | signal bits : std_logic_vector (15 downto 0) := (others=>'0'); |
18 | signal nextbit : std_logic := '0'; |
19 | begin
|
20 | -- hart aber herzlich:
|
21 | -- NEC-Signal einlesen, bis Pause (Timeout) länger als 20 ms
|
22 | process begin |
23 | wait until rising_edge(clk); |
24 | necsr <= necsr(necsr'left-1 downto 0) & NEC; |
25 | if (cnt<timeout) then |
26 | cnt <= cnt+1; |
27 | else -- Timeout --> Daten übernehmen |
28 | RXdata <= bits; |
29 | end if; |
30 | if (necsr="001") then -- steigende Flanke |
31 | bits <= bits(bits'left-1 downto 0) & nextbit; |
32 | cnt <= 0; |
33 | end if; |
34 | end process; |
35 | nextbit <= '1' when (cnt >= one) else '0'; |
36 | end Behavioral; |
Das funktioniert mit meiner Fernbedienung hier, weil die den Repeat-Code nicht sendet. Statt dessen wird das komplette Datenpaket nochmal übertragen (siehe Screenshot) :-o Die Variante 2 ist konform zum NEC-Protokoll, weil dort die Repeat-Pulse gesondert behandelt werden (siehe Anhang). Allerdings kann ich die Funktion nicht detailliert testen, weil wie gesagt meine FB nicht ganz das beschriebene NEC-Protokoll sendet... :-/
danke sehr miller, du hast dein versprechen gehalten danke nochmal aber ich werde dein code erst morgen analysieren ,bin müde mein cnt zählt auch vor der ersten flanke . . . signal cnt : integer range 0 to 67567 := 0; bits <= bits (31 downto 0)& NECSIG ; . . . if rising_edge(clk) then if (necsr(2 downto 1)= "01") then cnt <= 0; else cnt <= cnt + 1 ; end if ;END IF; NORMALERWEISE DER CNT FÄNGT ZU ZÄHLEN ERST NACH DEM TREFFEN MIT EINER FLANKE UND NICHT VOR DEM ERSTEN FLANKE VON DER STARTBIT, WO KEINE FLANKE GIBT VORAN KANN DAS LIEGEN? HABE ICH WAS FALSCHES üBERSEHEN?
Was mir da sofort auffällt: Dein Zähler begrenzt nicht. Der zählt lustig weiter bis 131071 und läuft dann über auf 0 und zählt dann dort weiter.... Besser wäre es auf jeden Fall so:
1 | if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler |
2 | cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt |
3 | bits <= bits (31 downto 0)& necsig ; |
4 | ELSE
|
5 | if (cnt<67567) then cnt <= cnt+1; end if; |
6 | end if; |
>>> signal cnt : integer range 0 to 67567 := 0;
Warum reichen dir nicht 65535 als Endwert?
Dann würden für den Zähler 16 Bit reichen.
dein programm ist 90 prozent wie meins es gibt ein problem was ich seit tagen lösen will die steigende flanke von nec signal zeigt den wert von der dem nextbit(dein signal) von den vorherigen nec signal ; der letzen bit wird unbewertet , stattdessen ist der 15-te bei dir ,bei mir auch der start bit hier ist ein fertigen testbench kannst du noch mal probieren NEC_PROC :PROCESS BEGIN NEC <= '0'; --pause WAIT FOR 3 MS; NEC <= '1'; WAIT FOR 9 mS;--START BIT NEC <= '0'; WAIT FOR 4500 us; NEC <= '1'; -- 1 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 2 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 3 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 560 US; NEC <= '1'; -- 4 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 560 US; NEC <= '1'; -- 5 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 6 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 7 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 560 US; NEC <= '1'; -- 8 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 1 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 2 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 3 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 560 US; NEC <= '1'; -- 4 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 5 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 560 US; NEC <= '1'; -- 6 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 1690 US; NEC <= '1'; -- 7 WAIT FOR 560 us; NEC <= '0'; WAIT FOR 560 US; NEC <= '1'; -- 8 WAIT FOR 560 us; NEC <= '0'; --PAUSE ,INKLUSIV PAUSENZEIT VON DEM LETZTENBIT WAIT FOR 20 MS; END PROCESS;
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.