打印

串口RS232通信程序

[复制链接]
5909|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
thf2008|  楼主 | 2009-12-19 09:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
串口有9个管脚,其中只有三个是最重要的,分别是

下载 (5.47 KB)
2009-12-16 23:26
pin 2: RxD (receive data).接收数据
pin 3: TxD (transmit data).发送数据
pin 5: GND (ground).     
串行通信时序

我们先来看看字节0x55的发送
下载 (6.28 KB)
2009-12-16 23:26
0x55的二进制代码是01010101,但发送时由低字节开始的,因此发送次序依次为1-0-1-0-1-0-1-0.
串行通信电平
·
"1" is sent using -10V (or between -5V and -15V).
·
"0" is sent using +10V (or between 5V and 15V).

由于计算机RS232的电平与电路板(通常+5V)之间电平的不同所以要用到转换芯片
如果PCB板电源+-5V的话用MAX232
如果PCB板(FPGA)电源是+-3.3V的话用MAX3232
下载 (35.72 KB)
2009-12-16 23:26

这个图的串口如果采用母头的话,要用交叉公母线,保证是PCB板上这边的RxD连计算机的TxD(3 Pin),PCB板这边的TxD连计算机的RxD(2 Pin).

相关帖子

沙发
thf2008|  楼主 | 2009-12-19 09:41 | 只看该作者
怎么图片都显示不了?只能麻烦大家打开图片来看了

使用特权

评论回复
板凳
thf2008|  楼主 | 2009-12-19 09:41 | 只看该作者
继续

使用特权

评论回复
地板
thf2008|  楼主 | 2009-12-19 09:44 | 只看该作者
串行通信波特率
这里要弄清楚波特率与比特率的差别:
比特率是数字信号的传输速率,它用单位时间内传输的二进制代码的有效位(bit)数来表示,其单位为每秒比特数bit/s(bps)、每秒千比特数(Kbps)或每秒兆比特数(Mbps)来表示(此处K和M分别为1000和1000000,而不是涉及计算机存储器容量时的1024和1048576)。
波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,其单位为波特(Baud)。

波特率与比特率的关系为:比特率=波特率X单个调制状态对应的二进制位数
两相调制(单个调制状态对应1个二进制位)的比特率等于波特率;
四相调制(单个调制状态对应2个二进制位)的比特率为波特率的两倍;
八相调制(单个调制状态对应3个二进制位)的比特率为波特率的三倍;
依次类推。
对于串行通信来说,或者说是对于普通的数字电路来说,都是两相调制(单个调制状态对应1个二进制位),因此波特率=比特率(通常叫波特率)。

PS
:可以看看下面图就知道什么是四相调制。
下载 (34.49 KB)
2009-12-16 23:35
如果系统时钟是1.8432MHz,那16分频就得到115200Hz
reg
[3:0] BaudDivCnt;
always @(posedge clk) BaudDivCnt <= BaudDivCnt + 1;

wire BaudTick = (BaudDivCnt==15);

但通常系统的时钟不是刚刚好是波特率的整数倍,如果不采用DCM对系统进行倍频的话,可以采用下面程序进行处理,设系统时钟为2MHz=2000000Hz
2000000/115200=17.36111
1024/59= 17.356
2000000/1152001024/59
两个频率很接近,可以采用下面程序产生我们要的波特率。
// 10 bits for the accumulator ([9:0]), and one extra bit for the accumulator carry-out ([10])reg
[10:0] acc;          // 11 bits total!

always @(posedge clk)
  acc <= acc[9:0] + 59;

// use only 10 bits from the previous result, but save the full 11 bits

wire BaudTick = acc[10]; // so that the 11th bit is the carry-out
当系统时钟为2MHz的时候,计算得到的波特率的值为115234,与115200只有0.03%的误差。
我们怎么得到“59呢,可以看下面的推导

使用特权

评论回复
5
thf2008|  楼主 | 2009-12-19 09:45 | 只看该作者
[localimg=180,145]5[/localimg]  

其中Baud<<BaudGeneratorAccWidth,Baud左移BaudGeneratorAccWidth位,相当于Baud乘以2的BaudGeneratorAccWidth次方。

参照上面的程序与公式推导可以把程序修改如下:

parameter
ClkFrequency = 25000000; // 25MHz
parameter Baud = 115200;
parameter BaudGeneratorAccWidth = 16;
parameter BaudGeneratorInc = (Baud<<BaudGeneratorAccWidth)/ClkFrequency;

reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;
always @(posedge clk)
  BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;

wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];




当要注意的是,上面程序中BaudGeneratorInc的计算公式出错,因为在Verilog语言中中间结果只能32位,而这个公式计算的结果超过了32位。所以要把这行改为

parameter
BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-4))+(ClkFrequency>>5))/(ClkFrequency>>4);




程序改变,得到的波特率不变。

使用特权

评论回复
6
thf2008|  楼主 | 2009-12-19 09:45 | 只看该作者
RS232发送接收模块


可以参考下面文档,这里就不贴出来了。

http://attach.baisi.net/getattac ... tion%2Foctet-stream



RS232发送模块(Verilog)

RS232接收模块(Verilog)

以上程序均标注了J



调用串口发送接收模块

`timescale 1ns / 1ps



module serialfun(clk, RxD, TxD);

input clk;     //系统时钟



input RxD;

output TxD;



//////////////////////////////////////////////////

wire RxD_data_ready;

wire [7:0] RxD_data;



async_receiver deserializer(                //RS-232接收模块

                        .clk(clk),

                                                .RxD(RxD),

                                                .RxD_data_ready(RxD_data_ready),

//当接收到一个字节的数据时,"RxD_data_ready"有效一个周期

                                                .RxD_data(RxD_data)   //接收一个字节数据

                                                );



///////////////////////////////////////////////////

async_transmitter serializer(               //RS-232发送模块

                        .clk(clk),

                                               .TxD(TxD),

                                                .TxD_start(RxD_data_ready),   

//"TxD_start"置位后开始传输

                                                .TxD_data(RxD_data)  //发送一个字节数据

                                                );



endmodule



这个程序的结果是在从计算机发送八个字节到FPGA,FPGA再把这八个字节转发回计算机。

要注意是如果以十六进制发送的话,就要以十六进制显示,8个字节可以发送2个字符(0~F)。如果没选以十六进制发送的话,会以ASCII码发送,只能发送一个字符(一个字符的ASCII有8个字节)。






在Spartan3E Starter Kit开发板上有两个串口,所以设置管脚时要注意选择哪个串口,选择母头的话(DCE)与计算机相连的串口线选择交叉的公母线;选择公头的话(DTE),与计算机相连的串口线选择交叉的母母线。

我选择了公头,UCF文件如下(约束管脚)



NET
"clk" LOC
= "C9" |
IOSTANDARD
= LVCMOS33 ;

NET
"RxD" LOC
= "U8" |
IOSTANDARD
= LVTTL ;

NET
"TxD" LOC
= "M13" |
IOSTANDARD
= LVTTL |DRIVE
= 8 |SLEW
= SLOW ;



本文Xilinx ISE工程文件(在Spartan3E Starter Kit开发板上实现)

使用特权

评论回复
7
thf2008|  楼主 | 2009-12-19 09:46 | 只看该作者
希望对大家有用

使用特权

评论回复
8
linhai2009| | 2009-12-19 09:56 | 只看该作者
有点乱

使用特权

评论回复
9
juventus9554| | 2009-12-19 22:11 | 只看该作者
学习了

使用特权

评论回复
10
hulan1985| | 2009-12-19 22:17 | 只看该作者
232的资料别的地方资料也很多,楼主帮我们找找422的资料吧

使用特权

评论回复
11
贾君鹏子| | 2009-12-19 22:21 | 只看该作者
485得也行啊,多学习学习

使用特权

评论回复
12
五谷道场| | 2009-12-19 22:45 | 只看该作者
嗯,乱七八糟的怎么

使用特权

评论回复
13
328500920| | 2009-12-19 22:55 | 只看该作者
浏览

使用特权

评论回复
14
GENERRALDE| | 2009-12-21 09:59 | 只看该作者
学习了

使用特权

评论回复
15
xiaoxin1986| | 2009-12-21 12:27 | 只看该作者
学习了

使用特权

评论回复
16
五谷道场| | 2009-12-23 15:47 | 只看该作者
学习了
xiaoxin1986 发表于 2009-12-21 12:27


学习到什么了?我怎么看的头晕眼花的,帮忙整理一些呗

使用特权

评论回复
17
hulan1985| | 2009-12-23 22:25 | 只看该作者
我来传个思路清晰的吧

PC机与单片机通信(RS232协议).rar

51.78 KB

使用特权

评论回复
18
hulan1985| | 2009-12-23 22:25 | 只看该作者
这个是以前做实验整理的

使用特权

评论回复
19
juventus9554| | 2009-12-23 22:29 | 只看该作者
嗯,程序有价值,虽然简单点

使用特权

评论回复
20
午夜粪车| | 2009-12-23 22:54 | 只看该作者
17楼还是学生吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

221

主题

2024

帖子

2

粉丝