专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
搞了几天的PCF8563时钟芯片。。求助。。
2019-07-21 07:07
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
5196
18
1422
I2C有应答,但是不管写什么数据进去,读出来都是为0。有应答,应该可以说时序没有问题吧?、不知道为什么??晶振起振了。。换了几片的8563都不行。。写数据是按手册来写的。。望搞过的大侠求求助。。
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
18条回答
qianyuyu
2019-07-23 06:40
--贴一个VHDL程序,基本是可以用的,但是之间感觉比较快。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity rtc is
generic(
constant CLK_RISING_CN : std_logic_vector(5 downto 0):= "010000";
constant CLK_FALING_CN : std_logic_vector(5 downto 0):= "011111";
constant CLK_DEVIDE_MAX: std_logic_vector(5 downto 0):= "011111"
);
port(
nRST : IN STD_LOGIC;
SYSCLK : IN STD_LOGIC;
rtc_int : IN STD_LOGIC;
rtc_scl : OUT STD_LOGIC;
rtc_sda : INOUT STD_LOGIC;
poweron : IN STD_LOGIC);
end rtc;
architecture behav of rtc is
type state2 is (idle,start,tran,recv,wait_2sck,stop);
type state1 is (idle,set_reg,set_time,read_time);
signal pstate2: state2:= idle;
signal pstate1: state1:= idle;
signal data_tran: std_logic_vector(7 downto 0):= (others => '0');
signal data_rec: std_logic_vector(7 downto 0):= (others => '0');
signal tran_en: std_logic:= '0';
signal rec_en: std_logic:= '0';
signal clk_en: std_logic:= '0';
signal stop_en: std_logic:= '0';
signal start_en: std_logic:= '0';
signal cnt_rtc_scl: std_logic_vector(4 downto 0):= (others => '0'); --cnt_rtc_scl * rtc_scl_buf
signal cnt_data: std_logic_vector(7 downto 0):= (others => '0');
signal second: std_logic_vector(5 downto 0):= (others => '0');
signal min: std_logic_vector(5 downto 0):= (others => '0');
signal hour: std_logic_vector(4 downto 0):= (others => '0');
signal days: std_logic_vector(4 downto 0):= (others => '0');
signal weekdays: std_logic_vector(2 downto 0):= (others => '0');
signal months: std_logic_vector(3 downto 0):= (others => '0');
signal years: std_logic_vector(6 downto 0):= (others => '0');
signal centurys: std_logic_vector(6 downto 0):= (others => '0');
signal alarm_min: std_logic_vector(5 downto 0):= (others => '0');
signal alarm_hour: std_logic_vector(4 downto 0):= (others => '0');
signal alarm_days: std_logic_vector(4 downto 0):= (others => '0');
signal alarm_weekdays: std_logic_vector(2 downto 0):= (others => '0');
signal cnt_sck: std_logic_vector(7 downto 0):= (others => '0'); --400KHZ
signal cnt: std_logic_vector(8 downto 0):= (others => '0'); --start mode rtc_sda falling edge is 0.3us
signal i: std_logic_vector(3 downto 0):= (others => '0');
--variable i:integer range 0 to 127:= 0;
--variable ii:integer range 0 to 127:= 0;
signal ii: std_logic_vector(3 downto 0):= (others => '0');
signal rtc_scl_buf: std_logic:= '0';
signal rtc_sda_in: std_logic:= '0';
signal rtc_sda_out: std_logic:= '0';
signal cnt_start: std_logic_vector(5 downto 0):= (others => '0');
signal cnt_stop: std_logic_vector(5 downto 0):= (others => '0');
signal first: std_logic:= '0';
signal bit_cnt: std_logic_vector(2 downto 0):= "111";
signal cnt_wait: std_logic_vector(7 downto 0):= "00000000";
signal rtc_sda_in_buf1: std_logic:= '0';
signal rtc_sda_in_buf2: std_logic:= '0';
signal cnt_int: std_logic_vector(7 downto 0):= (others => '0');
signal rtc_int_buf: std_logic:= '0';
signal rtc_sda_en: std_logic:= '0'; -- receive word is useful
begin
rtc_scl <= rtc_scl_buf;
rtc_sda <= rtc_sda_out when tran_en = '1' or pstate2 = stop or (pstate2 = wait_2sck and rec_en = '1')else 'Z' ; --transmit mode or stop mode
rtc_sda_in <= rtc_sda;
rtc_int_buf <= rtc_int;
cnt_int <= cnt_int + '1'when rtc_int_buf = '1' and rtc_int = '0' else cnt_int; --falling edge
process(SYSCLK,nRST)
begin
if nRST = '0' then
data_tran <= (others => '0');
tran_en <= '0';
rec_en <= '0';
stop_en <= '0';
start_en <= '0';
elsif rising_edge(SYSCLK) then
case pstate1 is
when idle =>
if poweron = '0' then
--pstate1 <= set_reg;
pstate1 <= read_time;
first <= '0';
else
pstate1 <= idle;
end if;
when set_reg =>
pstate1 <= set_time;
first <= '0'; --jijun
when set_time =>
if cnt_rtc_scl = 18 and cnt_sck >= 31 then
if first = '0' then --jijun
first <= '1';
cnt_data <= (others => '0');
rec_en <= '0'; --receive disable
tran_en <= '1'; --transmit I2C rtc_sda enable
else
cnt_data <= cnt_data + '1';
if cnt_data >= 9 then
cnt_data <= (others => '0');
pstate1 <= read_time;
stop_en <= '0';
first <= '0';
else
pstate1 <= set_time;
end if;
end if;
end if;
if cnt_rtc_scl = 18 and cnt_sck >= 31 and first = '1'then
case cnt_data is
when X"00" =>
data_tran <= X"A2"; --write
tran_en <= '1';
stop_en <= '0';
start_en <= '1';
when X"01" =>
data_tran <= X"02"; --second address
start_en <= '0';
when X"02" =>
data_tran <= X"01"; --second
when X"03" =>
data_tran <= X"01"; --min
when X"04" =>
data_tran <= X"15"; --hour
when X"05" =>
data_tran <= X"11"; --days
when X"06" =>
data_tran <= X"05"; --weekdays
when X"07" =>
data_tran <= X"07"; --months
when X"08" =>
data_tran <= X"0f"; --years
-- when X"09" =>
-- data_tran <= X"1d"; --alarm_min = 59 ; enable minute alarm
if pstate2 = stop then
stop_en <= '0';
cnt_data <= cnt_data + '1';
tran_en <= '0';
else
stop_en <= '1'; --stop mode
end if;
when others =>
stop_en <= '0';
start_en <= '0';
end case;
elsif pstate2 = stop then
stop_en <= '0';
end if;
when read_time =>
if cnt_rtc_scl = 18 and cnt_sck >= 31 then
if first = '0' then --base
first <= '1';
cnt_data <= (others => '0');
rec_en <= '1'; --receive disable
tran_en <= '0'; --transmit I2C rtc_sda enable
else
cnt_data <= cnt_data + '1';
if cnt_data >= 13 then
cnt_data <= (others => '0');
pstate1 <= idle;
stop_en <= '0';
else
pstate1 <= read_time;
end if;
end if;
end if;
-- if cnt_rtc_scl = 18 and cnt_sck >= 31 then --18
-- cnt_data <= cnt_data + '1';
-- end if;
-- if cnt_data >= 12 then
-- if cnt_rtc_scl = 18 then --useful next byte
-- cnt_data <= (others => '0');
-- pstate1 <= idle;
-- stop_en <= '0';
-- end if;
-- else
-- pstate1 <= read_time;
-- end if;
if cnt_rtc_scl = 18 and cnt_sck >= 31 and first = '1'then
case cnt_data is
when X"00" =>
data_tran <= X"A2"; --write
start_en <= '1';
tran_en <= '1';
rec_en <= '0';
when X"01" =>
data_tran <= X"02"; --second address
start_en <= '0';
when X"02" =>
data_tran <= X"A3"; --read
start_en <= '1';
tran_en <= '1';
when X"03" =>
start_en <= '0';
tran_en <= '0';
rec_en <= '1';
when X"04" =>
--second <= data_rec(5 downto 0); --test
when X"05" =>
--second <= data_rec(5 downto 0); --test
when X"06" =>
--second <= data_rec(5 downto 0);
when X"07" =>
--min <= data_rec(5 downto 0);
when X"08" =>
--hour <= data_rec(4 downto 0); --02H
when X"09" =>
--days <= data_rec(4 downto 0);
when X"0a" =>
--weekdays <= data_rec(2 downto 0);
when X"0b" =>
--months <= data_rec(3 downto 0);
when X"0c" =>
--years <= data_rec(6 downto 0);
if pstate2 = stop then
stop_en <= '0';
-- if cnt_rtc_scl = 18 then --useful next byte
cnt_data <= cnt_data + '1';
-- end if;
else
stop_en <= '1'; --stop mode
end if;
rec_en <= '0';
when others =>
stop_en <= '0';
end case;
elsif pstate2 = stop then
stop_en <= '0';
end if;
if rtc_sda_en = '1' then
case cnt_data is
when X"04" =>
--second <= data_rec(5 downto 0); --test
when X"05" =>
--second <= data_rec(5 downto 0); --test
when X"06" =>
second <= data_rec(5 downto 0);
when X"07" =>
min <= data_rec(5 downto 0);
when X"08" =>
hour <= data_rec(4 downto 0); --02H
when X"09" =>
days <= data_rec(4 downto 0);
when X"0a" =>
weekdays <= data_rec(2 downto 0);
when X"0b" =>
months <= data_rec(3 downto 0);
when X"0c" =>
years <= data_rec(6 downto 0);
when others =>
alarm_min <= data_rec(5 downto 0); --test
end case;
end if;
when others =>
pstate1 <= idle;
end case;
end if;
end process;
process(SYSCLK,nRST) --generate rtc_sda
begin
if nRST = '0' then
cnt_start <= (others => '0');
cnt_stop <= (others => '0');
i <= (others => '0');
bit_cnt <= "111";
rtc_sda_en <= '0';
elsif rising_edge(SYSCLK) then
rtc_sda_in_buf1 <= rtc_sda_in;
rtc_sda_in_buf2 <= rtc_sda_in_buf1;
case pstate2 is
when idle =>
if start_en = '1' then
if rtc_scl_buf = '0' then --Time interval can't be too long from start to tran
pstate2 <= start;
else
pstate2 <= idle;
end if;
elsif stop_en = '1' then
pstate2 <= stop;
end if;
when start => --falling edge
clk_en <= '0';
if rtc_scl_buf = '1' then
cnt_start <= cnt_start + '1';
if cnt_start < 16 then
rtc_sda_out <= '1';
elsif cnt_start < 31 then
rtc_sda_out <= '0';
elsif cnt_start = 31 then
if tran_en = '1' then
pstate2 <= tran;
elsif rec_en = '1' then
pstate2 <= recv;
end if;
cnt_start <= (others => '0');
i <= (others => '0');
end if;
end if;
when tran =>
clk_en <= '1';
if rtc_scl_buf = '0' and cnt_sck = 16 then --the mid of low level
bit_cnt <= bit_cnt - '1';
rtc_sda_out <= data_tran(conv_integer(bit_cnt));
if bit_cnt = "000" then
pstate2 <= wait_2sck;
end if;
else
pstate2 <= tran;
end if;
when wait_2sck =>
clk_en <= '1';
if cnt_wait = 62 then
if rec_en = '1' then
rtc_sda_out <= '0'; --acknowledge of master
rtc_sda_en <= '1';
-- elsif tran_en = '1' then --why why
-- rtc_sda_out <= 'Z';
-- else
-- rtc_sda_out <= '1';
end if;
end if;
if cnt_wait = 124 then
if stop_en = '1' then
pstate2 <= stop;
elsif start_en = '1' then
pstate2 <= start;
elsif tran_en = '1' then
pstate2 <= tran;
elsif rec_en = '1' then
pstate2 <= recv;
rtc_sda_en <= '0';
end if;
cnt_wait <= (others => '0');
else
pstate2 <= wait_2sck;
cnt_wait <= cnt_wait + '1';
end if;
when recv =>
clk_en <= '1';
if rtc_scl_buf = '1' and cnt_sck = 16 then -- the mid of high level
bit_cnt <= bit_cnt - '1';
data_rec(conv_integer(bit_cnt)) <= rtc_sda_in_buf2;
if bit_cnt = "000" then
pstate2 <= wait_2sck;
end if;
end if;
when stop => --rising edge
if rtc_scl_buf = '1' then
cnt_start <= cnt_start + '1';
if cnt_start < 16 then
clk_en <= '0';
rtc_sda_out <= '0';
elsif cnt_start < 31 then
rtc_sda_out <= '1';
elsif cnt_start = 31 then
pstate2 <= idle;
clk_en <= '1';
--pstate2 <= recv;
cnt_start <= (others => '0');
end if;
end if;
when others =>
pstate2 <= idle;
end case;
end if;
end process;
process(SYSCLK,nRST)
begin
if nRST = '0' then
rtc_scl_buf <= '1';
cnt_sck <= (others => '0');
cnt_rtc_scl <= (others => '0');
elsif rising_edge(SYSCLK) then
--if clk_en = '1' then
if cnt_sck >= 31 then
rtc_scl_buf <= not rtc_scl_buf;
cnt_sck <= (others => '0');
if cnt_rtc_scl >= 18 then
cnt_rtc_scl <= (others => '0');
else
cnt_rtc_scl <= cnt_rtc_scl + '1';
end if;
else
rtc_scl_buf <= rtc_scl_buf;
cnt_sck <= cnt_sck + '1';
end if;
--else
-- rtc_scl_buf <= '1';
-- cnt_sck <= (others => '0');
--end if;
end if;
end process;
-- if div_cnt = CLK_DEVIDE_MAX then
-- div_cnt <= (others => '0');
-- bit_cnt <= bit_cnt - '1';
-- if bit_cnt = "000" then
-- pstate <= wait_2sck;
-- end if;
-- else
-- div_cnt <= div_cnt + '1';
-- end if;
-- if (div_cnt = CLK_RISING_CN) then
-- rtc_scl_buf <= '1';
-- elsif (div_cnt = CLK_FALING_CN) then
-- rtc_scl_buf <= '0';
-- end if;
end architecture;
加载中...
查看其它18个回答
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity rtc is
generic(
constant CLK_RISING_CN : std_logic_vector(5 downto 0):= "010000";
constant CLK_FALING_CN : std_logic_vector(5 downto 0):= "011111";
constant CLK_DEVIDE_MAX: std_logic_vector(5 downto 0):= "011111"
);
port(
nRST : IN STD_LOGIC;
SYSCLK : IN STD_LOGIC;
rtc_int : IN STD_LOGIC;
rtc_scl : OUT STD_LOGIC;
rtc_sda : INOUT STD_LOGIC;
poweron : IN STD_LOGIC);
end rtc;
architecture behav of rtc is
type state2 is (idle,start,tran,recv,wait_2sck,stop);
type state1 is (idle,set_reg,set_time,read_time);
signal pstate2: state2:= idle;
signal pstate1: state1:= idle;
signal data_tran: std_logic_vector(7 downto 0):= (others => '0');
signal data_rec: std_logic_vector(7 downto 0):= (others => '0');
signal tran_en: std_logic:= '0';
signal rec_en: std_logic:= '0';
signal clk_en: std_logic:= '0';
signal stop_en: std_logic:= '0';
signal start_en: std_logic:= '0';
signal cnt_rtc_scl: std_logic_vector(4 downto 0):= (others => '0'); --cnt_rtc_scl * rtc_scl_buf
signal cnt_data: std_logic_vector(7 downto 0):= (others => '0');
signal second: std_logic_vector(5 downto 0):= (others => '0');
signal min: std_logic_vector(5 downto 0):= (others => '0');
signal hour: std_logic_vector(4 downto 0):= (others => '0');
signal days: std_logic_vector(4 downto 0):= (others => '0');
signal weekdays: std_logic_vector(2 downto 0):= (others => '0');
signal months: std_logic_vector(3 downto 0):= (others => '0');
signal years: std_logic_vector(6 downto 0):= (others => '0');
signal centurys: std_logic_vector(6 downto 0):= (others => '0');
signal alarm_min: std_logic_vector(5 downto 0):= (others => '0');
signal alarm_hour: std_logic_vector(4 downto 0):= (others => '0');
signal alarm_days: std_logic_vector(4 downto 0):= (others => '0');
signal alarm_weekdays: std_logic_vector(2 downto 0):= (others => '0');
signal cnt_sck: std_logic_vector(7 downto 0):= (others => '0'); --400KHZ
signal cnt: std_logic_vector(8 downto 0):= (others => '0'); --start mode rtc_sda falling edge is 0.3us
signal i: std_logic_vector(3 downto 0):= (others => '0');
--variable i:integer range 0 to 127:= 0;
--variable ii:integer range 0 to 127:= 0;
signal ii: std_logic_vector(3 downto 0):= (others => '0');
signal rtc_scl_buf: std_logic:= '0';
signal rtc_sda_in: std_logic:= '0';
signal rtc_sda_out: std_logic:= '0';
signal cnt_start: std_logic_vector(5 downto 0):= (others => '0');
signal cnt_stop: std_logic_vector(5 downto 0):= (others => '0');
signal first: std_logic:= '0';
signal bit_cnt: std_logic_vector(2 downto 0):= "111";
signal cnt_wait: std_logic_vector(7 downto 0):= "00000000";
signal rtc_sda_in_buf1: std_logic:= '0';
signal rtc_sda_in_buf2: std_logic:= '0';
signal cnt_int: std_logic_vector(7 downto 0):= (others => '0');
signal rtc_int_buf: std_logic:= '0';
signal rtc_sda_en: std_logic:= '0'; -- receive word is useful
begin
rtc_scl <= rtc_scl_buf;
rtc_sda <= rtc_sda_out when tran_en = '1' or pstate2 = stop or (pstate2 = wait_2sck and rec_en = '1')else 'Z' ; --transmit mode or stop mode
rtc_sda_in <= rtc_sda;
rtc_int_buf <= rtc_int;
cnt_int <= cnt_int + '1'when rtc_int_buf = '1' and rtc_int = '0' else cnt_int; --falling edge
process(SYSCLK,nRST)
begin
if nRST = '0' then
data_tran <= (others => '0');
tran_en <= '0';
rec_en <= '0';
stop_en <= '0';
start_en <= '0';
elsif rising_edge(SYSCLK) then
case pstate1 is
when idle =>
if poweron = '0' then
--pstate1 <= set_reg;
pstate1 <= read_time;
first <= '0';
else
pstate1 <= idle;
end if;
when set_reg =>
pstate1 <= set_time;
first <= '0'; --jijun
when set_time =>
if cnt_rtc_scl = 18 and cnt_sck >= 31 then
if first = '0' then --jijun
first <= '1';
cnt_data <= (others => '0');
rec_en <= '0'; --receive disable
tran_en <= '1'; --transmit I2C rtc_sda enable
else
cnt_data <= cnt_data + '1';
if cnt_data >= 9 then
cnt_data <= (others => '0');
pstate1 <= read_time;
stop_en <= '0';
first <= '0';
else
pstate1 <= set_time;
end if;
end if;
end if;
if cnt_rtc_scl = 18 and cnt_sck >= 31 and first = '1'then
case cnt_data is
when X"00" =>
data_tran <= X"A2"; --write
tran_en <= '1';
stop_en <= '0';
start_en <= '1';
when X"01" =>
data_tran <= X"02"; --second address
start_en <= '0';
when X"02" =>
data_tran <= X"01"; --second
when X"03" =>
data_tran <= X"01"; --min
when X"04" =>
data_tran <= X"15"; --hour
when X"05" =>
data_tran <= X"11"; --days
when X"06" =>
data_tran <= X"05"; --weekdays
when X"07" =>
data_tran <= X"07"; --months
when X"08" =>
data_tran <= X"0f"; --years
-- when X"09" =>
-- data_tran <= X"1d"; --alarm_min = 59 ; enable minute alarm
if pstate2 = stop then
stop_en <= '0';
cnt_data <= cnt_data + '1';
tran_en <= '0';
else
stop_en <= '1'; --stop mode
end if;
when others =>
stop_en <= '0';
start_en <= '0';
end case;
elsif pstate2 = stop then
stop_en <= '0';
end if;
when read_time =>
if cnt_rtc_scl = 18 and cnt_sck >= 31 then
if first = '0' then --base
first <= '1';
cnt_data <= (others => '0');
rec_en <= '1'; --receive disable
tran_en <= '0'; --transmit I2C rtc_sda enable
else
cnt_data <= cnt_data + '1';
if cnt_data >= 13 then
cnt_data <= (others => '0');
pstate1 <= idle;
stop_en <= '0';
else
pstate1 <= read_time;
end if;
end if;
end if;
-- if cnt_rtc_scl = 18 and cnt_sck >= 31 then --18
-- cnt_data <= cnt_data + '1';
-- end if;
-- if cnt_data >= 12 then
-- if cnt_rtc_scl = 18 then --useful next byte
-- cnt_data <= (others => '0');
-- pstate1 <= idle;
-- stop_en <= '0';
-- end if;
-- else
-- pstate1 <= read_time;
-- end if;
if cnt_rtc_scl = 18 and cnt_sck >= 31 and first = '1'then
case cnt_data is
when X"00" =>
data_tran <= X"A2"; --write
start_en <= '1';
tran_en <= '1';
rec_en <= '0';
when X"01" =>
data_tran <= X"02"; --second address
start_en <= '0';
when X"02" =>
data_tran <= X"A3"; --read
start_en <= '1';
tran_en <= '1';
when X"03" =>
start_en <= '0';
tran_en <= '0';
rec_en <= '1';
when X"04" =>
--second <= data_rec(5 downto 0); --test
when X"05" =>
--second <= data_rec(5 downto 0); --test
when X"06" =>
--second <= data_rec(5 downto 0);
when X"07" =>
--min <= data_rec(5 downto 0);
when X"08" =>
--hour <= data_rec(4 downto 0); --02H
when X"09" =>
--days <= data_rec(4 downto 0);
when X"0a" =>
--weekdays <= data_rec(2 downto 0);
when X"0b" =>
--months <= data_rec(3 downto 0);
when X"0c" =>
--years <= data_rec(6 downto 0);
if pstate2 = stop then
stop_en <= '0';
-- if cnt_rtc_scl = 18 then --useful next byte
cnt_data <= cnt_data + '1';
-- end if;
else
stop_en <= '1'; --stop mode
end if;
rec_en <= '0';
when others =>
stop_en <= '0';
end case;
elsif pstate2 = stop then
stop_en <= '0';
end if;
if rtc_sda_en = '1' then
case cnt_data is
when X"04" =>
--second <= data_rec(5 downto 0); --test
when X"05" =>
--second <= data_rec(5 downto 0); --test
when X"06" =>
second <= data_rec(5 downto 0);
when X"07" =>
min <= data_rec(5 downto 0);
when X"08" =>
hour <= data_rec(4 downto 0); --02H
when X"09" =>
days <= data_rec(4 downto 0);
when X"0a" =>
weekdays <= data_rec(2 downto 0);
when X"0b" =>
months <= data_rec(3 downto 0);
when X"0c" =>
years <= data_rec(6 downto 0);
when others =>
alarm_min <= data_rec(5 downto 0); --test
end case;
end if;
when others =>
pstate1 <= idle;
end case;
end if;
end process;
process(SYSCLK,nRST) --generate rtc_sda
begin
if nRST = '0' then
cnt_start <= (others => '0');
cnt_stop <= (others => '0');
i <= (others => '0');
bit_cnt <= "111";
rtc_sda_en <= '0';
elsif rising_edge(SYSCLK) then
rtc_sda_in_buf1 <= rtc_sda_in;
rtc_sda_in_buf2 <= rtc_sda_in_buf1;
case pstate2 is
when idle =>
if start_en = '1' then
if rtc_scl_buf = '0' then --Time interval can't be too long from start to tran
pstate2 <= start;
else
pstate2 <= idle;
end if;
elsif stop_en = '1' then
pstate2 <= stop;
end if;
when start => --falling edge
clk_en <= '0';
if rtc_scl_buf = '1' then
cnt_start <= cnt_start + '1';
if cnt_start < 16 then
rtc_sda_out <= '1';
elsif cnt_start < 31 then
rtc_sda_out <= '0';
elsif cnt_start = 31 then
if tran_en = '1' then
pstate2 <= tran;
elsif rec_en = '1' then
pstate2 <= recv;
end if;
cnt_start <= (others => '0');
i <= (others => '0');
end if;
end if;
when tran =>
clk_en <= '1';
if rtc_scl_buf = '0' and cnt_sck = 16 then --the mid of low level
bit_cnt <= bit_cnt - '1';
rtc_sda_out <= data_tran(conv_integer(bit_cnt));
if bit_cnt = "000" then
pstate2 <= wait_2sck;
end if;
else
pstate2 <= tran;
end if;
when wait_2sck =>
clk_en <= '1';
if cnt_wait = 62 then
if rec_en = '1' then
rtc_sda_out <= '0'; --acknowledge of master
rtc_sda_en <= '1';
-- elsif tran_en = '1' then --why why
-- rtc_sda_out <= 'Z';
-- else
-- rtc_sda_out <= '1';
end if;
end if;
if cnt_wait = 124 then
if stop_en = '1' then
pstate2 <= stop;
elsif start_en = '1' then
pstate2 <= start;
elsif tran_en = '1' then
pstate2 <= tran;
elsif rec_en = '1' then
pstate2 <= recv;
rtc_sda_en <= '0';
end if;
cnt_wait <= (others => '0');
else
pstate2 <= wait_2sck;
cnt_wait <= cnt_wait + '1';
end if;
when recv =>
clk_en <= '1';
if rtc_scl_buf = '1' and cnt_sck = 16 then -- the mid of high level
bit_cnt <= bit_cnt - '1';
data_rec(conv_integer(bit_cnt)) <= rtc_sda_in_buf2;
if bit_cnt = "000" then
pstate2 <= wait_2sck;
end if;
end if;
when stop => --rising edge
if rtc_scl_buf = '1' then
cnt_start <= cnt_start + '1';
if cnt_start < 16 then
clk_en <= '0';
rtc_sda_out <= '0';
elsif cnt_start < 31 then
rtc_sda_out <= '1';
elsif cnt_start = 31 then
pstate2 <= idle;
clk_en <= '1';
--pstate2 <= recv;
cnt_start <= (others => '0');
end if;
end if;
when others =>
pstate2 <= idle;
end case;
end if;
end process;
process(SYSCLK,nRST)
begin
if nRST = '0' then
rtc_scl_buf <= '1';
cnt_sck <= (others => '0');
cnt_rtc_scl <= (others => '0');
elsif rising_edge(SYSCLK) then
--if clk_en = '1' then
if cnt_sck >= 31 then
rtc_scl_buf <= not rtc_scl_buf;
cnt_sck <= (others => '0');
if cnt_rtc_scl >= 18 then
cnt_rtc_scl <= (others => '0');
else
cnt_rtc_scl <= cnt_rtc_scl + '1';
end if;
else
rtc_scl_buf <= rtc_scl_buf;
cnt_sck <= cnt_sck + '1';
end if;
--else
-- rtc_scl_buf <= '1';
-- cnt_sck <= (others => '0');
--end if;
end if;
end process;
-- if div_cnt = CLK_DEVIDE_MAX then
-- div_cnt <= (others => '0');
-- bit_cnt <= bit_cnt - '1';
-- if bit_cnt = "000" then
-- pstate <= wait_2sck;
-- end if;
-- else
-- div_cnt <= div_cnt + '1';
-- end if;
-- if (div_cnt = CLK_RISING_CN) then
-- rtc_scl_buf <= '1';
-- elsif (div_cnt = CLK_FALING_CN) then
-- rtc_scl_buf <= '0';
-- end if;
end architecture;
一周热门 更多>