基于FPGA的UART串口通信实验(VHDL语言实现)
一、前言:
最近在做UART串口通信的相关实验时,在网上查了很多资料,发现网上的大部分文章只注重理论,不注重代码,很多代码有错误不说,而且难以理解。故在完成此实验后,起了写一篇博客的心思,以供有想做相关实验且基础比较薄弱的朋友参阅。
二、实验要求:
(1)实现和 PC 双向通信
(2)可通过 FPGA 的键盘扫描,在开发板上设置控制参数,输入发送内容
(3)通信波特率可调
(4)LCD 液晶屏实现菜单、接收到的数据显示
注:关于UART串口通信实验的相关理论网上很多,而且都很详细,我在这里都不赘余了,我的重点是代码及其分析。本次使用到的FPGA开发板为: Cyclone Ⅱ EP2C5Q208C8 核心的MAGIC3200_EP2C5 开发板。
三、引脚分配:
四、代码及其分析:
注:此处代码有两个文件,一个是主文件,另外一个是按键消抖文件。
先上按键消抖文件,此处代码比较好理解。
------------------------------------------------按键消抖文件---------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity key5 is --按键防抖动
port(
CLK,RESET: in std_logic; --时钟以及有效位
din: in std_logic; --是按键,可能与防抖动有关!
dout: out std_logic --'0'有效
);
end key5;
architecture Behavioral of key5 is
signal count : integer range 0 to 3000000 ; --分频器
signal keyclk : std_logic ; --分频器
type state is(s0,s1); --定义两种状态
signal pre_s,next_s:state; --状态机指针
begin
process(CLK,RESET) --时钟进程,产生各种时钟信号
begin
if RESET='0' then keyclk<='0';count<=0;
elsif CLK'event and CLK='1' then
count<=count+1;
if count=3000000 then keyclk<=not keyclk; count<=0;
else count<=count+1;
end if;
end if; --毫秒时钟
end process;
process(keyclk,RESET) --状态机激励源
begin
if RESET='0' then pre_s<=s0;
elsif keyclk'event and keyclk='1' then pre_s<=next_s;
else null;
end if;
end process;
process(pre_s,next_s,din) --
begin
case pre_s is
when s0=>
dout<='1';
if din='0' then next_s<=s1; --检测到按键
else next_s<=s0;
end if;
when s1=>
dout<='1';
if din='0' then dout<='0'; --检测到按键
else next_s<=s0;
end if;
when others => next_s<=s0;
end case;
end process;
end Behavioral;
------------------------------------------------按键消抖文件---------------------------------------------------------
下面是主程序文件,我们重点来分析这一块。
------------------------------------------------主程序文件-----------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity RS232 is
port
(
RESET : in std_logic; --复位信号
CLK : in std_logic; --时钟输入,50MHZ
KeyIn : in std_logic_vector(3 downto 0); --column列电平
KeyOut : out std_logic_vector(3 downto 0); --row行电平
JX : in std_logic; --改变波特率(键盘上X、Y、Z三个键分别对应波特率9600、19200、38400)
KEYA : in std_logic;
UART0_RX : in std_logic;
UART0_TX : out std_logic;
LCD_RESET : out std_logic ;
LCD_RW : out std_logic ;
LCD_RS : out std_logic ;
LCD_E : out std_logic ;
LCD_D : buffer std_logic_vector ( 7 downto 0)
);
end RS232;
architecture Behavioral of RS232 is --此处代码均和LCD显示屏字符设置有关
type states is ( set ,clr ,set_d ,open1,set_addr,set_ddrom1,
set_ddrom2,set_ddrom3,set_ddrom4,set_ddrom5,set_1,
set_ddrom6,set_ddrom7,set_ddrom8,set_ddrom9,set_ddrom10,
set_ddrom11,set_ddrom12,set_ddrom13,s1,s2,
set_addrh4,set_ddrom1h4,
set_ddrom2h4,set_ddrom3h4,set_ddrom4h4,set_ddrom5h4,set_1h4,
set_ddrom6h4,set_ddrom7h4,set_ddrom8h4);
signal current_state : states :=set ;
Signal timecnt : integer range 0 to 100000; --分频计数器,用来得到10ms时钟
Signal time10ms : std_logic ; --10ms时钟
Signal scanvalue : std_logic_vector(3 downto 0);--记录扫描数据
Signal combvalue : std_logic_vector(7 downto 0);--KeyIn、KeyOut组合值
Signal cpy_scanvalue : std_logic_vector(3 downto 0);--备份扫描数据
Signal JX : std_logic_vector(2 downto 0);
Signal Data00 : std_logic_vector(9 downto 0);
Signal Clock9600 : std_logic; --9600波特率时钟,发送
Signal Clock3 : std_logic; --9600三倍频采样时钟,用于接收采用
Signal Send_data : std_logic_vector(9 downto 0); --发送寄存器
Signal Send_en : std_logic; --串口发送使能,0有效
Signal Send_over : std_logic; --串口发送完成,0有效
Signal Rx_Hold : std_logic; --串口接收到起始位标志
Signal Rx_Valid : std_logic; --标志接收到一字节有效数据
Signal Rx_Data : std_logic_vector(7 downto 0); --接收寄存器
Signal Data1 : std_logic_vector(3 downto 0);
Signal Data2 : std_logic_vector(3 downto 0);
Signal count : integer range 0 to 100000 ; --分频器,产生毫秒时钟基准
Signal dout : std_logic; --A键
Signal clkcnt : std_logic_vector(13 downto 0);
Signal LCD_Clk : std_logic;
component key5 --按键防抖动
port(
CLK,RESET:in std_logic;
din:in std_logic;
dout:out std_logic --'0'有效
);
end component;
------------------------------------------------波特率设置部分--------------------------------------------------------
begin
LCD_RESET <='1';LCD_RW <= '0' ;
process(CLK,RESET,Rx_Hold) --时钟产生进程
variable ClockCount : integer range 0 to 5208 :=0;
variable ClockCount_Rx : integer range 0 to 314 :=0;
variable ClockCount1 : integer range 0 to 5208 :=0;
variable ClockCount_Rx1 : integer range 0 to 314 :=0;
begin
if RESET='0' then time10ms<='0';
elsif (rising_edge(CLK)) then ClockCount:=ClockCount+1;
ClockCount_Rx:=ClockCount_Rx+1;
timecnt<=timecnt+1;
--产生9600时钟,1/50MHZ*5208=1/9600
case JX is --波特率选择
when "100" => ClockCount1:=5208;ClockCount_Rx1:=314;
when "010" => ClockCount1:=2604;ClockCount_Rx1:=157;
when "001" => ClockCount1:=1302;ClockCount_Rx1:=78;
when others => null;
end case;
if ClockCount=ClockCount1 then Clock9600<='1';
ClockCount:=0;
else Clock9600<='0';
end if;
if timecnt=100000 then time10ms<=not time10ms; timecnt<=0;
end if;
--16倍超采样,5208/16=325
if ClockCount_Rx=ClockCount_Rx1 then Clock3<='1';ClockCount_Rx:=0;
else Clock3<='0';
end if;
if(clkcnt="10000000000000")then clkcnt<="00000000000000";
else clkcnt<=clkcnt+1;
end if;
end if;
end process;
--注:以上代码注释 均是以波特率9600为例,case语句部分即为波特率选择部分。
LCD_Clk<=clkcnt(6);
------------------------------------------------键盘扫描部分--------------------------------------------------------
--进程2:键盘扫描输出
process( time10ms,RESET)
begin
if RESET='0' then scanvalue<="0001";combvalue<="00000000"; Data00<="0000000000"; --初始化
elsif time10ms'event and time10ms='1' then --每10ms进行一次键盘扫描
KeyOut<=scanvalue; --输出扫描值
cpy_scanvalue<=scanvalue; --备份扫描值,为了进程3对扫描结果进行比较
case scanvalue is --扫描值移位
when "0001" => scanvalue<="0010";
when "0010" => scanvalue<="0100";
when "0100" => scanvalue<="1000";
when "1000" => scanvalue<="0001";
when others => scanvalue<="0001";
end case;
combvalue<= (KeyIn & cpy_scanvalue); --组合键盘扫描的输入和输出
case combvalue is --翻译扫描结果
when "00010001" => Data00<="1000000010"; --对应键盘“1”
when "00100001" => Data00<="1000000100"; --对应键盘“2”
when "01000001" => Data00<="1000000110"; --对应键盘“3”
when "10000001" => JX<="100"; --对应键盘“X”
when "00010010" => Data00<="1000001000"; --对应键盘“4”
when "00100010" => Data00<="1000001010"; --对应键盘“5”
when "01000010" => Data00<="1000001100"; --对应键盘“6”
when "10000010" => JX<="010"; --对应键盘“Y”
when "00010100" => Data00<="1000001110"; --对应键盘“7”
when "00100100" => Data00<="1000010000"; --对应键盘“8”
when "01000100" => Data00<="1000010010"; --对应键盘“9”
when "10000100" => JX<="001"; --对应键盘“Z”
when "00011000" => Data00<="1000001000"; --对应键盘“0”
when "00101000" => null; --对应键盘“+”
when "01001000" => null; --对应键盘“-”
when "10001000" => null; --对应键盘“=”
when others => null; --无键盘按下
end case;
end if;
end process;
------------------------------------------------串口发送部分--------------------------------------------------------
process(Clock9600) --串口发送程序
variable Send_count : integer range 0 to 9 :=0; --位发送计数
begin
if Send_en='1' then Send_count:=0;UART0_TX<='1';Send_over<='1';
elsif rising_edge(Clock9600) then
if Send_count=9 then UART0_TX<=Send_data(9); Send_over<='0';
else UART0_TX<=Send_data(Send_count); Send_count:=Send_count+1;
end if;
end if;
end process;
Key0:key5 port map(CLK=>CLK,RESET=>RESET,din=>KEYA,dout=>dout); --元件例化
process(dout,Clock9600,RESET) --发送激励
begin
if RESET='0' then Send_en<='1';Send_data<="1000000000";
else
if rising_edge(dout)
then Send_en<='0'; Send_data<=Data00;
end if;
if Send_over='0' then Send_en<='1'; end if;
end if;
end process;
------------------------------------------------串口接收部分--------------------------------------------------------
process(RESET,CLK,Rx_Valid) --串口接收检测起始位
begin
if RESET='0' then Rx_Hold<='0';
else
if UART0_RX='0' and Rx_Hold='0' then Rx_Hold<='1'; --挂起串口接收
elsif Rx_Valid'event and Rx_Valid='0' then Rx_Hold<='0';
end if;
end if;
end process;
process(RESET,Clock3) --
variable m:integer range 0 to 168 :=0;
begin
if RESET='0' then Rx_Valid<='0';m:=0;
elsif rising_edge(Clock3) and Rx_Hold='1'
then
case m is
when 24 => Rx_Data(0)<=UART0_RX;
when 40 => Rx_Data(1)<=UART0_RX;
when 56 => Rx_Data(2)<=UART0_RX;
when 72 => Rx_Data(3)<=UART0_RX;
when 88 => Rx_Data(4)<=UART0_RX;
when 104 => Rx_Data(5)<=UART0_RX;
when 120 => Rx_Data(6)<=UART0_RX;
when 136=> Rx_Data(7)<=UART0_RX;
when 152 => Rx_Valid<='1';
when 168=> m:=0;Rx_Valid<='0';
when others => null;
end case;
m:=m+1;
end if;
end process;
process(Rx_Valid,CLK)
begin
if RESET='0' then Data1<="0000"; Data2<="0000";
else
if rising_edge(Rx_Valid) then
Data1<=Rx_Data(3)&Rx_Data(2)&Rx_Data(1)&Rx_Data(0);
Data2<=Rx_Data(7)&Rx_Data(6)&Rx_Data(5)&Rx_Data(4);
end if;
end if;
end process;
---------------------------------------LCD12864基本参数设置---------------------------------------------------------
control: process ( LCD_Clk,current_state )
variable fanwei:integer:=2500;
variable cnt : integer:=0 ;
begin
if LCD_Clk'event and LCD_Clk='1' then
case current_state is
when set => LCD_RS<='0'; --功能设定
LCD_D<="00110000" ; ----30h
LCD_E<='0';
if cnt=2 then LCD_E<='1' ;cnt:=cnt+1 ;
else LCD_E<='0' ; cnt:=cnt+1 ;
end if ;
if cnt=fanwei*2 then
current_state<=clr ;cnt:=0 ;else current_state<=set ;
end if ;
when clr => LCD_E<='0' ;
LCD_RS<='0' ;
LCD_D<="00000001"; ---清除显示 ,01H
if cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;
else LCD_E<='0'; cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_d ;cnt:=0 ; else current_state<=clr ;
end if ;
when set_d => LCD_E<= '0' ; -----设定显示的移动方向,06H
LCD_RS<= '0' ;
LCD_D<="00000110";
if cnt=2 then LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state <=open1; cnt :=0 ; else current_state<=set_d;
end if ;
when open1=> LCD_E<='0' ; -----显示状态开或关 0FH
LCD_RS<='0' ;
LCD_D<="00001100";
if cnt=2 then LCD_E<= '1'; cnt:=cnt+1 ;
else LCD_E<='0'; cnt:=cnt+1 ;
end if ;
if cnt=fanwei*2 then
current_state<=set_addr ;cnt:=0 ; else current_state<=open1;
end if ;
--------------------------------第一行 显示“波特率:(波特率数值)”------------------------------------------
when set_addr=>LCD_E<='0' ;
LCD_RS<='0' ;
LCD_D<=X"80"; ----设定地址 80H
if cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;
else LCD_E<='0'; cnt :=cnt+1 ;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom1 ;cnt:=0; else current_state<=set_addr;
end if ;
when set_ddrom1=>LCD_E<='0' ;
LCD_RS<='1' ;
LCD_D<=X"B2"; ----‘波’高字节
if cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;
else LCD_E<='0'; cnt :=cnt+1 ;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom2 ;cnt:=0; else current_state<=set_ddrom1;
end if ;
when set_ddrom2=> LCD_E<='0';
LCD_RS<='1';
LCD_D<=X"A8"; ----‘波’低字节
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if;
if cnt=fanwei*2 then
current_state<=set_ddrom3;cnt:=0; else current_state<=set_ddrom2;
end if;
when set_ddrom3=> LCD_E<='0'; ----‘特’高字节
LCD_RS<='1';
LCD_D<=X"CC";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom4;cnt:=0;else current_state<=set_ddrom3;
end if;
when set_ddrom4=> LCD_E<='0'; ----‘特’低字节
LCD_RS<='1';
LCD_D<=X"D8";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom5;cnt:=0;else current_state<=set_ddrom4;
end if;
when set_ddrom5=> LCD_E<='0'; ----‘率’高字节
LCD_RS<='1';
LCD_D<=X"C2";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom6;cnt:=0;else current_state<=set_ddrom5;
end if;
when set_ddrom6=> LCD_E<='0'; ----‘率’低字节
LCD_RS<='1';
LCD_D<=X"CA";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom7;cnt:=0;else current_state<=set_ddrom6;
end if;
when set_ddrom7=> LCD_E<='0'; ----‘:’高字节
LCD_RS<='1';
LCD_D<=X"A3";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom8;cnt:=0;else current_state<=set_ddrom7;
end if;
when set_ddrom8=> LCD_E<='0'; ----‘:’低字节
LCD_RS<='1';
LCD_D<=X"BA";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom9;cnt:=0;else current_state<=set_ddrom8;
end if;
when set_ddrom9=> LCD_E<='0'; ----‘9’
LCD_RS<='1';
case JX is
when "100" => LCD_D<=X"39";
when "010" => LCD_D<=X"31";
when "001" => LCD_D<=X"33";
when others => null;
end case;
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom10;cnt:=0;else current_state<=set_ddrom9;
end if;
when set_ddrom10=> LCD_E<='0'; ----‘6’
LCD_RS<='1';
case JX is
when "100" => LCD_D<=X"36";
when "010" => LCD_D<=X"39";
when "001" => LCD_D<=X"38";
when others => null;
end case;
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom11;cnt:=0;else current_state<=set_ddrom10;
end if;
when set_ddrom11=> LCD_E<='0';
LCD_RS<='1'; ----‘0’高字节
case JX is
when "100" => LCD_D<=X"30";
when "010" => LCD_D<=X"32";
when "001" => LCD_D<=X"34";
when others => null;
end case;
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom12;cnt:=0;else current_state<=set_ddrom11;
end if;
when set_ddrom12=> LCD_E<='0';
LCD_RS<='1'; ----‘0’低字节
LCD_D<=X"30";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom13;cnt:=0;else current_state<=set_ddrom12;
end if;
when set_ddrom13=> LCD_E<='0'; ----‘ ’高字节
LCD_RS<='1';
case JX is
when "100" => LCD_D<=X"D7";
when "010" => LCD_D<=X"30";
when "001" => LCD_D<=X"30";
when others => null;
end case;
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_addrh4;cnt:=0;else current_state<=set_ddrom13;
end if;
--注:以上代码注释 均是以波特率9600为例,case语句部分即为波特率选择部分。
---------------------------------第二行 显示:“数字:(传送值)”---------------------------------
when set_addrh4=>LCD_E<='0' ;
LCD_RS<='0' ;
LCD_D<=X"8A"; ----设定地址 8AH
if cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;
else LCD_E<='0'; cnt :=cnt+1 ;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom1h4 ;cnt:=0; else current_state<=set_addrh4;
end if ;
when set_ddrom1h4=>LCD_E<='0' ;
LCD_RS<='1' ;
LCD_D<="11001010"; ----‘数’高字节
if cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;
else LCD_E<='0'; cnt :=cnt+1 ;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom2h4 ;cnt:=0; else current_state<=set_ddrom1h4;
end if ;
when set_ddrom2h4=> LCD_E<='0';
LCD_RS<='1';
LCD_D<="11111101"; ----‘数’低字节
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if;
if cnt=fanwei*2 then
current_state<=set_ddrom3h4;cnt:=0; else current_state<=set_ddrom2h4;
end if;
when set_ddrom3h4=> LCD_E<='0'; ----‘字’高字节
LCD_RS<='1';
LCD_D<=X"D7";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom4h4;cnt:=0;else current_state<=set_ddrom3h4;
end if;
when set_ddrom4h4=> LCD_E<='0'; ----‘字’低字节
LCD_RS<='1';
LCD_D<=X"D6";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom5h4;cnt:=0;else current_state<=set_ddrom4h4;
end if;
when set_ddrom5h4=> LCD_E<='0'; ----‘:’高字节
LCD_RS<='1';
LCD_D<=X"A3";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom6h4;cnt:=0;else current_state<=set_ddrom5h4;
end if;
when set_ddrom6h4=> LCD_E<='0'; ----‘:’低字节
LCD_RS<='1';
LCD_D<=X"BA";
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom7h4;cnt:=0;else current_state<=set_ddrom6h4;
end if;
when set_ddrom7h4=> LCD_E<='0'; ----‘传送的代码值’
LCD_RS<='1';
LCD_D<=X"20";
case Data2 is
when "0000" => LCD_D<=X"30";
when "0001" => LCD_D<=X"31";
when "0010" => LCD_D<=X"32";
when "0011" => LCD_D<=X"33";
when "0100" => LCD_D<=X"34";
when "0101" => LCD_D<=X"35";
when "0110" => LCD_D<=X"36";
when "0111" => LCD_D<=X"37";
when "1000" => LCD_D<=X"38";
when "1001" => LCD_D<=X"39";
when others => null;
end case;
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=set_ddrom8h4;cnt:=0;else current_state<=set_ddrom7h4;
end if;
when set_ddrom8h4=> LCD_E<='0'; ----‘传送的代码值’
LCD_RS<='1';
LCD_D<=X"20";
case Data1 is
when "0000" => LCD_D<=X"30";
when "0001" => LCD_D<=X"31";
when "0010" => LCD_D<=X"32";
when "0011" => LCD_D<=X"33";
when "0100" => LCD_D<=X"34";
when "0101" => LCD_D<=X"35";
when "0110" => LCD_D<=X"36";
when "0111" => LCD_D<=X"37";
when "1000" => LCD_D<=X"38";
when "1001" => LCD_D<=X"39";
when others => null;
end case;
if cnt=2 then
LCD_E<='1';cnt:=cnt+1;
else LCD_E<='0';cnt:=cnt+1;
end if ;
if cnt=fanwei*2 then
current_state<=open1;cnt:=0;else current_state<=set_ddrom8h4;
end if;
when others=>current_state<=open1;
end case;
end if;
end process control;
end Behavioral;
------------------------------------------------主程序文件-----------------------------------------------------------
五、实验结果:
本次试验的波特率通过键盘上的“X”“Y”“Z”分别更改为:“9600、19200、38400”;LCD屏幕第一行显示“波特率: ”,第二行显示:“数字: ”;发送数字时按键盘中“A”键即可,在这里,只能发送和接收两位数的数字。以上功能,读者均可根据自身需求增添删改。在使用LCD12864时,需要知道汉字、数字和标点符号的内码,使用到的汉字内码查询器站内有很多,读者自行下载使用即可。
注明:本文章仅供学习参考之用,代码简单,但贵在易于理解和更改。作者水平有限,不免有错漏之处,如有问题或建议,可留言告之。