实验十七:串口通信实验
一、实验目的
1.学习用FPGA设计简单串口通信的方法。 2.学习UART串口通信的工作原理。
3.学习用FPGA实现UART的实现的原理和具体实现方法。 二、实验原理 2.1串口通信概述
串行接口的数据传输方式是串行的,即数据是一位位的进行传输。串行接口的应用非常广泛,PC机上一般就至少有两个串行接口——COM1和COM2,虽然串行接口的传输方式导致其传输速度会比较慢,但是却具有较强的抗干扰能力,并能有较长的传输距离。
在串行通信中,用“波特率”来描述数据的传输速率。所谓波特率,即每秒传送的二进制位数,其单位为bit/s(bits per second),它是衡量传输串行数据速度快慢的重要指标。有时候也用“位周期”来表示传输速率,位周期是波特率的倒数。国际上规定了一个标准波特率系列:110bit/s、300bit/s、600 bit/s、1200 bit/s、1800 bit/s、2400 bit/s、2400 bit/s、9600 bit/s、14.4k bit/s、19.2 kbit/s、28.8k bit/s等,如9600 bit/s,其意义是每秒传送9600位数据,包含字符位和其他必须的位。
大多数串行接口电路的接收波特率和发送波特率都可以设置,但是接收方的波特率必须与发送方的发送波特率形同。通信线上所传输的字符数据时逐位传送的,1个字符由若干位组成,因此每秒钟所传输的字符数(字符速率)和波特率是两种概念。在串行通信中所说的传输速率是指波特率。
在串行通信中,除了可以设置波特率外,其他的如字符数据的位数、奇偶校验位、停止位也可以被设置,其中字符数据的位数可以被设置为5~8位;奇偶校验位可以去除,也可以设置为奇校验或者偶校验;停止位可以设置为1位、1.5位或者2位。
2.2串行通信的时序和UART
串行总线在空闲时候保持逻辑1的状态,当需要传送一个字符时,首先要发送一个逻辑0的起始位,表示开始发送数据;之后就逐个发送数据位、奇偶校验位和停止位(逻辑为1)。例如通过RS232串行通信发送一个字符“1”(二进制00110001),设置为8位数据位,1位奇偶校验位,1位停止位,发送时序如图一所示:
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
00110001停止位空闲状态空闲状态起始位字符”1”对应的二进制码奇偶校验位
图一 RS232串口通信时序图
对一个设备的处理器来说,要接收和发送串行通信的数据,还需要一个器件将串行的数据转换为并行的数据以便于处理器进行处理,这种器件就是UART。UART(Universal Asynchronous Receiver/Transmitter)通用异步收发器。UART是用于控制计算机与串行设备的芯片,有一点需要注意的是,它提供了RS232数据终端设备接口,这样计算机就可以和调制解调器或其他使用RS232接口的串行设备通信了,作为接口的一部分,UART还提供以下功能:
将由计算机内部传送过来的并行数据转换为输出的串行数据流; 将计算机外部来的串行数据转换为字节,供计算机内部使用并行数据的器件使用;
在输出的串行数据流中加入奇偶校验位,并对从外部接收的数据流进行奇偶校验;
在输出数据流中加入启停标记,并从接收数据流中删除启停标记。 2.3使用FPGA实现UART的 2.3.1 完整UART实现原理
UART主要由UART内核、信号检测器、移位寄存器、波特率发生器、计数器、总线选择器和奇偶校验器7个模块组成。
UARTCPU接口控制信号RS232输入信号检测器UART内核控制信号控制信号总线选择器校验信号奇偶校验器指示信号控制信号波特率时钟RS232输出移位寄存器控制信号波特率发生器指示信号计数器
图二 UART实现原理图
完整的UART各个模块的功能如下:
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
1. UART内核模块
UART内核模块是整个设计的核心。在数据接收时,UART内核模块负责控制波特率发生器和移位寄存器,使得移位寄存器在波特率时钟的驱动下同步的接收并且保存RS-232接收端口上的串行数据。在数据发送时,UART内核模块首先根据待发送的数据和奇偶校验位的设置产生完整的发送序列(包括起始位、数据位、奇偶校验位和停止位),之后控制移位寄存器将序列加载到移位寄存器的内部寄存器里,最后再控制波特率发生器驱动移位寄存器将数据串行输出。
2. 信号检测模块
信号检测器用于对RS-232的输入信号进行实时检测,一旦发现新的数据则立即通知UART内核。需要注意的是,这里所说的RS-232输入输出信号都指经过电平转换后的逻辑信号,而不是RS-232总线上的电平信号。绝对不能直接将RS-232总线的信号连接到FPGA管脚上,否则很容易造成FPGA芯片的损坏。
3. 移位寄存器模块
移位寄存器的作用是存储输入或者输出的数据。当UART接收RS-232输入时,移位寄存器在波特率模式下采集RS-232输入信号,并且保存结果;当UART进行RS-232输出时,UART内核首先将数据加载到移位寄存器内,再使移位寄存器在波特率提供的模式下将数据输出到RS-232输出端口上。在这里的波特率模式是指模块的输入时钟是符合RS-232传输波特率的时钟,与波特率模式对应的就是系统时钟模式,即模块是工作在系统时钟下。
4. 波特率发生器模块
由于RS-232传输必定是工作在某种波特率下,比如9600,为了便于和RS-232总线进行同步,需要产生符合RS-232传输波特率的时钟,这就是波特率发生器的功能。
5. 奇偶校验器模块
奇偶校验器的功能是根据奇偶校验的设置和输入数据计算出响应的奇偶校验位,它是通过纯组合逻辑来实现的。
6. 总线选择模块
总线选择模块用于选择奇偶校验器的输入是数据发送总线还是数据接收总线。在接收数据时,总线选择模块将数据接收总线连接到奇偶校验器的输入端,来检查已经接收数据的奇偶校验位是否正确;在发送数据时,总线选择模块将数据发送总线连接到奇偶校验器的输入端,UART内核模块就能获取并且保存待发送序列所需的奇偶校验位了。
7. 计数器模块
计数器模块的功能是记录串行数据发送或者接收的数目,在计数到某数值时
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目 通知UART内核模块。
2.3.2 UART完整的工作流程
UART完整的工作流程可以分为接收过程和发送过程两部分。
接收过程是指UART监测到RS-232总线上的数据,顺序读取串行数据并且将其输出给CPU的过程。当信号监测到新的数据(RS-232输入逻辑变为0,即RS-232传输协议的起始位)就会触发接收流程,流程图如图三所示。首先UART内核会重置波特率发生器和移位寄存器,并且设置设置移位寄存器的工作模式为波特率模式,以准备接收数据。其次,移位寄存器在波特率时钟的驱动下工作,不断读取RS-232串行总线的输入数据,并且将数据保存在内部的寄存器内。接收完成后,UART内核会对已接收的数据进行奇偶校验并且输出校验结果。最后,UART内核会重置信号检测器,以准备进行下一次数据接收。
启动进行奇偶校验重置波特率发生器和移位寄存器,设置其工作模式为波特率模式否奇偶位正确?是将移位寄存器移位,读取串行输入信号,保存在移位寄存器末位输出错误信号输出接收完成信号重置信号检测器否全部数据已读取?是结束 图三 UART接收数据流程图
发送过程是由加载和发送两个步骤组成,如图四所示。加载步骤是UART内核按RS-232串行发送的顺序将起始位、数据位、奇偶校验位和停止位加载到移位寄存器内,这个过程工作在系统时钟下,相对于RS-232传输速度来说非常快。完成加载步骤后,UART内核会重置波特率发生器,并且设置移位寄存器工作在波特率模式下,于是移位寄存器便在波特率时钟的驱动下依次将加载的数据发送到RS-232的发送端TxD,这样就产生了RS-232的数据发送时序。
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
启动移位寄存器在波特率的驱动下顺序将加载的数据发送到RS-232的发送端重置波特率发生器和移位寄存器,设置其工作模式为系统时钟模式,计算奇偶校验位将待发送的串行数据送到移位寄存器的输入端,移位寄存器顺序加载此数据全部发送完毕?否全部数据已加载?是重置波特率发生器,设置移位寄存器的工作模式为波特率模式输出信号提示发送完成结束 图四 UART发送数据流程图
三、实验说明
完整的UART控制器比较复杂,在这里本实验的目的是验证实现FPGA和PC机进行基本的串口通信的功能,功能实现的比较简单,只是实现UART协议的一部分。程序实现了一个发一帧10个bit(无奇偶校验位)的串口控制器,10个bit是1位起始位,8个数据位,1个结束位。串口的波特率由程序中定义的div_par参数决定,更改该参数可以实现相应的波特率。程序当前设定的div_par值是27=50M/115200/8/2,对应的波特率是115200。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间划分为8个时隙以使通信同步。程序的工作过程是:每按一下reset,FPGA向PC发送“welcomeyalong\"字符串,需要在PC机上安装一个串口调试工具来验证程序的功能。
四、实验步骤
1.建立工程完成文件输入
先建立一个工程,建立一个顶层原理图文件,保存为uart.bdf,建立一个.v文件,另存为serial.v,程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控制器,10个bit是1位起始位,8个数据位,1个结束位。串口的波特律由程序中定义的div_par参数决定,更改该参数可以实现相应的波特率。程序当前设定的div_par值是27=50M/115200/8/2,对应的波特率是115200。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间划分为8个时隙以使通信同步。程序的工作过程是:每按一下reset,FPGA向PC发送“welcomeyalong\"字符串,具体代码如下:
module serial (
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
clk , rst , rxd ,
txd , );
input clk; input rst; input rxd; output txd;
//////////////////inner reg////////////////////
reg [15:0] div_reg ; reg [2:0] div8_tras_reg ; reg [3:0] div8_rec_reg ; reg [3:0] state_tras ;
reg [3:0] state_rec ; //接受状态寄存器
reg clkbaud_tras ; //以波特率为频率的发送使能信号 reg clkbaud_rec ; //以波特率为频率的接受使能信号 reg clkbaud8x ; reg recstart ;
reg recstart_tmp ; //开始接受标志 reg trasstart ; //开始发送标志
reg rxd_reg1 ; //接收寄存器1 reg rxd_reg2 ;
reg txd_reg ; //发送寄存器 reg [7:0] rxd_buf ; //接受数据缓存 reg [7:0] txd_buf ; //发送数据缓存 reg [3:0] send_state ;
reg key_entry2 ; //确定有键按下标志
parameter div_par =16'b0000000000011011;
assign txd = txd_reg ;
always @(posedge clk or negedge rst) begin
if(rst==1'b0) begin
div_reg<=16'h00; clkbaud8x <= 1'b0; end
else if(div_reg < div_par)
div_reg <= div_reg + 1'b1; else
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
begin
div_reg<=16'h0000;
clkbaud8x <= ~clkbaud8x; end end
always @(posedge clkbaud8x or negedge rst) begin
if(rst==1'b0)
div8_rec_reg <= 3'b000; else if(recstart ==1'b1)
div8_rec_reg<=div8_rec_reg+1'b1; end
always @(posedge clkbaud8x or negedge rst) begin
if(rst==1'b0)
div8_tras_reg <=3'b000; else if(trasstart ==1'b1)
div8_tras_reg <= div8_tras_reg + 1'b1; end
always @(div8_rec_reg) begin
if(div8_rec_reg == 3'b111) clkbaud_rec <= 1'b1; else
clkbaud_rec <= 1'b0; end
always @(div8_tras_reg)//always @(div8_rec_reg) begin
if(div8_tras_reg == 3'b111) clkbaud_tras <= 1'b1; else
clkbaud_tras <= 1'b0; end
always @(posedge clkbaud8x or negedge rst) begin
if(rst==1'b0) begin
txd_reg <=1'b1;
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
trasstart <= 1'b0; txd_buf <= 8'h00; state_tras <= 4'b0000; send_state <= 4'b0000; key_entry2 <=1'b1;
txd_buf <= 8'b0000_0000;//8'b01110111;//\"w\" end else
case(state_tras)
4'b0000: begin //发送起始位
if(!trasstart&&(send_state < 4'b1111)) trasstart <= 1'b1;
else if(send_state < 4'b1111) if (clkbaud_tras == 1'b1)
begin txd_reg <= 1'b0;
state_tras <= state_tras + 1'b1; end else
begin
key_entry2 <= 1'b0; state_tras <= 4'b0000; end
end 4'b0001: begin //发送第一位
if(clkbaud_tras == 1'b1)
begin txd_reg = txd_buf[0];
txd_buf[6:0] = txd_buf[7:1]; state_tras = state_tras +1'b1; end
end 4'b0010: begin
if (clkbaud_tras == 1'b1) begin
txd_reg <= txd_buf[0];
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end 4'b0011: begin
if (clkbaud_tras == 1'b1)
begin txd_reg <= txd_buf[0];
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end 4'b0100: begin
if (clkbaud_tras == 1'b1) begin
txd_reg <= txd_buf[0];
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end 4'b0101: begin
if (clkbaud_tras == 1'b1) begin
txd_reg <= txd_buf[0];
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end 4'b0110: begin
if (clkbaud_tras == 1'b1) begin
txd_reg <= txd_buf[0];
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end 4'b0111: begin
if (clkbaud_tras == 1'b1) begin
txd_reg <= txd_buf[0];
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end
4'b1000: begin//发送第8位 if (clkbaud_tras == 1'b1) begin
txd_reg <= txd_buf[0];
txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras +1'b1; end end
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
4'b1001: begin//发送停止位 if (clkbaud_tras == 1'b1) begin
txd_reg <= 1'b1;
txd_buf <= 8'b01010101; state_tras <= state_tras +1'b1; end end 4'b1111:begin
if (clkbaud_tras == 1'b1) begin
state_tras <= state_tras + 1'b1; send_state <= send_state + 1'b1; trasstart <= 1'b0; case (send_state)
4'b0000:txd_buf<=8'b01010111;//W 4'b0001:txd_buf <=8'b01100101;//\"e\" 4'b0010:txd_buf <=8'b01101100;//\"l\" 4'b0011:txd_buf <=8'b01100011;//\"c\" 4'b0100:txd_buf <=8'b01101111;//\"o\" 4'b0101:txd_buf <=8'b01101101;//\"m\" 4'b0110:txd_buf <=8'b01100101;//\"e\" 4'b0111:txd_buf <=8'b01111001;//\"y\" 4'b1000:txd_buf <=8'b01100001;//\"a\" 4'b1001:txd_buf <=8'b01101100 ;//\"l\" 4'b1010:txd_buf <=8'b01101111;//\"o\" 4'b1011:txd_buf <=8'b01101110;//\"n\" 4'b1100:txd_buf <=8'b01100111;//\"g\" 4'b1101:txd_buf <=8'b00001010 ;//\"\\n\" default:txd_buf <=8'b00000000; endcase end end
default:begin
if (clkbaud_tras == 1'b1) begin
state_tras <= state_tras + 1'b1; trasstart <= 1'b1; end end endcase end
endmodule
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
2.完成工程
分析综合该文件,建立元件符号并放置在原理图中,为其加上输入输出符号,如图所示:
3. 设置芯片分配管脚
设置好配置芯片,Unused Pins管脚设置,以及cycloneⅡ系列的nCEO管脚设置。
在工程目录下建立一个name为Setup.tcl的file,输入一下代码 #setup pin setting
set_global_assignment -name RESERVE_ALL_UNUSED_PINS \"AS INPUT TRI-STATED\"
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT OFF
set_location_assignment PIN_23 -to clk set_location_assignment PIN_37 -to reset
set_location_assignment PIN_103 -to rxd set_location_assignment PIN_102 -to txd
将setup.tcl文件保存到工程目录下,将当前实体设定为顶层原理图,运行该管脚分配文件。
4. 全编译
将顶层原理图设置为顶层实体,运行ProcessingStart compilation编译该文件。
5.连接串口线
用标准串口线把实验板和PC连接起来,确定串口线连接正确。 6.下载运行
把实验板上电,下载完成后在PC上打开串口调试助手2.1,在上方接收区的串口选择COM1,波特率选择115200,校验位选择无校验位,8个数据位1个停止位。每按下reset,可以在接收区看到FPGA通过串口向PC发送的一个welcomeyalong。
EDA/SOPC实验系统 EDA/SOPC数字实验开发系统实验项目
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 99spj.com 版权所有 湘ICP备2022005869号-5
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务