⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xkcon.vhd

📁 用VHDL语言写的程序实例
💻 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 + -