📄 xkcon.vhd
字号:
----------------文件信息--------------------------------------------------------------------------------
--文 件 名: xkcon.vhd(相控充电机控制板)
--创 建 人: 刘宝贵
--最后修改日期: 2005年11月17日
---------------------------------------------------------------------------------------------------------
--功 能 描 述: 本程序为相控充电机控制板上的CPLD内的程序,完成如下功能1.键盘扫描2.控制AD转换3.产生PWM信号
-- 与51系列CPU接口,接在51地址数据总线上,51单片机通过访问地址总线上的数据寄存器来控制CPLD
-- -----------------------------------------------------------------------------------------
-- |地址 | 读 | 写 |
-- -----------------------------------------------------------------------------------------
-- |10000000 |AD转换低8位值 |写PA口,低三位有一位为1则begin_ad = '1' |
-- -----------------------------------------------------------------------------------------
-- |10000001 |AD转换高5位值最高位为1则数据无效 |写PB口,液晶的数据总线 |
-- -----------------------------------------------------------------------------------------
-- |10000010 |按键值,大于15为无效按键 |写PWM低8位 |
-- -----------------------------------------------------------------------------------------
-- |10000011 |无效 |写PWM高4位 |
-- -----------------------------------------------------------------------------------------
-- |10000100 |无效 |写PE口,0:液晶被光制线,其它备用 |
---------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity xkcon is
port(
reset: in std_logic;------------------------单片机的复位引脚,为1时PWM输出最小值
clk8mhz:in std_logic;------------------------时钟输入
ale: in std_logic;------------------------单片机的地址锁存信号
rd: in std_logic;------------------------单片机的写信号
wr: in std_logic;------------------------单片机的读信号
databus:inout std_logic_vector (7 downto 0);----单片机的地址数据复用总线(P0口)
outpa: out std_logic_vector (7 downto 0);----CPLD扩展的并行输出口 0:VCCE1 1:VCCE3 2:VCCE2 3:422EN
----CPLD扩展的并行输出口 4:REL1E 5:REL1E 6:REL1E 7:REL1E
outpb: out std_logic_vector (7 downto 0);----CPLD扩展的并行输出口 本项目做为液晶的数据总线
outpe: out std_logic_vector (5 downto 0);----CPLD扩展的并行输出口 0:液晶被光制线,其它备用
keyin: in std_logic_vector (3 downto 0);----键盘接口:接受扫描
keyout: out std_logic_vector (3 downto 0);----键盘接口:输出扫描信号
cs12887:out std_logic;------------------------P0口输出地址小于128时选中12887,大于128时选中CPLD
lcdcs1: in std_logic;------------------------本项目使用128X64液晶,该液晶两条片选线互为反向用
lcdcs2: out std_logic;------------------------CPLD做反向器
a4052: out std_logic;------------------------隔离同相控制信号处理板的4052A引脚
b4052: out std_logic;------------------------隔离同相控制信号处理板的4052B引脚
adflag: in std_logic;------------------------信号处理板输出,输出0表示反向积分完成
pwm_pina:out std_logic;------------------------输出PWM信号:'1...1'时输出全为高电平'0...0'时输出全为低电平
pwm_pinb:out std_logic;------------------------与pwm_pina反向
t200khz: out std_logic-------------------------200hz频率输出信号,供测试用
);
end xkcon;
architecture bhv of xkcon is
type st_type is(st0,st1,st2,st3,st4);-------------------AD转换时所用的状态机
signal c_st:st_type;
signal internal_bus_in :std_logic_vector(7 downto 0);---读进程所用总线缓冲
signal port_no:std_logic_vector(2 downto 0);------------CPLD内部端口地址
signal count,pwm_count:std_logic_vector(11 downto 0);---count:当前PWM计数值,pwm_count:单片机设定的PWM值
signal cs: std_logic;-----------------------------------单片机P0口输出的地址总线最高位,1:选中CPLD,0:选中12887
signal clk2mhz:std_logic;-------------------------------2M时钟,用于PWM计数脉冲
signal clk200khz:std_logic;-----------------------------200K时钟,用于AD计数脉冲
signal begin_ad: std_logic;-----------------------------VCCE1或VCCE2或VCCE3的任意一位为高时begin_ad 变为1
signal count_ad:std_logic_vector(12 downto 0);----------AD转换所用计数器,最高位为1时数据溢出无效
signal key_pressed: std_logic;--------------------------是否有键按下1:无 0:有
signal scan_cnt: std_logic_vector(3 downto 0);----------键盘扫描计数值
begin
-----------------------------------------------------------------------------------------------------
lcdcs2<= not lcdcs1;
cs12887<= cs;
t200khz<= clk200khz;
-----------------------------------------------------------------------------------------------------
--键盘扫描进程
-----------------------------------------------------------------------------------------------------
scan_1:process(clk2mhz,clk200khz,key_pressed)
begin
if(clk2mhz'event and clk2mhz='1')then
if(clk200khz='1' and key_pressed = '1')then
scan_cnt<= scan_cnt+1;
end if;
end if;
end process;
keyout<="1110" when scan_cnt(3 downto 2) = "00" else
"1101" when scan_cnt(3 downto 2) = "01" else
"1011" when scan_cnt(3 downto 2) = "10" else
"0111";
key_pressed<=keyin(0)when scan_cnt(1 downto 0)= "00" else
keyin(1)when scan_cnt(1 downto 0)= "01" else
keyin(2)when scan_cnt(1 downto 0)= "10" else
keyin(3);
-----------------------------------------------------------------------------------------------------
--AD转换进程
-----------------------------------------------------------------------------------------------------
adconvert:process(clk200khz)
begin
if(clk200khz'event and clk200khz='1')then
case c_st is
when st0 =>----st0:等待AD转换命令当写PA口使VCCE1或VCCE2或VCCE3的某位为高时begin_ad 变为1转为状态2
a4052<='1';
b4052<='1';
if(begin_ad = '1')then
c_st <=st1;count_ad<=(others=>'0');
else
c_st <=st0;
end if;
when st1=>----st1:等待10ms,以使VCCE1或VCCE2或VCCE3信号稳定
count_ad<=count_ad+1;
a4052<='1';
b4052<='1';
if(count_ad(11) = '1')then
c_st <=st2;
count_ad(11)<='0';
else
c_st <=st1;
end if;
when st2=>----对基准源进行正向积分20ms
count_ad<=count_ad+1;
a4052<='1';
b4052<='0';
if(count_ad(12) = '1' ) then
c_st <=st3;
count_ad(12)<='0';
else
c_st <=st2;
end if;
when st3=>----对被测信号进行反向积分adflag为0时反向积分完成
a4052<='0';
b4052<='1';
if(adflag='0')then
c_st <=st4;
else
c_st <=st3;
if(count_ad(12) = '0' ) then
count_ad<=count_ad+1;
else
c_st <=st4;
end if;
end if;
when st4=>----等待CPU把VCCE1和VCCE2和VCCE3变为低
a4052<='1';
b4052<='1';
if(begin_ad = '0')then
c_st <=st0;
else
c_st <=st4;
end if;
when others =>----非正常状态处理
c_st <= st0;
end case;
end if;
end process;
-----------------------------------------------------------------------------------------------------
--分频器进程:将8Mhz的外部时钟分成2Mhz和200Khz的内部使用的时种
-----------------------------------------------------------------------------------------------------
divider:process(clk8mhz)
variable count_divider:std_logic_vector(4 downto 0);
begin
if(clk8mhz'event and clk8mhz='0') then
if(count_divider<"10011")then
count_divider:= count_divider + 1;
else
count_divider:=(others=>'0');
clk200khz<= not clk200khz;
end if;
clk2mhz <= count_divider(1);
end if;
end process;
-----------------------------------------------------------------------------------------------------
--地址锁存进程
-----------------------------------------------------------------------------------------------------
latch_address:process(ale)
begin
if ale'event and ale='0' then
port_no<= databus(2 downto 0);
cs <= databus(7);
end if;
end process;
-----------------------------------------------------------------------------------------------------
--CPU读进程
-----------------------------------------------------------------------------------------------------
cpu_read:process(rd,cs)
begin
if(cs='1' and rd='0')then
if (port_no="000")then internal_bus_in<=count_ad(7 downto 0);
elsif(port_no="001")then internal_bus_in(4 downto 0)<=count_ad(12 downto 8);
internal_bus_in(7 downto 5)<="000";
elsif(port_no="010")then internal_bus_in(3 downto 0)<=scan_cnt;
internal_bus_in(4)<=key_pressed;
internal_bus_in(7 downto 5)<="000";
else internal_bus_in<="ZZZZZZZZ";
end if;
else internal_bus_in<="ZZZZZZZZ";
end if;
databus<=internal_bus_in;
end process;
-----------------------------------------------------------------------------------------------------
--CPU写进程
-----------------------------------------------------------------------------------------------------
cpu_write:process(wr)
begin
if(wr'event and wr ='1')then
if (port_no="000" and cs='1')then outpa<=databus;
if( databus(0)='1' or databus(1)='1' or databus(2)='1' )then
begin_ad <= '1';
else
begin_ad <= '0';
end if;
elsif(port_no="001" and cs='1')then outpb<=databus;
elsif(port_no="010" and cs='1')then pwm_count( 7 downto 0)<=databus;
elsif(port_no="011" and cs='1')then pwm_count(11 downto 8)<=databus(3 downto 0);
elsif(port_no="100" and cs='1')then outpe(5 downto 0)<=databus(5 downto 0);
-- elsif(port_no="100" and cs='1')then outpe<=databus(6 downto 0);
end if;
end if;
end process;
-----------------------------------------------------------------------------------------------------
--PWM信号产生进程
-----------------------------------------------------------------------------------------------------
pwm:process(clk2mhz)
begin
if(reset='0')then
if(clk2mhz'event and clk2mhz ='0')then
count<=count + 1;
if(count<pwm_count)then
pwm_pina <= '1';
pwm_pinb <= '0';
else
pwm_pina <= '0';
pwm_pinb <= '1';
end if;
end if;
else
pwm_pina <= '0';
pwm_pinb <= '1';
end if;
end process;
end bhv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -