RS232通信程序的设计.docx
- 文档编号:3541961
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:44
- 大小:92.18KB
RS232通信程序的设计.docx
《RS232通信程序的设计.docx》由会员分享,可在线阅读,更多相关《RS232通信程序的设计.docx(44页珍藏版)》请在冰豆网上搜索。
RS232通信程序的设计
RS232通信程序的设计
本章先介绍串口通信的基础知识,之后将重点介绍一个通过串口配置寄存器的一些代码。
1.RS232基础
RS232是一种异步串行通信接口,由于它比较简单,在工业中使用相当广泛。
虽然我们常说RS232程序设计,但是RS232只是一个物理层的标准,只规定了信号物理特性,链路层的协议是UART,而我们所说的RS232接口的逻辑设计主是指这部分的内容。
图5-1UART的帧格式
图5-1给出了UART的帧格式。
在线路空闲的时候,主设备将发送”1”;在通信时,主设备需要先发一个起始位”0”,以表示通信的开始;然后开始发送有效数据;之后再传送一比特的奇偶校验值;最后发送停止位”1”,以表示当前通信的完成。
其中,数据可以事先约定为5位、6位、7位或者8位;奇偶校验位根据事先约定由对数据位按位进行异或或者同或而得到,它不是必须的。
PC上的RS232接口有多个引脚,如果使用Modem的话需要将所有管脚都接起来,但是如果在其它情况下,则可不需要控制信号,只需要将通信两端的收发、电源和地相连即可,如图所示。
图5-2使用Modem的RS232连接图
图5-3不使用Modem的RS232连接图
另外,在RS232中,还有一个波特率的概念。
所谓波特率,在这里指单位时间内传送二进制数据的位数,以位/秒为单位,是衡量串行数据传输快慢的重要指标。
如果某串口的波特率为115200,指的是该串口以115200bits/s的速率在传输数据。
2.设计需求
在接下来的章节介绍的是一个通过RS232接口配置寄存器的设计,它是某项目的其中一部分,这部分电路用于配置IP地址等参数。
在我们这个演示程序中,为了简单起见,我们只设置了几个寄存器。
设计输入输出信号如表5-1表示。
表5-1端口列表
信号名
方向
功能
clk
I
时钟信号
rst_n
I
全局复位信号
rs232_din
I
RS232串行输入信号
rs232_dout
O
RS232串行输出信号
cpu与外部的信息交换统称为通信。
基本的通信方式有两种:
(1)并行通信--各位数据同时传送。
例如cpu与pio间的数据交换是八位一起传送的,这就是并行通信。
(2)串行通信--数据是一位、一位顺序传送的方式。
例如远动装置发、收两端的距离很长,只采用一条通道传送信息,这就需要各位信息逐位按次序传送,即串行通信。
串行通信分为异步通信(async)和同步通信(sync),以及同步数据链路通信(sdlc)、高级数据链路通信(hdlc)等,它们的主要区别表现在不同的信息格式上。
我们主要介绍其中最基本的异步和同步通信。
(1)异步通信:
在数据位的前后必须加上起始位和停止位。
传送一个八位数据时,最少也要有十位数据的长度。
(2)同步通信:
在异步通信中,每一个字符要用起始位和停止位作为开始和结
束的标志。
例如一个字符为8位数据。
起始位和终止位至少各占1位,实际传送信息的效率最多是80%。
在传送大量数据时,为了提高传送信息的效率,采用一个数据块共用一个同步字作为起始位的力格式,叫同步通信方式,同步传送方式是用发、收双方规定的同步字来作为数据块的开始和结束。
同步方式可分为内同步和外同步两种方式。
发送帧的格式及接收帧的格式分别如图5-4和5-5所示。
图5-4发送帧格式
图5-5接收帧格式
图5-6
由于传输链路不复杂,我们对检错设计做的较为简单,在UART协议中,不使用奇偶校验(如图5-6所示),只是在每一帧结尾加上一个简单的校验和。
该校验和的生成方式将同步字、帧头、操作码、数据相加,丢掉进位,只保留低8位值作为校验和并传送。
图5-7串口通信程序使用的UART帧格式
系统时钟频率为40Mhz,波特率为115.2Kb/s。
3.模块划分
RTL级划分
结合设计需求,该设计可划分成4个一级模块:
config_registers、clken_gen、frame_deal(桢处理)和rs232模块(如图5-7所示)。
图5-8RTL级结构划分图
config_registers模块用于存放配置寄存器组。
clken_en用于产生时钟使能。
由于原项目的系统时钟频率是40Mhz,为了避免使用分频时钟,我们采取了使用时钟使能的方法,在第三章我们也提过,这种做法可以使设计变得简单和可靠。
frame_deal模块用于完成数据帧的处理。
它包括了tx_frame和rx_frame两个子模块,分别对应发送帧和接收帧的处理。
RS232模块用于完成与RS232接口相关的功能。
它包括了txmit和rxvr子模块,分别对应于UART的发送和接收功能。
行为级划分
图5-9行为级结构划分示意图
图5-10
图5-9给出了行为级结构的示意图。
在该设计中,testcase和bm_frame_deal模块位于设计的上层,具体时序已被harness模块封装了起来,在testcase和bm_frame_deal这个层次已经没有了时序的概念。
testbench中每一个上层都通过调用下层的task来完成相应的功能,这种方式有点类似于windows的API函数,通过对一些接口函数的调用屏蔽了下层的细节。
osc_rst模块用于产生系统时钟和复位信号。
bfm_uart模块位于testbench的底层,主要模拟与被测对象接口的行为,它包含了uart_tx和uart_rx两个任务,分别对应uart的发送和接收。
harness模块封装了bfm_uart、ocs_rst和被测对象,时序的概念到该层为止。
bm_frame_deal模块用于完成数据帧的发送和接收,由tx_frame和rx_frame两个任务构成。
testcase位于设计的顶层,包含了几种简单的需测试的情况。
4.RTL级代码
top_module
`timescale1ns/100ps
moduletop_module(
//-------inputport------
clk,
rst_n,
rs232_din,
//-----outputport-------
rs232_dout
);
//-------inputport------
inputclk;
inputrst_n;
inputrs232_din;
//-----outputport-------
outputrs232_dout;
wirers232_dout;
//internalsignaldeclaration
wirewrite_cmd;
wire[31:
0]config_din;
wire[2:
0]config_addr;
wire[31:
0]config_dout;
wirers232_16xclk_en;
wirers232_1xclk_en;
wire[7:
0]uart_txdata;
wireuart_txdata_en;
wirers232_din;
wireuart_d_ready;
wire[7:
0]uart_rxdata;
//--------------------maincode----------------
――各模块的实现――
――配置寄存器模块――
config_registersUconfig_registers(
//--------------inputport------------
.clk(clk),
.rst_n(rst_n),
.write_cmd(write_cmd),
.config_din(config_din),
.config_addr(config_addr),
//--------------outputport------------
.config_dout(config_dout)
);
――发送接受模块――
rs232Urs232(
//-------------inputside---------------
.clk(clk),
.rst_n(rst_n),
.rs232_16xclk_en(rs232_16xclk_en),
.rs232_1xclk_en(rs232_1xclk_en),
.uart_txdata(uart_txdata),
.uart_txdata_en(uart_txdata_en),
.rs232_din(rs232_din),
//-----------outputside--------------
.uart_d_ready(uart_d_ready),
.uart_rxdata(uart_rxdata),
.rs232_dout(rs232_dout)
);
――分频模块――
clken_genUclken_gen(
//------inputport---------
.clk(clk),
.rst_n(rst_n),
//-------outputport--------
.rs232_16xclk_en(rs232_16xclk_en),
.rs232_1xclk_en(rs232_1xclk_en)
);
――数据处理模块――
frame_dealUframe_deal(
//---------inputport----------
.clk(clk),
.rst_n(rst_n),
.rs232_1xclk_en(rs232_1xclk_en),
.uart_d_ready(uart_d_ready),
.uart_rxdata(uart_rxdata),
.config_dout(config_dout),
//----------outputport--------
.write_cmd(write_cmd),
.config_addr(config_addr),
.config_din(config_din),
.uart_txdata_en(uart_txdata_en),
.uart_txdata(uart_txdata)
);
endmodule
config_registers
`timescale1ns/100ps
moduleconfig_registers(
//--------------inputport------------
clk,
rst_n,
write_cmd,
config_din,
config_addr,
//--------------outputport------------
config_dout
);
//--------------inputport------------
inputclk;
inputrst_n;
inputwrite_cmd;
input[31:
0]config_din;――32位的数据输入
input[2:
0]config_addr;――3位的地址输入
//--------------outputport------------
output[31:
0]config_dout;――32位的数据输出
reg[31:
0]config_dout;
//----------------internalsignaldeclaration-----------
parameterU_DLY=1;
reg[7:
0]priority;――配置寄存器1
reg[31:
0]port0_ip;
reg[31:
0]port1_ip;
reg[31:
0]port2_ip;
reg[31:
0]port3_ip;
//-----------------maincode------------------------
//配置寄存器1
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
priority<=8'b0000_0001;
elseif(write_cmd==1'b1&config_addr==3'h1)
priority<=#U_DLYconfig_din[7:
0];
end
//配置寄存器2
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
port0_ip<=32'b0;
elseif(write_cmd==1'b1&config_addr==3'h2)
port0_ip<=#U_DLYconfig_din;
end
//配置寄存器3
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
port1_ip<=32'b0;
elseif(write_cmd==1'b1&config_addr==3'h3)
port1_ip<=#U_DLYconfig_din;
end
//配置寄存器4
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
port2_ip<=32'b0;
elseif(write_cmd==1'b1&config_addr==3'h4)
port2_ip<=#U_DLYconfig_din;
end
//配置寄存器5
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
port3_ip<=32'b0;
elseif(write_cmd==1'b1&config_addr==3'h5)
port3_ip<=#U_DLYconfig_din;
end
//------------------读配置寄存器--------------------
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
config_dout<=32'b01;//默认为版本寄存器
else
case(config_addr)
3'h0:
config_dout<=#U_DLY32'b1;//版本寄存器
3'h1:
config_dout<=#U_DLY{24'b0,priority};
3'h2:
config_dout<=#U_DLYport0_ip;
3'h3:
config_dout<=#U_DLYport1_ip;
3'h4:
config_dout<=#U_DLYport2_ip;
3'h5:
config_dout<=#U_DLYport3_ip;
default:
config_dout<=#U_DLY32'b1;
endcase
end
endmodule
frame_deal
`timescale1ns/100ps
moduleframe_deal(
//---------inputport----------
clk,
rst_n,
rs232_1xclk_en,
uart_d_ready,
uart_rxdata,
config_dout,
//----------outputport--------
write_cmd,
config_addr,
config_din,
uart_txdata_en,
uart_txdata
);
//---------inputport----------
inputclk;
inputrst_n;
inputrs232_1xclk_en;
inputuart_d_ready;
input[7:
0]uart_rxdata;
input[31:
0]config_dout;
//----------outputport--------
outputwrite_cmd;
output[2:
0]config_addr;
output[31:
0]config_din;
outputuart_txdata_en;
output[7:
0]uart_txdata;
wirewrite_cmd;
wire[2:
0]config_addr;
wire[31:
0]config_din;
wireuart_txdata_en;
wire[7:
0]uart_txdata;
//---internalsignaldeclaration----
wireread_cmd;
rx_frameUrx_frame(
//-------------inputport-------------
.clk(clk),
.rst_n(rst_n),
.rs232_1xclk_en(rs232_1xclk_en),
.uart_d_ready(uart_d_ready),
.uart_rxdata(uart_rxdata),
//-------------outputport------------
.read_cmd(read_cmd),
.write_cmd(write_cmd),
.config_addr(config_addr),
.config_din(config_din)
);
tx_frameUtx_frame(
//-------------inputport-------------
.clk(clk),
.rst_n(rst_n),
.rs232_1xclk_en(rs232_1xclk_en),
.read_cmd(read_cmd),
.config_dout(config_dout),
//-------------outputport------------
.uart_txdata_en(uart_txdata_en),
.uart_txdata(uart_txdata)
);
endmodule
tx_frame
`timescale1ns/100ps
moduletx_frame(
//-------------inputport-------------
clk,
rst_n,
rs232_1xclk_en,
read_cmd,
config_dout,
//-------------outputport------------
uart_txdata_en,
uart_txdata
);
//-------------inputport-------------
inputclk;
inputrst_n;
inputrs232_1xclk_en;
inputread_cmd;
input[31:
0]config_dout;
//-------------outputport------------
outputuart_txdata_en;
output[7:
0]uart_txdata;
reguart_txdata_en;
reg[7:
0]uart_txdata;
//------internalsignaldeclaration---------
parameterU_DLY=1;
parameterSYN_WORD=8'h55,
FRAME_HEADER=8'hF1;
parameterIDLE=0,
SEND_SYN_CODE=1,
SEND_HEADER=2,
SEND_DATA=3,
SEND_CHECKSUM=4;
reg[4:
0]current_state;
reg[4:
0]next_state;
reg[3:
0]rs232_cnt;
reg[1:
0]uart_txdata_cnt;
reg[7:
0]check_sum;
//-------------------maincode---------------
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1'b0)
current_state<=5'b1;
else
current_state<=#U_DLYnext_state;
end
always@(current_stateorread_cmdoruart_txdata_enoruart_txdata_cnt)
begin
next_state=5'b0;
case(1'b1)//synthesisfull_caseparallel_case
current_state[IDLE]:
if(read_cmd==1'b1)
next_state[SEND_SYN_CODE]=1'b1;
else
next_state[IDLE]=1'b1;
current_state[SEND_SYN_CODE]:
if(uart_txdata_en==1'b1)
next_state[SEND_HEADER]=1'b1;
else
next_state[SEND_SYN_CODE]=1'b1;
current_state[SEND_HEADER]:
if(uart_txdata_en==1'b1)
next_state[SEND_DATA]=1'b1;
else
next_state[SEND_HEADER]=1'b1;
current_state[SEND_DATA]:
if(uart_txdata_en==1'b1&&uart_txdata_cnt==2'b11)
next_state[SEND_CHECKSUM]=1'b1;
else
next_state[SEND_DATA]=1'b1;
current_state[SEND_CHECKSUM]:
if(uart_t
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- RS232 通信 程序 设计