?? con_pcf8563.vhd
字號:
--文件名:con_pcf8563.vhd
--功 能:讀出pcf8563中的時鐘信號
--說 明:PCF8563芯片是PHILIPS公司推出的一款工業級內含I2C總線接口功能的具有極低功耗的多功能時鐘/日歷芯片。
--該程序實現的功能是把PCF8563芯片中的時鐘讀出來顯示,而且編寫該程序的主要目的是教會大家如何對該時鐘芯片進行編程控制,
--因此我們只是把芯片中時鐘的秒位、分位讀出,并用數碼管顯示。PCF8563芯片的功能十分的強大,我們可以應用它設計出很多有用的
--產品,目前,我們教會大家應用這種芯片的方法。用戶可以根據自身的需要對芯片不同的地址和數據進行操作實現自己功能。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL; --調試成功
entity con_pcf8563 is
Port ( sysclk,reset : in std_logic;
sda,scl : inout std_logic;
cs: out std_logic;
shift_led : out std_logic_vector(3 downto 0);
led:out std_logic_vector(8 downto 1));
end con_pcf8563;
architecture Behavioral of con_pcf8563 is
type state is (prepare,start,transmit_slave_address,check_ack1,transmit_sub_address,check_ack2,
transmit_data,check_ack3,transmit_data1,transmit_data2,check_ack4,check_ack44,start1,start2,transmit_slave_address1,
transmit_slave_address2,
transmit_sub_address1,check_ack5,check_ack6,check_ack7,read_data,stop); --定義狀態機的各子狀態;
signal current_state:state; --定義信號;
signal clock,shift_clk:std_logic;
signal code_led : std_logic_vector(3 downto 0);
signal reg_led : std_logic_vector(8 downto 1);
begin
pulse:process(sysclk,reset) --進程1,分頻得到f為400khz的時鐘信號
variable count:integer range 0 to 125000;
begin
if reset='0' then count:=0;
elsif rising_edge(sysclk) then
count:=count+1;
if count=65000 then clock<='1';
elsif count=125000 then clock<='0';count:=0; --frequency:400kHz
end if;
end if;
end process pulse;
statemachine:process(clock,reset) --進程2,狀態機的轉換
variable slave_address1,sub_address1,data1,slave_address2,sub_address2:std_logic_vector(8 downto 1);
variable cnt:std_logic_vector(6 downto 0);
variable cnt1:integer range 0 to 8;
variable count1:integer range 0 to 40;
begin
if reset='0' then count1:=0;cnt:="0000000";cnt1:=8;cs<='1';
sda<='1';scl<='1';slave_address1:="10100010";slave_address2:="10100011";
sub_address1:="00000000"; sub_address2:="00000010";
current_state<=prepare;data1:="00000000";
reg_led<="11111111";
elsif rising_edge(clock) then
case current_state is
when prepare=>cnt:=cnt+1;-- --準備狀態,等各個器件復位
if cnt="0000010" then cnt:="0000000";current_state<=start;
else current_state<=prepare;
end if;
when start=>count1:=count1+1; --起始信號產生狀態
case count1 is
when 1=>sda<='1';
when 2=>scl<='1';
when 3=>sda<='0';
when 4=>scl<='0';
when 5=>count1:=0;current_state<=transmit_slave_address;
when others=>null;
end case;
when transmit_slave_address=>count1:=count1+1; --發送器件從地址
case count1 is
when 1=>sda<=slave_address1(cnt1);
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack1;
else current_state<=transmit_slave_address;
end if;
when others=>null;
end case;
when check_ack1=>count1:=count1+1; --查詢應答信號
case count1 is
when 1=>sda<='0';
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>
current_state<=transmit_sub_address;
count1:=0;
when others=>null;
end case;
when transmit_sub_address=>count1:=count1+1; reg_led<="11111110"; --發送器件子地址
case count1 is
when 1=>sda<=sub_address1(cnt1);
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack2;
else current_state<=transmit_sub_address;
end if;
when others=>null;
end case;
when check_ack2=>count1:=count1+1; --查詢應答信號
case count1 is
when 1=>sda<='0';
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>current_state<=transmit_data;
count1:=0;
when others=>null;
end case;
when transmit_data=>count1:=count1+1; reg_led<="11111101"; --發送數據
case count1 is
when 1=>sda<=data1(cnt1);
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack3;
else current_state<=transmit_data;
end if;
when others=>null;
end case;
when check_ack3=>count1:=count1+1; --查詢應答信號
case count1 is
when 1=>sda<='0';
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>
current_state<=transmit_data1;
count1:=0;
when others=>null;
end case;
when transmit_data1=>count1:=count1+1; --發送數據
case count1 is
when 1=>sda<=data1(cnt1);
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack4;
else current_state<=transmit_data1;
end if;
when others=>null;
end case;
when check_ack4=>count1:=count1+1; --查詢應答信號
case count1 is
when 1=>sda<='0';
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>
current_state<=transmit_data2;
count1:=0;
when others=>null;
end case;
when transmit_data2=>count1:=count1+1; reg_led<="11111011"; --發送數據
case count1 is
when 1=>sda<=data1(cnt1);
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack44;
else current_state<=transmit_data2;
end if;
when others=>null;
end case;
when check_ack44=>count1:=count1+1; --查詢應答信號
case count1 is
when 1=>sda<='0';
when 2=>scl<='1';
when 3=>scl<='0';
when 4=>
current_state<=start1;
count1:=0;
when others=>null;
end case;
when start1=>count1:=count1+1; --起始信號產生狀態
case count1 is
when 1=>sda<='1';
when 3=>scl<='1';
when 5=>sda<='0';
when 7=>scl<='0';
when 9=>count1:=0;current_state<=transmit_slave_address1;
when others=>null;
end case;
when transmit_slave_address1=>count1:=count1+1; --發送器件從地址
case count1 is
when 1=>sda<=slave_address1(cnt1);
when 3=>scl<='1';
when 6=>scl<='0';
when 8=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack5;
else current_state<=transmit_slave_address1;
end if;
when others=>null;
end case;
when check_ack5=>count1:=count1+1; --查詢應答信號
case count1 is
when 3=>sda<='0';
when 6=>scl<='1';
when 8=>scl<='0';
when 10=>
current_state<=transmit_sub_address1;
count1:=0;
when others=>null;
end case;
when transmit_sub_address1=>count1:=count1+1; --發送器件子地址
case count1 is
when 1=>sda<=sub_address2(cnt1);
when 3=>scl<='1';
when 6=>scl<='0';
when 9=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack6;
else current_state<=transmit_sub_address1;
end if;
when others=>null;
end case;
when check_ack6=>count1:=count1+1; --查詢應答信號
case count1 is
when 3=>sda<='0';
when 6=>scl<='1';
when 8=>scl<='0';
when 10=>
current_state<=start2;
count1:=0;
when others=>null;
end case;
when start2=>count1:=count1+1; --重新起始信號產生狀態
case count1 is
when 1=>sda<='1';
when 3=>scl<='1';
when 6=>sda<='0';
when 8=>scl<='0';
when 10=>count1:=0;current_state<=transmit_slave_address2;
when others=>null;
end case;
when transmit_slave_address2=>count1:=count1+1; --發送器件從地址
case count1 is
when 1=>sda<=slave_address2(cnt1);
when 3=>scl<='1';
when 6=>scl<='0';
when 8=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=check_ack7;
else current_state<=transmit_slave_address2;
end if;
when others=>null;
end case;
when check_ack7=>count1:=count1+1; --查詢應答信號
case count1 is
when 3=>sda<='0';
when 6=>scl<='1';
when 8=>scl<='0';
when 10=>
current_state<=read_data;
count1:=0;
when others=>null;
end case;
when read_data=>count1:=count1+1; --讀操作
case count1 is
when 1=>sda<='Z';
when 4=>scl<='1';
when 8=>reg_led(cnt1)<=sda;
when 10=>scl<='0';
when 12=>cnt1:=cnt1-1;count1:=0;
if cnt1=0 then cnt1:=8;
current_state<=stop;
else current_state<=read_data;
end if;
when others=>null;
end case;
when stop=>count1:=count1+1; --產生停止信號
case count1 is
when 1=>sda<='0';
when 3=>scl<='1';
when 10=>sda<='1';
when 15=>count1:=0;current_state<=start1;
when others=>null;
end case;
when others=>null;
end case;
end if;
end process;
process(sysclk) --動態掃描模塊
variable cnt : integer range 0 to 50000;
begin
if rising_edge(sysclk) then cnt:=cnt+1;
if cnt<25000 then shift_clk<='1';
elsif cnt<50000 then shift_clk<='0';
else cnt:=0;
end if;
end if;
end process;
process(shift_clk)
variable cnt : integer range 0 to 1;
begin
if rising_edge(shift_clk) then
cnt:=cnt+1;
if cnt=0 then shift_led<="1101";code_led<=reg_led(4 downto 1);
else shift_led<="1011";code_led<='0'®_led(7 downto 5);
end if;
end if;
end process;
with code_led select --數碼管譯碼
led <="10000001" when "0000",
"11001111" when "0001",
"10010010" when "0010",
"10000110" when "0011",
"11001100" when "0100",
"10100100" when "0101",
"10100000" when "0110",
"10001111" when "0111",
"10000000" when "1000",
"10000100" when "1001",
"11111111" when others;
end Behavioral;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -