一、前言:
最近在做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 issignal count         :   integer range 0 to 3000000  ;    --分频器signal keyclk     :   std_logic   ;                    --分频器type state is(s0,s1);                                    --定义两种状态signal pre_s,next_s:state;                               --状态机指针beginprocess(CLK,RESET)  --时钟进程,产生各种时钟信号beginif 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)    --状态机激励源beginif 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)   --begincase pre_s iswhen 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;                      --时钟输入,50MHZKeyIn            :   in  std_logic_vector(3 downto 0);   --column列电平KeyOut           :   out std_logic_vector(3 downto 0);   --row行电平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;------------------------------------------------波特率设置部分--------------------------------------------------------     beginLCD_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/9600case 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=325if 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)beginif 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;  --位发送计数                       beginif Send_en='1' then   Send_count:=0;UART0_TX<='1';Send_over<='1';elsif rising_edge(Clock9600) thenif 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)                                   --发送激励beginif RESET='0' then  Send_en<='1';Send_data<="1000000000";elseif 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)                                       --串口接收检测起始位beginif 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;beginif RESET='0' then Rx_Valid<='0';m:=0;elsif rising_edge(Clock3) and Rx_Hold='1'then     case m iswhen 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)beginif RESET='0' then   Data1<="0000";    Data2<="0000";elseif 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 ;beginif LCD_Clk'event and LCD_Clk='1' then     case current_state iswhen    set => LCD_RS<='0';                        --功能设定LCD_D<="00110000" ;                 ----30hLCD_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 thencurrent_state<=clr ;cnt:=0 ;else current_state<=set ;end if ;when    clr => LCD_E<='0' ;LCD_RS<='0' ;LCD_D<="00000001";                ---清除显示  ,01Hif cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;else LCD_E<='0'; cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_state<=set_d ;cnt:=0 ; else current_state<=clr ;end if ;when  set_d => LCD_E<= '0' ;                 -----设定显示的移动方向,06HLCD_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 thencurrent_state <=open1; cnt :=0 ;  else current_state<=set_d;end if ;when open1=> LCD_E<='0' ;                   -----显示状态开或关    0FHLCD_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 thencurrent_state<=set_addr ;cnt:=0 ; else current_state<=open1;end if ;--------------------------------第一行 显示“波特率:(波特率数值)”------------------------------------------                  when set_addr=>LCD_E<='0' ;LCD_RS<='0' ;             LCD_D<=X"80";                 ----设定地址 80Hif cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;else LCD_E<='0'; cnt :=cnt+1 ;end if ;if cnt=fanwei*2 thencurrent_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 thencurrent_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 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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";               ----设定地址 8AHif cnt=2 then LCD_E<='1'; cnt:=cnt+1 ;else LCD_E<='0'; cnt :=cnt+1 ;end if ;if cnt=fanwei*2 thencurrent_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 thencurrent_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 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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 thenLCD_E<='1';cnt:=cnt+1;else LCD_E<='0';cnt:=cnt+1;end if ;if cnt=fanwei*2 thencurrent_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时,需要知道汉字、数字和标点符号的内码,使用到的汉字内码查询器站内有很多,读者自行下载使用即可。


注明:本文章仅供学习参考之用,代码简单,但贵在易于理解和更改。作者水平有限,不免有错漏之处,如有问题或建议,可留言告之。

基于FPGA的UART串口通信实验(VHDL语言实现)相关推荐

  1. 基于FPGA Uart串口通信实验

    基于FPGA Uart串口通信实验 首先需要了解uart串口通信协议,根据个人专业需求不同,了解的层面可以不同. UART简介 通用异步收发传输器(Universal Asynchronous Rec ...

  2. 基于 FPGA 的 UART 控制器设计(VHDL)(下)

    今天给大侠带来基于FPGA的 UART 控制器设计(VHDL)(下),由于篇幅较长,分三篇.今天带来第三篇,下篇,使用 FPGA 实现 UART.话不多说,上货. 之前有关于 Veriliog HDL ...

  3. 【正点原子MP157连载】 第十六章 UART串口通信实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  4. 基于FPGA实现uart串口模块(Verilog)--------发送模块及整合

    基于FPGA实现uart串口模块(Verilog)--------发送模块及整合 当接收模块接收到数据后,需要重新发送形成回环验证模块正确性.思路和结束模块有一点点的小差异.接收模块最终输出的是一个并 ...

  5. 基于FPGA实现uart串口模块(Verilog)--------接收模块及思路总结

    基于FPGA实现uart串口模块(Verilog)--------接收模块及思路总结 uart通信协议简单理解为串转并和并转串的两个模块.同时必须保证数据的正确性.且输入输出端为串行. 此次实现uar ...

  6. 【FPGA练习】(一): UART串口通信实验

    由于之前学习FPGA的过程中,没有做一个良好的记录,以及已学知识的扩展,所以从今天开始每一个实验例程和扩展应用,都要做文档记录.本实验,是基于正点原子达芬奇xc7a35tfgg484-2开发板.开发板 ...

  7. UART 串口通信实验

            串口是"串行接口"的简称,即采用串行通信方式的接口.串行通信将数据字节分成一位一位的形式在一条数据线上逐个传送,其特点是通信线路简单,但传输速度较慢.因此串口广泛应 ...

  8. 【FPGA】UART串口通信

    目录 前言 一丶通信方式 1.串行通信 2.并行通信 二丶UART 串口通信 三丶模块设计 四丶发送模块 1.代码 2.仿真 五丶接收模块 1.代码 2.仿真 六丶顶层模块 1.代码 2.模块原理图 ...

  9. 【FPGA】——UART串口通信

    UART串口简介   串行通信分为两种方式:同步串行通信和异步串行通信.同步串行通信要求通信双方使用同一时钟,异步则没有这个要求.UART是一种采用异步串行通信方式的通用异步收发传输器(univers ...

最新文章

  1. PyQt5 技术篇-调用字体对话框(QFontDialog)获取字体,控件设置字体。
  2. 【蚁群路径规划】基于MATLAB的蚁群算法的二维路径规划
  3. C++ Primer 5th笔记(chap 19 特殊工具与技术)两种不可移植的特性之“位域”
  4. php 客户端上传图片,php上传图片客户端和服务器端实现方法
  5. 上班族吐槽大集合:那些发生在公司的傻X奇遇
  6. 使用SynchronousQueue实现生产者/消费者
  7. 关于chrome控制台警告:Synchronous XMLHttpRequest on the main thread终极解决办法
  8. 高德联手饿了么:外卖小哥跑出偏远地区活地图
  9. 设置将Maven的jar包发布到lib
  10. CSS布局:让页脚始终保持底部的方法
  11. 弱监督学习-snorkel
  12. java 日语文档翻译_日语文档怎么翻译?我来教会你日语翻译
  13. 旋转木马图片效果图,轮播图
  14. 阿拉伯数字转换为英语
  15. 独家爆料!在美团搞安全,是种怎样的体验?
  16. 逆向经验 + 逆向工具
  17. ACM素数打表(模版)
  18. pcie gen3 bios设置_u盘pe设置联想台式机lenovo BIOS从u盘启动教程
  19. div样式之margin
  20. 谷歌卫星地图下载器有哪些那款好用

热门文章

  1. 入门c语言。(1建立开发环境)
  2. 就靠一刀999的手游广告,这些隐形公司可以月赚百万
  3. 7.0.高等数学四-隐函数存在定理
  4. 学 Python 和学 Java ,哪个好找工作?
  5. 医依通小程序项目总结
  6. 【笔试】计算机网络知识点整理
  7. PHP 常用字符串、数组处理函数
  8. 获得汉字首字母和拼音
  9. IOS逆向之汇编基础
  10. VUE项目(仿商城)