此程序作为我的网络存档之用,看的懂的话也欢迎参考。
--2011.7.7凌晨版本 --加入闭环控制 --原有程序大幅改写,去掉了部分编译警告 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity XTKZQ is port( rst,clk : in std_logic; --时钟和复位信号,复位信号由AVR初始化手动给出 --avr 读写相关信号线 ale,rd,wr : in std_logic; --地址锁存、读、写信号 ad : inout std_logic_vector(7 downto 0); --地址数据复用信号线 --LED指示灯 led1,led2 : out std_logic; --pwm pwm1,pwm2,pwm3,pwm4,pwm5,pwm6 : out 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; --放大增益控制,此处每一路AD设置了两级放大增益 sw11: out std_logic;--控制模拟开关,调节放大增益 sw12: out std_logic; sw21: out std_logic; sw22: out std_logic; sw31: out std_logic; sw32: out std_logic; sw41: out std_logic; sw42: out std_logic; sw51: out std_logic; sw52: out std_logic; sw61: out std_logic; sw62: out std_logic ); end XTKZQ; architecture art of XTKZQ is ------------------------------------------------全局信号定义------------------------------------------------------------------- --avr访问操作相关信号 signal adr : std_logic_vector(7 downto 0); --地址寄存器 signal data_buf : std_logic_vector(7 downto 0); signal data_outctl : std_logic; --pwm控制部分有三组变量,第一组是由avr写入,控制相应的占空比,这个是供调试使用 --第二组是自动pid控制使用的 --第三组是pwm计数使用的,根据pid_sw开关的设置决定读入第一组还是第二组的值 --pwm部分相关寄存器定义 寄存器暂时定义为8位 signal pwmfreq_reg : std_logic_vector(7 downto 0); signal pwmocr1_reg : std_logic_vector(7 downto 0); signal pwmocr2_reg : std_logic_vector(7 downto 0); signal pwmocr3_reg : std_logic_vector(7 downto 0); signal pwmocr4_reg : std_logic_vector(7 downto 0); signal pwmocr5_reg : std_logic_vector(7 downto 0); signal pwmocr6_reg : std_logic_vector(7 downto 0); --pwm部分PID调节中用到的相关变量 signal pwmfreq_pid : std_logic_vector(7 downto 0); signal pwmocr1_pid : std_logic_vector(7 downto 0); signal pwmocr2_pid : std_logic_vector(7 downto 0); signal pwmocr3_pid : std_logic_vector(7 downto 0); signal pwmocr4_pid : std_logic_vector(7 downto 0); signal pwmocr5_pid : std_logic_vector(7 downto 0); signal pwmocr6_pid : std_logic_vector(7 downto 0); --PWM计数用到的相关变量,这里定义为8位 signal pwm_cnt : std_logic_vector(7 downto 0); signal pwmfreq : std_logic_vector(7 downto 0); signal pwmocr1 : std_logic_vector(7 downto 0); signal pwmocr2 : std_logic_vector(7 downto 0); signal pwmocr3 : std_logic_vector(7 downto 0); signal pwmocr4 : std_logic_vector(7 downto 0); signal pwmocr5 : std_logic_vector(7 downto 0); signal pwmocr6 : std_logic_vector(7 downto 0); --自动闭环控制相关寄存器定义 signal pid_sw : std_logic_vector(7 downto 0); --闭环控制开关,此寄存器为0x01时开启自动闭环控制 --六个AD寄存器位,用于存放设定的AD值 signal adcset1h_reg,adcset1l_reg,adcset2h_reg,adcset2l_reg : std_logic_vector(7 downto 0); signal adcset3h_reg,adcset3l_reg,adcset4h_reg,adcset4l_reg : std_logic_vector(7 downto 0); signal adcset5h_reg,adcset5l_reg,adcset6h_reg,adcset6l_reg : std_logic_vector(7 downto 0); --时钟分频相关变量 signal clkcnt : std_logic_vector(16 downto 0); signal adc_clk : std_logic; --adc时钟信号 signal pwm_clk : std_logic; --pwm时钟信号 signal pid_clk : std_logic; --pid时钟信号,用于调节pid的反应速度 --led指示相关变量 signal led_clk : std_logic; --led时钟信 signal led1_cnt : std_logic_vector(7 downto 0); signal led2_cnt : std_logic_vector(7 downto 0); signal led1s : std_logic; signal led2s : std_logic; --ads8364信号 signal adcdata1h_reg,adcdata1l_reg,adcdata2h_reg,adcdata2l_reg : std_logic_vector(7 downto 0); signal adcdata3h_reg,adcdata3l_reg,adcdata4h_reg,adcdata4l_reg : std_logic_vector(7 downto 0); signal adcdata5h_reg,adcdata5l_reg,adcdata6h_reg,adcdata6l_reg : std_logic_vector(7 downto 0); 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):="111010110110"; constant st23 :std_logic_vector(11 downto 0):="111010010111";--读ch3数据 constant st24 :std_logic_vector(11 downto 0):="111011111000"; constant st25 :std_logic_vector(11 downto 0):="111011011001";--读ch4数据 constant st26 :std_logic_vector(11 downto 0):="111100111010"; constant st27 :std_logic_vector(11 downto 0):="111100011011";--读ch5数据 constant st28 :std_logic_vector(11 downto 0):="111101111100"; constant st29 :std_logic_vector(11 downto 0):="111101011101";--读ch6数据 constant st30 :std_logic_vector(11 downto 0):="111000111110"; signal adc1_datasum :std_logic_vector(22 downto 0);--对采样数据进行累加存储 signal adc2_datasum :std_logic_vector(22 downto 0); signal adc3_datasum :std_logic_vector(22 downto 0); signal adc4_datasum :std_logic_vector(22 downto 0); signal adc5_datasum :std_logic_vector(22 downto 0); signal adc6_datasum :std_logic_vector(22 downto 0); signal adcadd_cnt :std_logic_vector(7 downto 0);--累加次数统计 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(2); --2 8分频,8位计数的话PWM波频率为12KHZ led_clk <= clkcnt(15); --15 分频led时钟 adc_clk <= clkcnt(2); pid_clk <= clkcnt(13); --13 2^14=16384,频率为1525hz adcclk_out <= clkcnt(2);--2 8分频,ADC时钟速率为3.125MHz,22个ADC时钟采样一次数据则采样速度为142K ------------------------------------------------avr访问操作---------------------------------------------------------------- data_outctl <= (not ale) and (not rd) and (wr); ad <= data_buf when (data_outctl='1') else "ZZZZZZZZ"; --锁存avr地址数据 process(rst,ale) is begin if rst='0' then adr <= "00000000"; elsif(ale'event and ale='0') then --在ale信号的下降沿锁存地址数据 adr <= ad; end if; end process; -------------------------------------avr写数据----------------------------------- process(rst,wr,ale) is begin if rst='0' then --对各寄存器给定初值 pwmfreq_reg <= "11111111"; pwmocr1_reg <= "00000000"; pwmocr2_reg <= "00000000"; pwmocr3_reg <= "00000000"; pwmocr4_reg <= "00000000"; pwmocr5_reg <= "00000000"; pwmocr6_reg <= "00000000"; --自动控制设定寄存器初值 adcset1h_reg <= "10000000";-----------------------------------fangz adcset1l_reg <= "00000000"; adcset2h_reg <= "00000000"; adcset2l_reg <= "00000000"; adcset3h_reg <= "00000000"; adcset3l_reg <= "00000000"; adcset4h_reg <= "00000000"; adcset4l_reg <= "00000000"; adcset5h_reg <= "00000000"; adcset5l_reg <= "00000000"; adcset6h_reg <= "00000000"; adcset6l_reg <= "00000000"; pid_sw <= "00000000"; elsif (wr='1' and wr'event) then --在wr信号上升沿进行写操作 if ale = '0' then case adr is when "00010000" => pwmfreq_reg <= ad;--10 when "00010001" => pwmocr1_reg <= ad;--11 when "00010010" => pwmocr2_reg <= ad; when "00010011" => pwmocr3_reg <= ad; when "00010100" => pwmocr4_reg <= ad; when "00010101" => pwmocr5_reg <= ad; when "00010110" => pwmocr6_reg <= ad;--16 when "00100001" => adcset1h_reg <= ad;--21 when "00100010" => adcset1l_reg <= ad; when "00100011" => adcset2h_reg <= ad; when "00100100" => adcset2l_reg <= ad; when "00100101" => adcset3h_reg <= ad; when "00100110" => adcset3l_reg <= ad;--26 when "00100111" => adcset4h_reg <= ad;--27 when "00101000" => adcset4l_reg <= ad; when "00101001" => adcset5h_reg <= ad; when "00101010" => adcset5l_reg <= ad; when "00101011" => adcset6h_reg <= ad; when "00101100" => adcset6l_reg <= ad;--2C when "00101101" => pid_sw <= ad;--2D when others => pwmfreq_reg <= pwmfreq_reg; pwmocr1_reg <= pwmocr1_reg; pwmocr2_reg <= pwmocr2_reg; pwmocr3_reg <= pwmocr3_reg; pwmocr4_reg <= pwmocr4_reg; pwmocr5_reg <= pwmocr5_reg; pwmocr6_reg <= pwmocr6_reg; adcset1h_reg<= adcset1h_reg; adcset1l_reg<= adcset1l_reg; adcset2h_reg<= adcset2h_reg; adcset2l_reg<= adcset2l_reg; adcset3h_reg<= adcset3h_reg; adcset3l_reg<= adcset3l_reg; adcset4h_reg<= adcset4h_reg; adcset4l_reg<= adcset4l_reg; adcset5h_reg<= adcset5h_reg; adcset5l_reg<= adcset5l_reg; adcset6h_reg<= adcset6h_reg; adcset6l_reg<= adcset6l_reg; pid_sw <= pid_sw; end case; end if; end if; end process; ------------------------------------avr读数据------------------------------------- process(rst,rd,ale) is begin if rst='0' then data_buf<="00000000"; elsif (rd='0'and rd'event) then case adr is when "00000001" => data_buf <= adcdata1h_reg;--1 when "00000010" => data_buf <= adcdata1l_reg;--2 when "00000011" => data_buf <= adcdata2h_reg;--3 when "00000100" => data_buf <= adcdata2l_reg;--4 when "00000101" => data_buf <= adcdata3h_reg;--5 when "00000110" => data_buf <= adcdata3l_reg;--6 when "00000111" => data_buf <= adcdata4h_reg;--7 when "00001000" => data_buf <= adcdata4l_reg;--8 when "00001001" => data_buf <= adcdata5h_reg;--9 when "00001010" => data_buf <= adcdata5l_reg;--A when "00001011" => data_buf <= adcdata6h_reg;--B when "00001100" => data_buf <= adcdata6l_reg;--C when "00010000" => data_buf <= adcset1h_reg; when "00010001" => data_buf <= adcset1l_reg; when others => data_buf <= "ZZZZZZZZ"; end case; end if; end process; ------------------------------------led指示------------------------------------- process(led_clk)is begin if(led_clk'event and led_clk='1') then led1_cnt <= led1_cnt+1; if (led1_cnt >= pwmocr1) then led1s <= not led1s; led1_cnt <="00000000"; end if; end if; end process; led1<=led1s; process(led_clk)is begin if(led_clk'event and led_clk='1') then led2_cnt <= led2_cnt+1; if (led2_cnt >= pwmocr2) then led2s <= not led2s; led2_cnt <="00000000"; end if; end if; end process; led2<=led2s; --------------------------------------pwm--------------------------------------- process(pwm_clk,rst) is begin if rst='0' then pwm_cnt<="00000000"; sw11<= '0'; sw12<= '0'; sw21<= '0'; sw22<= '0'; sw31<= '0'; sw32<= '0'; sw41<= '0'; sw42<= '0'; sw51<= '0'; sw52<= '0'; sw61<= '0'; sw62<= '0'; elsif(pwm_clk'event and pwm_clk='1') then if(pid_sw="00000001") then--如果pid控制寄存器开启,则pwm计数使用pid的调节量 pwmocr1<=pwmocr1_pid; pwmocr2<=pwmocr2_pid; pwmocr3<=pwmocr3_pid; pwmocr4<=pwmocr4_pid; pwmocr5<=pwmocr5_pid; pwmocr6<=pwmocr6_pid; else--否则使用外部给定的量 pwmocr1<=pwmocr1_reg; pwmocr2<=pwmocr2_reg; pwmocr3<=pwmocr3_reg; pwmocr4<=pwmocr4_reg; pwmocr5<=pwmocr5_reg; pwmocr6<=pwmocr6_reg; end if; if(pwm_cnt >=pwmfreq_reg) then pwm_cnt <= "00000000"; else pwm_cnt<=pwm_cnt+1; end if; --数据比较模块 这里设计的所有通道频率一致 --第一通道 if(pwm_cnt>= pwmocr1) then pwm1<= '1'; else pwm1<= '0'; end if; --第二通道 if(pwm_cnt>= pwmocr2) then pwm2<= '1'; else pwm2<= '0'; end if; --第三通道 if(pwm_cnt>= pwmocr3) then pwm3<= '1'; else pwm3<= '0'; end if; --第四通道 if(pwm_cnt>= pwmocr4) then pwm4<= '1'; else pwm4<= '0'; end if; --第五通道 if(pwm_cnt>= pwmocr5) then pwm5<= '1'; else pwm5<= '0'; end if; --第六通道 if(pwm_cnt>= pwmocr6) then pwm6<= '1'; else pwm6<= '0'; end if; --可编程增益放大 --此处是根据占空比自动调节放大增益,可以根据实际测量参数改变临界点的值 sw11<= '1'; sw12<= '0'; sw21<= '1'; sw22<= '0'; sw31<= '1'; sw32<= '0'; sw41<= '1'; sw42<= '0'; sw51<= '1'; sw52<= '0'; sw61<= '1'; sw62<= '0'; end if; end process; --------------------------------------ads8364------------------------------------ --ads8364控制,默认byte=0,add=0 adc_cs <= '0'; --片选一直选中 adc_wr <= '1'; --ads状态转移 process(adc_clk,rst,state) 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<=st23; when st23=> state<=st24; when st24=> state<=st25; when st25=> state<=st26; when st26=> state<=st27; when st27=> state<=st28; when st28=> state<=st29; when st29=> state<=st30; when st30=> 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; adc_data_buf(14 downto 0) <= adc_d(14 downto 0);--ADC输出为补码形式,转换为单端输入的原码 adc_data_buf(15) <= not adc_d(15); --------------------------------------求平均------------------------------------ process(rst,adc_clk,pwm_clk,adc_d,pwm_cnt) begin if(rst='0')then adc1_datasum<="00000000000000000000000"; adc2_datasum<="00000000000000000000000"; adc3_datasum<="00000000000000000000000"; adc4_datasum<="00000000000000000000000"; adc5_datasum<="00000000000000000000000"; adc6_datasum<="00000000000000000000000"; adcadd_cnt<="00000000"; elsif(adc_clk'event and adc_clk='0')then if readst="0000" then adc1_datasum <= adc1_datasum + adc_data_buf; adcadd_cnt <= adcadd_cnt + '1';--一次读取状态只需要计数一次 elsif readst="0010" then adc2_datasum <= adc2_datasum + adc_data_buf; elsif readst="0100" then adc3_datasum <= adc3_datasum + adc_data_buf; elsif readst="0110" then adc4_datasum <= adc4_datasum + adc_data_buf; elsif readst="1000" then adc5_datasum <= adc5_datasum + adc_data_buf; elsif readst="1010" then adc6_datasum <= adc6_datasum + adc_data_buf; end if; if(adcadd_cnt >= "01111111") then adcdata1h_reg <= adc1_datasum(22 downto 15); adcdata1l_reg <= adc1_datasum(14 downto 7); adcdata2h_reg <= adc2_datasum(22 downto 15); adcdata2l_reg <= adc2_datasum(14 downto 7); adcdata3h_reg <= adc3_datasum(22 downto 15); adcdata3l_reg <= adc3_datasum(14 downto 7); adcdata4h_reg <= adc4_datasum(22 downto 15); adcdata4l_reg <= adc4_datasum(14 downto 7); adcdata5h_reg <= adc5_datasum(22 downto 15); adcdata5l_reg <= adc5_datasum(14 downto 7); adcdata6h_reg <= adc6_datasum(22 downto 15); adcdata6l_reg <= adc6_datasum(14 downto 7); adc1_datasum<="00000000000000000000000"; adc2_datasum<="00000000000000000000000"; adc3_datasum<="00000000000000000000000"; adc4_datasum<="00000000000000000000000"; adc5_datasum<="00000000000000000000000"; adc6_datasum<="00000000000000000000000"; adcadd_cnt <= "00000000"; end if; end if; end process; --------------------------------------闭环控制------------------------------------ process(rst,pid_clk,pid_sw,adcset1h_reg,adcset1l_reg,adcset2h_reg,adcset2l_reg,adcset3h_reg,adcset3l_reg, adcset4h_reg,adcset4l_reg,adcset5h_reg,adcset5l_reg,adcset6h_reg,adcset6l_reg) begin if(rst='0')then pwmocr1_pid<="00000000"; pwmocr2_pid<="00000000"; pwmocr3_pid<="00000000"; pwmocr4_pid<="00000000"; pwmocr5_pid<="00000000"; pwmocr6_pid<="00000000"; elsif(pid_clk'event and pid_clk='0')then if(pid_sw="00000001")then--如果PID自动控制标志位开启 --第1通道闭环控制 if(adcset1h_reg>adcdata1h_reg) then --这里只比较高八位,留有一定的死区,避免频繁调节 pwmocr1_pid <= pwmocr1_pid + '1'; --采样值小于设定值,增加占空比 elsif(adcset1h_reg<adcdata1h_reg) then pwmocr1_pid <= pwmocr1_pid - '1'; --否则减小占空比 end if; --第2通道闭环控制 if(adcset2h_reg>adcdata2h_reg) then pwmocr2_pid <= pwmocr2_pid + '1'; elsif(adcset2h_reg<adcdata2h_reg) then pwmocr2_pid <= pwmocr2_pid - '1'; end if; --第3通道闭环控制 if(adcset3h_reg>adcdata3h_reg) then pwmocr3_pid <= pwmocr3_pid + '1'; elsif(adcset3h_reg<adcdata3h_reg) then pwmocr3_pid <= pwmocr3_pid - '1'; end if; --第4通道闭环控制 if(adcset4h_reg>adcdata4h_reg) then pwmocr4_pid <= pwmocr4_pid + '1'; elsif(adcset4h_reg<adcdata4h_reg) then pwmocr4_pid <= pwmocr4_pid - '1'; end if; --第5通道闭环控制 if(adcset5h_reg>adcdata5h_reg) then pwmocr5_pid <= pwmocr5_pid + '1'; elsif(adcset5h_reg<adcdata5h_reg) then pwmocr5_pid <= pwmocr5_pid - '1'; end if; --第6通道闭环控制 if(adcset6h_reg>adcdata6h_reg) then pwmocr6_pid <= pwmocr6_pid + '1'; elsif(adcset6h_reg<adcdata6h_reg) then pwmocr6_pid <= pwmocr6_pid - '1'; end if; --加入一个比较,防止在自动调整的时候数据溢出 if(pwmocr1_pid>"11111110") then pwmocr1_pid <="11111110"; elsif(pwmocr1_pid<"00000001") then pwmocr1_pid <="00000001"; end if; if(pwmocr2_pid>"11111110") then pwmocr2_pid <="11111110"; elsif(pwmocr2_pid<"00000001") then pwmocr2_pid <="00000001"; end if; if(pwmocr3_pid>"11111110") then pwmocr3_pid <="11111110"; elsif(pwmocr3_pid<"00000001") then pwmocr3_pid <="00000001"; end if; if(pwmocr4_pid>"11111110") then pwmocr4_pid <="11111110"; elsif(pwmocr4_pid<"00000001") then pwmocr4_pid <="00000001"; end if; if(pwmocr5_pid>"11111110") then pwmocr5_pid <="11111110"; elsif(pwmocr5_pid<"00000001") then pwmocr5_pid <="00000001"; end if; if(pwmocr6_pid>"11111110") then pwmocr6_pid <="11111110"; elsif(pwmocr6_pid<"00000001") then pwmocr6_pid <="00000001"; end if; end if; end if; end process; end;