Gast
#1495866
Hallo!
Ich habe hier ein Spartan 3 Board sowie ein cmps03 Kompassmodul liegen.
Dieses habe ich bereits erfolgreich per PWM auslesen können,
funktioniert ohne Probleme. Nun wollte ich das Ganze gern per I2C
ansteuern, nur leider funktioniert das bisher nicht richtig. Ich habe
das I2C Protokoll erstmal (vielleicht ein wenig unübersichtlich) mit
einem recht langen Automaten implementiert, laut LogicAnalyzer sende ich
auch das richtige raus (so wie es im Datenblatt steht). Geschwindigkeit
ist unter 100kHz,das sollte auch nicht das Problem sein. Ich poste
gleich mal den Automaten, vielleicht kann mir ja hier jemand den
entscheidenden Hinweis geben.. :-) Vielen Dank schonmal!!
main: process(clk)
variable I2Cstate: integer range 0 to 30:=0;
variable adr_cnt: integer range 0 to 15:=15;
begin
if clk='1' and clk'event then
if btn = '1' then -- Kalibrierung, Pin 6 kurzzeitig auf GND ziehen
calibrate <= '0';
else
calibrate <= 'Z';
end if;
case I2Cstate is
when 0 =>
SDA <= '1'; SCL <= '1'; ready<='1';
I2Cstate := I2Cstate+1;
when 1=>
if Start = '1' and ready = '1' then
SDA <= '0'; ready<='0';
I2Cstate := I2Cstate+1;
else
I2Cstate := 1;
end if;
when 2 =>
SCL<='1';
I2Cstate := I2Cstate+1;
wen 3 => -- Kompassadresse C0
case adr_cnt is
when 15|13|11|9|7|5|3 =>
SCL <= '0';
SDA <= Adr((adr_cnt-1)/2);
adr_cnt := adr_cnt-1;
when 14|12|10|8|6|4|2 =>
SCL <= '1';
adr_cnt := adr_cnt-1;
when 1 =>
SCL <= '0';
SDA <= Adr(adr_cnt-1);
adr_cnt := adr_cnt-1;
when 0 =>
SCL <= '1';
adr_cnt := 15;
I2Cstate := I2Cstate+1;
end case;
when 17 =>
SCL <= '0';
I2Cstate := I2Cstate+1;
when 4|9|19|24 =>
SCL <= '0'; SDA <= 'Z';
I2Cstate := I2Cstate+1;
when 5|10|20|25 => -- ACK
ACK <= SDA; SCL <= '1';
if ACK = '0' then
ACK <='1';
SCL <='0';
I2Cstate := I2Cstate+2;
end if;
when 6|7|11|12|16|21|26|27|29 =>
I2Cstate := I2Cstate+1;
when 8 => -- Registeradresse (1=Kompass Wert)
case adr_cnt is
when 15|13|11|9|7|5|3 =>
SCL <= '0';
SDA <= RegNr((adr_cnt-1)/2);
adr_cnt := adr_cnt-1;
when 14|12|10|8|6|4|2 =>
SCL <= '1';
adr_cnt := adr_cnt-1;
when 1 =>
SCL <= '0';
SDA <= RegNr(adr_cnt-1);
adr_cnt := adr_cnt-1;
when 0 =>
SCL <= '1';
adr_cnt := 15;
I2Cstate := I2Cstate+1;
end case;
when 22 =>
SCL <= '0'; SDA <= '0';
I2Cstate := I2Cstate+1;
when 13|30 =>
SDA <= '1'; -- repeated Startbit
I2Cstate := I2Cstate+1;
when 14|28 =>
SCL <= '1';
I2Cstate := I2Cstate+1;
when 15 =>
SDA <= '0';
I2Cstate := I2Cstate+1;
when 18 => -- Kompassadresse C1 (gesetztes R/W Bit)
case adr_cnt is
when 15|13|11|9|7|5|3 =>
SCL <= '0';
SDA <= AdrRW((adr_cnt-1)/2);
adr_cnt := adr_cnt-1;
when 14|12|10|8|6|4|2 =>
SCL <= '1';
adr_cnt := adr_cnt-1;
when 1 =>
SCL <= '0';
SDA <= AdrRW(adr_cnt-1);
adr_cnt := adr_cnt-1;
when 0 =>
SCL <= '1';
adr_cnt := 15;
I2Cstate := I2Cstate+1;
end case;
when 23 => -- Kompass Wert lesen
SDA <= 'Z';
case adr_cnt is
when 15|13|11|9|7|5|3 =>
SCL <= '0';
cmps((adr_cnt-1)/2) <= SDA;
adr_cnt := adr_cnt-1;
when 14|12|10|8|6|4|2 =>
SCL <= '1';
adr_cnt := adr_cnt-1;
when 1 =>
SCL <= '0';
cmps(adr_cnt-1) <= SDA;
adr_cnt := adr_cnt-1;
when 0 =>
SCL <= '1';
adr_cnt := 15;
i2csig <= cmps; -- Kompasswert übergeben
I2Cstate := I2Cstate+1;
end case;
when 31 =>
I2Cstate := 0;
end case;
end if;
end process;