这个程序的寄存器读取时和STM32通讯的,之前有一个是和AVR通讯的,这个程序已经调试通过,原理比较简单,相信认真看的都能够明白。
因为ADS8364为差分AD,所以其输出为补码形式,按照2.5V的参考电压源输出的数据范围为-32768~+32768,如果AIN- 连到VREF(2.5V),那么当AIN+ 输入为0时 输出的数据为0x8000,如果AIN+ 输入为2.5V则输出数据为0x0000,AIN+ 输入为5V时输出数据位0x7F。程序如下:
--最后修改2011.3.26
--最后测试功能:
--利用第一块板子测试ADS8364
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
--------------------------------------------------------------------------------------
--此段定义系统的各信号线
--------------------------------------------------------------------------------------
entity ad is
port(
-- 系统信号线
clk: in std_logic;
led: out std_logic;
rst: in std_logic;
-- arm相连的信号线
adr_l: in std_logic_vector(7 downto 0); --a7...a0,只使用了低八位地址线
data: inout std_logic_vector(7 downto 0); --只使用了低八位数据线
fsmc_ne4: in std_logic;
fsmc_noe: in std_logic;
fsmc_nwe: in std_logic;
--ad8364信号线
adc_d: in std_logic_vector(15 downto 0);
adc_a0,adc_a1,adc_a2: out std_logic;
adc_reset: out std_logic;
adc_cs: out std_logic;
adc_wr: out std_logic;
adc_rd: out std_logic;
adc_holda,adc_holdb,adc_holdc: out std_logic;
adc_eoc: in std_logic;
adcclk_out: out std_logic
);
end entity;
--统一编址,地址线数据线为八位,每个地址数据宽度8位
--"00000001" ad0_h_data 0x01
--"00000010" ad0_l_data 0x02
--"00000011" ad1_h_data 0x03
--"00000100" ad1_l_data 0x04
--"00000101" led_ctrl 0x05
architecture art of ad is
--------------------------------------------------------------------------------------
--此段定义内部相应的寄存器和相应变量
--------------------------------------------------------------------------------------
--stm32读写相关信号
--设置存储数据的寄存器
signal ad0_h_data,ad0_l_data,ad1_h_data,ad1_l_data,led_ctrl: std_logic_vector(7 downto 0);
--数据缓冲寄存器
signal data_buf: std_logic_vector(7 downto 0);
--数据输出控制
signal data_outctl: std_logic;
--时钟分频相关变量
signal clkcnt : std_logic_vector(16 downto 0);
signal adc_clk : std_logic; --adc时钟信号
signal adc_data_buf : std_logic_vector(15 downto 0);
--定义读取过程的各个状态
--13位控制分别为 hold adc_a rd 状态机状态5位 hhhabcr
---------------------------------------------------98365
constant st0 :std_logic_vector(11 downto 0):="000000100000";--启动转换
constant st1 :std_logic_vector(11 downto 0):="111000100001";--进入17个周期等待转换结束,不检测EOC
constant st2 :std_logic_vector(11 downto 0):="111000100010";
constant st3 :std_logic_vector(11 downto 0):="111000100011";
constant st4 :std_logic_vector(11 downto 0):="111000100100";
constant st5 :std_logic_vector(11 downto 0):="111000100101";
constant st6 :std_logic_vector(11 downto 0):="111000100110";
constant st7 :std_logic_vector(11 downto 0):="111000100111";
constant st8 :std_logic_vector(11 downto 0):="111000101000";
constant st9 :std_logic_vector(11 downto 0):="111000101001";
constant st10 :std_logic_vector(11 downto 0):="111000101010";
constant st11 :std_logic_vector(11 downto 0):="111000101011";
constant st12 :std_logic_vector(11 downto 0):="111000101100";
constant st13 :std_logic_vector(11 downto 0):="111000101101";
constant st14 :std_logic_vector(11 downto 0):="111000101110";
constant st15 :std_logic_vector(11 downto 0):="111000101111";
constant st16 :std_logic_vector(11 downto 0):="111000110000";
constant st17 :std_logic_vector(11 downto 0):="111000110001";
constant st18 :std_logic_vector(11 downto 0):="111000110010";
constant st19 :std_logic_vector(11 downto 0):="111000010011";--读ch1数据
constant st20 :std_logic_vector(11 downto 0):="111001110100";
constant st21 :std_logic_vector(11 downto 0):="111001010101";--读ch2数据
constant st22 :std_logic_vector(11 downto 0):="111001110110";
signal state :std_logic_vector(11 downto 0);--用于状态跳转
signal readst :std_logic_vector(3 downto 0);--adc_a,在另一个进程中根据此信号 选择输出的数据
begin
------------------------------------------------时钟分频-------------------------------------------------------------------
process(rst,clk) is
begin
if rst='0' then
clkcnt <= "00000000000000000";
elsif(clk'event and clk = '1') then
if(clkcnt = "11111111111111111") then
clkcnt<= "00000000000000000";
else
clkcnt <= clkcnt+1;
end if;
end if;
end process;
--pwm_clk <= clkcnt(7); --分频pwm时钟
--led_clk <= clkcnt(16); --分频led时钟
led <= clkcnt(16); --分频led时钟
adc_clk <= clkcnt(3);
adcclk_out <= clkcnt(3);
--------------------------------------------------------------------------------------
--stm32读写程序
--根据stm32读写时序图和信号线设计,实际上并没有使用全部信号线
--------------------------------------------------------------------------------------
--当读取cpld数据时用来判断何时向总线上输出数据
data_outctl <= (not fsmc_ne4) and (not fsmc_noe) and (fsmc_nwe);
data <= data_buf when (data_outctl='1') else "ZZZZZZZZ";--向数据线输出数据,否则保持为高阻态
-- 写操作,模式1,时序图在数据手册p331
process(rst,fsmc_ne4,fsmc_nwe,adr_l,fsmc_noe) is
begin
if rst='0' then
elsif(fsmc_nwe'event and fsmc_nwe='1') then
if((fsmc_noe and (not fsmc_ne4))='1') then
case (adr_l) is
when "00000001" => --对应的地址
when "00000010" =>
when "00000011" =>
when "00000100" =>
when "00000101" =>
when others =>
end case;
end if;
end if;
end process;
--读操作,模式1,p331
process(rst,fsmc_ne4,fsmc_nwe,adr_l,fsmc_noe) is
begin
if rst= '0' then
data_buf<="00000000";
elsif(fsmc_noe='0' and fsmc_noe'event) then --直接在noe的下降沿更新数据
case (adr_l) is
when "00000001" =>
data_buf <= ad0_h_data; --0x01
when "00000010" =>
data_buf <= ad0_l_data; --0x02
when "00000011" =>
data_buf <= ad1_h_data; --0x03
when "00000100" =>
data_buf <= ad1_l_data; --0x04
when "00000101" =>
data_buf <= "11001100"; --0x05
when others => data_buf <= "ZZZZZZZZ";
end case;
end if;
end process;
--------------------------------------ads8364------------------------------------
--ads8364控制,默认byte=0,add=0
adc_cs <= '0'; --片选一直选中
adc_wr <= '1';
--ads状态转移
process(adc_clk,rst)
begin
if(rst='0') then
state<=st0;
adc_reset<='0';
adc_holda<='1';
adc_holdb<='1';
adc_holdc<='1';
elsif(adc_clk'event and adc_clk='1') then
adc_reset<='1';
case state is
when st0=> state<=st1;
when st1=> state<=st2;
when st2=> state<=st3;
when st3=> state<=st4;
when st4=> state<=st5;
when st5=> state<=st6;
when st6=> state<=st7;
when st7=> state<=st8;
when st8=> state<=st9;
when st9=> state<=st10;
when st10=> state<=st11;
when st11=> state<=st12;
when st12=> state<=st13;
when st13=> state<=st14;
when st14=> state<=st15;
when st15=> state<=st16;
when st16=> state<=st17;
when st17=> state<=st18;
when st18=> state<=st19;
when st19=> state<=st20;
when st20=> state<=st21;
when st21=> state<=st22;
when st22=> state<=st0;
when others=> state<=st0;
end case;
end if;
readst<=state(8 downto 5);
adc_holdc<=state(11);
adc_holdb<=state(10);
adc_holda<=state(9);
adc_a2<=state(8);
adc_a1<=state(7);
adc_a0<=state(6);
adc_rd<=state(5);
end process;
process(clk,adc_d)
begin
if(clk'event and clk='0')then
adc_data_buf(14 downto 0) <= adc_d(14 downto 0);
adc_data_buf(15) <= not adc_d(15);
if readst="0000" then
ad0_h_data <= adc_data_buf(15 downto 8);
ad0_l_data <= adc_data_buf(7 downto 0);
elsif readst="0010" then
ad1_h_data <= adc_data_buf(15 downto 8);
ad1_l_data <= adc_data_buf(7 downto 0);
end if;
end if;
end process;
end;