数码管扫描显示控制器实验报告

实验四数码管扫描显示控制器设计与实现

2011211208班  2011211055  4  于圣泽

一、      实验目的

1.        掌握VHDL语言的语法规范,掌握时序电路描述方法;

2.        掌握多个数码管动态扫描显示的原理及设计方法。

二、      实验原理

多个数码管动态扫描显示,是将所有数码管的相同段并联在一起,通过选通信号分时控制各个数码管的公共端,循环依次点亮多个数码管,利用人眼的视觉暂留现象,只要扫描的频率大于50Hz,将看不到闪烁现象。一个数码管要稳定显示要求显示频率大于50Hz,那么6个数码管则需要50×6=300Hz以上才能看到持续稳定点亮的现象。

cat1~cat6是数码管选通控制信号,分别对应于6个共阴极数码管的公共端,当catn=‘0’时,其对应的数码管被点亮。因此,通过控制cat1~cat6,就可以控制6个数码管循环依次点亮。

三、      实验内容

1.        用VHDL语言设计并实现六个数码管串行扫描电路,要求同时显示0、1、2、3、4、5这6个不同的数字图形到6个数码管上,仿真验证其功能,并下载到实验板测试。

2.        用VHDL语言设计并实现六个数码管滚动显示电路

(1)   循环左滚动,始终点亮6个数码管,左出右进。状态为:012345→123450→234501→3450123→450123→501234→012345

(2)   向左滚动,用全灭的数码管填充右边,直至全部变灭,然后再依次从右边一个一个地点亮。状态为:012345→12345X→2345XX→345XXX→45XXXX→5XXXXX→XXXXXX→XXXXX0→XXXX01→XXX012→XX0123→X01234→012345,其中‘X’表示数码管不显示。

四、      设计思路和过程

对50MHz时钟进行5000分频,得到10kHZ时钟scanclk。把scanclk作为6进制计数器的时钟,对计数器的状态进行译码,得到cat(5 downto 0)的选通脉冲。定义信号q(5 downto 0)作为各个二极管当前应该显示的输出数字,在cat(i)置0前将对应的q(i)通过decode()函数译码为a(6 downto 0)控制数码管a~g输出,实现数码管扫描。

对于实验内容2,对scanclk进行10000分频,得到1Hz时钟moveclk,把它作为控制数字变化的时钟,根据不同要求定时改变q(5 downto 0)的值,实现显示数字的变化。对于’X’不显示状态,通过定义decode(10)译码得“0000000”实现熄灭。

五、      VHDL程序

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

use ieee.std_logic_unsigned.all;

entity LED is

port(clk : in std_logic;

        ctrl : in std_logic_vector(2 downto 0);

        a : out std_logic_vector(6 downto 0);

        cat : out std_logic_vector(5 downto 0));

end LED;

architecture behave of LED is

function decode(i:integer) return std_logic_vector is  --  七段译码函数

       variable q : std_logic_vector(6 downto 0);

begin

       case i is

              when 0 => q := "1111110";

              when 1 => q := "0110000";

              when 2 => q := "1101101";

              when 3 => q := "1111001";

              when 4 => q := "0110011";

              when 5 => q := "1011011";

              when 6 => q := "1011111";

              when 7 => q := "1110000";

              when 8 => q := "1111111";

              when 9 => q := "1111011";

              when others => q := "0000000";

       end case;

       return q;

end decode;

signal scanclk: std_logic;

signal moveclk: std_logic;

type array_type1 is array (0 to 5) of integer range 0 to 10;

type array_type2 is array (0 to 11) of integer range 0 to 10;

signal q : array_type1 := (0,1,2,3,4,5);

begin

       p1:process(clk)                               --  分频比:5000

       variable temp : integer range 0 to 4999; 

       begin

              if (clk'event and clk = '1') then

                     if temp = 4999 then temp := 0;

                     else temp := temp+1;

                     end if;

                     if (temp = 4999) then scanclk <= '1';

                     else scanclk <= '0';

                     end if;

              end if;

       end process;

       p2:process(scanclk)                      --  产生选通脉冲和输出译码

       variable temp : integer range 0 to 10;

       begin

              if (scanclk'event and scanclk = '1') then

                     if temp = 5 then temp := 0;

                     else temp := temp+1;

                     end if;

                     cat <= "111111";

                     cat(temp) <= '0';

                     a <= decode(q(temp));

              end if;

       end process;

      

       p3:process(scanclk)                            --分频比:10000

       variable temp : integer range 0 to 9999; 

       begin

              if (scanclk'event and scanclk = '1') then

                     if temp = 9999 then temp := 0;

                     else temp := temp+1;

                     end if;

                     if (temp = 9999) then moveclk <= '1';

                     else moveclk <= '0';

                     end if;

              end if;

       end process;

      

       p5:process(moveclk)                          --  定时改变显示数字

       variable temp : integer range 0 to 10;

       variable q1 : array_type1 := (0,1,2,3,4,5);

       variable q2 : array_type1 := (0,1,2,3,4,5);

       variable q3 : array_type2 := (0,1,2,3,4,5,10,10,10,10,10,10);

       begin

              if (moveclk'event and moveclk ='1') then        --  ctrl控制模式

                     if ctrl = "010" then

                            temp := q2(0);

                            for i in 0 to 4 loop

                                   q2(i) := q2(i+1);

                            end loop;

                            q2(5) := temp;

                     elsif ctrl = "100" then

                            temp := q3(0);

                            for i in 0 to 10 loop

                                   q3(i) := q3(i+1);

                            end loop;

                            q3(11) := temp;

                     end if;

                    

                     if ctrl = "001" then

                            for i in 0 to 5 loop

                                   q(i) <= q1(i);

                            end loop;

                     elsif ctrl = "010" then

                            for i in 0 to 5 loop

                                   q(i) <= q2(i);

                            end loop;

                     elsif ctrl = "100" then

                            for i in 0 to 5 loop

                                   q(i) <= q3(i);

                            end loop;

                     end if;

              end if;

       end process;

end;

六、      仿真波形图

ctrl=’001’

ctrl=’010’

ctrl=’100’

七、      仿真波形分析

为了便于仿真,将scanclk分频比改成2,将moveclk分频比改成12

ctrl=’001’时,cat(i)=’0’,时a对应i的七段译码值;

ctrl=’010’时,黄色框内显示输出012345,绿色框内显示输出123450;

ctrl=’100’时,黄色框内显示输出2345XX,绿色框内显示输出345XXX。

八、      故障及问题分析

刚开始很迷茫,根本不知道如何下手写代码,后来将要实现的功能分解成一个一个小模块,通过不同的process得以完成了实验内容。在过程中还遇到了需要实时调用的decode,通过查书我学会了函数的编写规范,最终用函数实现了七段译码。总体来说有了之前三次VHDL的编程经验,完成这次实验并不困难,遇到的几个小问题也通过调试解决了。

九、      实验总结

四周的数电实验很快就结束了,期间通过老师的讲解和我自己的领悟,我了解了EDA技术和PLD开发工具Quartus II的基本使用方法,学会了通过原理图和VHDL语言设计、综合、仿真、下载程序,实现了一些简单功能,如计数器,也实现了一些稍微复杂但更实用的功能,如数码管扫描显示。四周实验在教会我这些技能的更教会了我如何思考和解决问题,同时也让我体会到了测试成功后油然而生的喜悦。虽然我知道目前我的水平还很肤浅,只是了解了EDA技术的表面,我很期待下学期的数电综合实验,也希望通过这两个学期的实验为未来继续学习打下坚实的基础。

 

第二篇:数码管显示驱动和键盘扫描控制器CH451初始化C语言程序

#include<reg52.h>

#define uchar unsigned char

#define uint unsigned int

#define ch451_rst 0x0201 //复位

#define ch451_lmov 0x0300 //设置移动方式-左移 #define ch451_lcyc 0x0301 //设置移动方式-左循 #define ch451_rmov 0x0302 //设置移动方式-右移 #define ch451_rcyc 0x0303 //设置移动方式-右循

#define ch451_soff 0x0400 //关显示、键盘、看门狗 #define ch451_son 0x0401 //开显示

#define ch451_dsp 0x0500 //设置默认显示方式 #define ch451_BCD 0x0580 //设置BCD译码方式 #define ch451_twinkle 0x0600 //设置闪烁控制

#define ch451_DIG0 0x0800 //数码管位0显示 #define ch451_DIG1 0x0900 //数码管位1显示 #define ch451_DIG2 0x0A00 //数码管位2显示 #define ch451_DIG3 0x0B00 //数码管位3显示 #define ch451_DIG4 0x0C00 //数码管位4显示 #define ch451_DIG5 0x0D00 //数码管位5显示 #define ch451_DIG6 0x0E00 //数码管位6显示 #define ch451_DIG7 0x0F00 //数码管位7显示

sbit ch451_load=P0^0;

sbit ch451_din =P0^1;

sbit ch451_dclk=P0^2;

const uchar DatCode[18]={0x3F,0x06,0x5B,0x4F,//0,1,2,3

0x66,0x6D,0x7D,0x07,//4,5,6,7

0x7F,0x6F,0x77,0x7C,//8,9,A,b

0x39,0x5E,0x79,0x71,//C,d,E,F

0x40,0x00};//-,全灭

const uint DigCode[8]={ch451_DIG0,ch451_DIG1,ch451_DIG2,ch451_DIG3,

ch451_DIG4,ch451_DIG5,ch451_DIG6,ch451_DIG7};

const uint

table[]={0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009};

void delay(uchar t)

{

uchar tt;

for(;t>0;t--)

for(tt=200;tt>0;tt--);

}

void long_delay(uchar t)

{

for(;t>0;t--)

delay(255);

}

void write_ch451(uint cmd)

{

uchar i;

ch451_load=0;

for(i=0;i<12;i++)

{

ch451_din=cmd&1; ch451_dclk=0;

cmd=cmd>>1;

ch451_dclk=1;

}

ch451_load=1;

}

void ch451_init()

{

ch451_din=0;

ch451_din=1;

write_ch451(ch451_rst);

write_ch451(0x0401); //开显示 }

void main()

{

uchar i;

uint temp=0x01;

ch451_init();

long_delay(5);

// } write_ch451(0x0c80); write_ch451(0x08ff); write_ch451(0x09ff); write_ch451(0x0aff); write_ch451(0x0bff); write_ch451(0x0cff); write_ch451(0x0dff); write_ch451(0x0eff); write_ch451(0x0fff); while(1) { /* for(i=0;i<8;i++) { write_ch451(DigCode[i]|table[i]); long_delay(2); } */ }

相关推荐