打印

有关pc与fpga串口通信的问题

[复制链接]
2420|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wlinot|  楼主 | 2012-9-26 12:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
gaochy1126| | 2012-9-26 19:59 | 只看该作者
是的,可以设置为无奇偶校验,这样很简单那的!

使用特权

评论回复
板凳
gaochy1126| | 2012-9-26 19:59 | 只看该作者
而且波特率,可以根据自己的需要来设置,使用非常简单

使用特权

评论回复
地板
51xlf| | 2012-9-26 20:03 | 只看该作者
典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配:   a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。   b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。   c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。   d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位为1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

使用特权

评论回复
5
hawksabre| | 2012-9-27 18:10 | 只看该作者
timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    17:27:40 08/28/08
// Design Name:   
// Module Name:    speed_select
// Project Name:   
// Target Device:  
// Tool versions:  
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module speed_select(
                                clk,rst_n,
                                bps_start,clk_bps
                        );

input clk;        // 50MHz主时钟
input rst_n;        //低电平复位信号
input bps_start;        //接收到数据后,波特率时钟启动信号置位
output clk_bps;        // clk_bps的高电平为接收或者发送数据位的中间采样点

/*
parameter                 bps9600         = 5207,        //波特率为9600bps
                                 bps19200         = 2603,        //波特率为19200bps
                                bps38400         = 1301,        //波特率为38400bps
                                bps57600         = 867,        //波特率为57600bps
                                bps115200        = 433;        //波特率为115200bps        //直接利用分频的思路,用系统时钟50MHZ/波特率

parameter                 bps9600_2         = 2603,
                                bps19200_2        = 1301,
                                bps38400_2        = 650,
                                bps57600_2        = 433,
                                bps115200_2 = 216;  
*/

        //以下波特率分频计数值可参照上面的参数进行更改
`define                BPS_PARA                433        //波特率为115200时的分频计数值
`define         BPS_PARA_2                216        //波特率为115200时的分频计数值的一半,用于数据采样//(中间采样)

reg[12:0] cnt;                        //分频计数
reg clk_bps_r;                        //波特率时钟寄存器

//----------------------------------------------------------
reg[2:0] uart_ctrl;        // uart波特率选择寄存器
//----------------------------------------------------------

always @ (posedge clk or negedge rst_n)
        if(!rst_n) cnt <= 13'd0;
        else if((cnt == `BPS_PARA) || !bps_start) cnt <= 13'd0;        //波特率计数清零  //  当计数器计满或者还没有接收到数据时,计数器清零
        else cnt <= cnt+1'b1;                        //波特率时钟计数启动

always @ (posedge clk or negedge rst_n)
        if(!rst_n) clk_bps_r <= 1'b0;
        else if(cnt == `BPS_PARA_2) clk_bps_r <= 1'b1;        // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
        else clk_bps_r <= 1'b0;

assign clk_bps = clk_bps_r;

endmodule



`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:
// Design Name:   
// Module Name:    my_uart_top
// Project Name:   
// Target Device:  
// Tool versions:  
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 欢迎加入EDN的FPGA/CPLD助学小组一起讨论:http://group.**/1375/
////////////////////////////////////////////////////////////////////////////////
module my_uart_top(
                                clk,rst_n,
                                rs232_rx,rs232_tx
                                );

input clk;                        // 50MHz主时钟
input rst_n;                //低电平复位信号

input rs232_rx;                // RS232接收数据信号
output rs232_tx;        //        RS232发送数据信号

wire bps_start1,bps_start2;        //接收到数据后,波特率时钟启动信号置位
wire clk_bps1,clk_bps2;                // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
wire[7:0] rx_data;        //接收数据寄存器,保存直至下一个数据来到
wire rx_int;                //接收数据中断信号,接收到数据期间始终为高电平
//----------------------------------------------------
//下面的四个模块中,speed_rx和speed_tx是两个完全独立的硬件模块,可称之为逻辑复制
//(不是资源共享,和软件中的同一个子程序调用不能混为一谈)
////////////////////////////////////////////
speed_select                speed_rx(       
                                                        .clk(clk),        //波特率选择模块
                                                        .rst_n(rst_n),
                                                        .bps_start(bps_start1),
                                                        .clk_bps(clk_bps1)
                                                );

my_uart_rx                        my_uart_rx(               
                                                        .clk(clk),        //接收数据模块
                                                        .rst_n(rst_n),
                                                        .rs232_rx(rs232_rx),
                                                        .rx_data(rx_data),
                                                        .rx_int(rx_int),
                                                        .clk_bps(clk_bps1),
                                                        .bps_start(bps_start1)
                                                );

///////////////////////////////////////////                                               
speed_select                speed_tx(       
                                                        .clk(clk),        //波特率选择模块
                                                        .rst_n(rst_n),
                                                        .bps_start(bps_start2),
                                                        .clk_bps(clk_bps2)
                                                );

my_uart_tx                        my_uart_tx(               
                                                        .clk(clk),        //发送数据模块
                                                        .rst_n(rst_n),
                                                        .rx_data(rx_data),
                                                        .rx_int(rx_int),
                                                        .rs232_tx(rs232_tx),
                                                        .clk_bps(clk_bps2),
                                                        .bps_start(bps_start2)
                                                );

endmodule


`timescale 1ns / 1ps                                       
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    17:11:32 08/28/08
// Design Name:   
// Module Name:    my_uart_rx
// Project Name:   
// Target Device:  
// Tool versions:  
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module my_uart_rx(
                                clk,rst_n,
                                rs232_rx,rx_data,rx_int,
                                clk_bps,bps_start
                        );

input clk;                // 50MHz主时钟
input rst_n;        // 低电平复位信号
input rs232_rx;        // RS232接收数据信号
input clk_bps;        // clk_bps的高电平为接收或者发送数据位的中间采样点
output bps_start;                //接收到数据后,波特率时钟启动信号置位
output[7:0] rx_data;        //接收数据寄存器,保存直至下一个数据来到
output rx_int;        //接收数据中断信号,接收到数据期间始终为高电平

//----------------------------------------------------------------
reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;        //接收数据寄存器,滤波用
wire neg_rs232_rx;        //表示数据线接收到下降沿

always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
                        rs232_rx0 <= 1'b0;
                        rs232_rx1 <= 1'b0;
                        rs232_rx2 <= 1'b0;
                        rs232_rx3 <= 1'b0;
                end
        else begin
                        rs232_rx0 <= rs232_rx;
                        rs232_rx1 <= rs232_rx0;
                        rs232_rx2 <= rs232_rx1;
                        rs232_rx3 <= rs232_rx2;
                end
end
        //下面的下降沿检测可以滤掉<20ns-40ns的毛刺(包括高脉冲和低脉冲毛刺),
        //这里就是用资源换稳定(前提是我们对时间要求不是那么苛刻,因为输入信号打了好几拍)
        //(当然我们的有效低脉冲信号肯定是远远大于40ns的)
assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0;        //接收到下降沿后neg_rs232_rx置高一个时钟周期

//----------------------------------------------------------------
reg bps_start_r;
reg[3:0] num;        //移位次数
reg rx_int;                //接收数据中断信号,接收到数据期间始终为高电平

always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                        bps_start_r <= 1'bz;
                        rx_int <= 1'b0;
                end
        else if(neg_rs232_rx) begin                //接收到串口接收线rs232_rx的下降沿标志信号//接收到下降沿后neg_rs232_rx置高一个时钟周期
                        bps_start_r <= 1'b1;        //启动串口准备数据接收
                        rx_int <= 1'b1;                        //接收数据中断信号使能
                end
        else if(num==4'd12) begin                //接收完有用数据信息
                        bps_start_r <= 1'b0;        //数据接收完毕,释放波特率启动信号
                        rx_int <= 1'b0;                        //接收数据中断信号关闭
                end

assign bps_start = bps_start_r;

//----------------------------------------------------------------
reg[7:0] rx_data_r;                //串口接收数据寄存器,保存直至下一个数据来到
//----------------------------------------------------------------

reg[7:0] rx_temp_data;        //当前接收数据寄存器

always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                        rx_temp_data <= 8'd0;
                        num <= 4'd0;
                        rx_data_r <= 8'd0;
                end
        else if(rx_int) begin        //接收数据处理
                if(clk_bps) begin        //读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位               
                                num <= num+1'b1;
                                case (num)
                                                4'd1: rx_temp_data[0] <= rs232_rx;        //锁存第0bit
                                                4'd2: rx_temp_data[1] <= rs232_rx;        //锁存第1bit
                                                4'd3: rx_temp_data[2] <= rs232_rx;        //锁存第2bit
                                                4'd4: rx_temp_data[3] <= rs232_rx;        //锁存第3bit
                                                4'd5: rx_temp_data[4] <= rs232_rx;        //锁存第4bit
                                                4'd6: rx_temp_data[5] <= rs232_rx;        //锁存第5bit
                                                4'd7: rx_temp_data[6] <= rs232_rx;        //锁存第6bit
                                                4'd8: rx_temp_data[7] <= rs232_rx;        //锁存第7bit
                                                default: ;
                                endcase
                        end
                else if(num == 4'd12) begin                //我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
                                num <= 4'd0;                        //接收到STOP位后结束,num清零
                                rx_data_r <= rx_temp_data;        //把数据锁存到数据寄存器rx_data中
                        end
                end

assign rx_data = rx_data_r;       

endmodule



`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    17:11:32 08/28/08
// Design Name:   
// Module Name:    my_uart_rx
// Project Name:   
// Target Device:  
// Tool versions:  
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module my_uart_tx(
                                clk,rst_n,
                                rx_data,rx_int,rs232_tx,
                                clk_bps,bps_start
                        );

input clk;                        // 50MHz主时钟
input rst_n;                //低电平复位信号
input clk_bps;                // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
input[7:0] rx_data;        //接收数据寄存器
input rx_int;                //接收数据中断信号,接收到数据期间始终为高电平,在该模块中利用它的下降沿来启动串口发送数据
output rs232_tx;        // RS232发送数据信号
output bps_start;        //接收或者要发送数据,波特率时钟启动信号置位

//---------------------------------------------------------
reg rx_int0,rx_int1,rx_int2;        //rx_int信号寄存器,捕捉下降沿滤波用
wire neg_rx_int;        // rx_int下降沿标志位

always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
                        rx_int0 <= 1'b0;
                        rx_int1 <= 1'b0;
                        rx_int2 <= 1'b0;
                end
        else begin
                        rx_int0 <= rx_int;
                        rx_int1 <= rx_int0;
                        rx_int2 <= rx_int1;
                end
end

assign neg_rx_int =  ~rx_int1 & rx_int2;        //捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期

//---------------------------------------------------------
reg[7:0] tx_data;        //待发送数据的寄存器
//---------------------------------------------------------
reg bps_start_r;
reg tx_en;        //发送数据使能信号,高有效
reg[3:0] num;

always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
                        bps_start_r <= 1'bz;
                        tx_en <= 1'b0;
                        tx_data <= 8'd0;
                end
        else if(neg_rx_int) begin        //接收数据完毕,准备把接收到的数据发回去
                        bps_start_r <= 1'b1;
                        tx_data <= rx_data;        //把接收到的数据存入发送数据寄存器
                        tx_en <= 1'b1;                //进入发送数据状态中
                end
        else if(num==4'd11) begin        //数据发送完成,复位
                        bps_start_r <= 1'b0;
                        tx_en <= 1'b0;
                end
end

assign bps_start = bps_start_r;

//---------------------------------------------------------
reg rs232_tx_r;

always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
                        num <= 4'd0;
                        rs232_tx_r <= 1'b1;
                end
        else if(tx_en) begin
                        if(clk_bps)        begin
                                        num <= num+1'b1;
                                        case (num)
                                                4'd0: rs232_tx_r <= 1'b0;         //发送起始位
                                                4'd1: rs232_tx_r <= tx_data[0];        //发送bit0
                                                4'd2: rs232_tx_r <= tx_data[1];        //发送bit1
                                                4'd3: rs232_tx_r <= tx_data[2];        //发送bit2
                                                4'd4: rs232_tx_r <= tx_data[3];        //发送bit3
                                                4'd5: rs232_tx_r <= tx_data[4];        //发送bit4
                                                4'd6: rs232_tx_r <= tx_data[5];        //发送bit5
                                                4'd7: rs232_tx_r <= tx_data[6];        //发送bit6
                                                4'd8: rs232_tx_r <= tx_data[7];        //发送bit7
                                                4'd9: rs232_tx_r <= 1'b1;        //   xcc/发送结束位
                                                 default: rs232_tx_r <= 1'b1;
                                                endcase
                                end
                        else if(num==4'd11) num <= 4'd0;        //复位
                end
end

assign rs232_tx = rs232_tx_r;

endmodule

使用特权

评论回复
6
hawksabre| | 2012-9-27 18:12 | 只看该作者
这是他们之间建立通信的程序   你试一下   这个是我在网上找的   希望对你有帮助  呵呵

使用特权

评论回复
7
gaochy1126| | 2012-9-27 22:46 | 只看该作者
楼上的 程序很不错,哈哈

使用特权

评论回复
8
wjzx111056| | 2012-9-28 20:24 | 只看该作者
串口通信肯定是要双方协调一致才能正常通信的,简单说就是协议,任何通信的双方在通信之前都是需要有协议的约定的,不然彼此都能明白对方在说什么,就如两个人谈话一样~~~~~

使用特权

评论回复
9
gaochy1126| | 2012-9-29 08:50 | 只看该作者
自己设计串口开始觉得很难,后来就感觉还是自己设计的方便

使用特权

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

本版积分规则

0

主题

16

帖子

0

粉丝