首页 > 编程知识 正文

51串口通信程序实例,三菱plc串口通信程序

时间:2023-05-06 02:21:58 阅读:208210 作者:3043

1,时序设计:

在进行具体的串口设计之前,先了解串口通信协议。通常串口的一次发送或接收由四个部分组成:起始位 S(“一般为逻辑‘0’)、数据位 D0~D7(一般为 6 位~8 位之间可变,数据低位在前)、校验位(奇校验、偶检验或不需要校验位)、停止位(通常为 1 位、1.5 位、2 位)。停止位必须为逻辑 1。在一次串口通信过程中,数据接收与发送双方没有共享时钟,因此,双方必须协商好数据传输波特率。波特率即数据传输速率。根据双方协议好的传输速率,接收端即可对发送端的数据进行采样。常见的波特率标准有300bps,600bps,800bps,9600bps,19200bps 等。当然更块的速度意味着对采样的要求更高,有可能误码率会逐渐提高。
通常对串口进行数据采样,采用更高频的时钟。这样做的目的是采用高频时钟来锁存低频时钟,减少数据的误码率,增加接收模块的自纠错能力。

具体的工作流程为:发送端按照预先设定好的波特率,发送起始位(Start)+数据位(data)+奇偶校验位+结束位。起始位为
逻辑 0,结束位为逻辑 1,发送端在空闲状态为 1。发送数据包格式如图:

2,具体代码

module uart(
                clk,rst_n,
                rx_bit,
                rx_en, //仿真测试
                rx_stop, //仿真测试
                bit_data, //仿真测试
                bit_num, //仿真测试
                rx_data );
input clk;
input rst_n;
input rx_bit; //串口数据输入测试 11 0 10101100 11
output [7:0]rx_data;
output rx_en; //仿真测试
output rx_stop; //仿真测试
output bit_data; //仿真测试
output [3:0]bit_num; //仿真测试

parameter buad_rate = 5207;   //设置波特率为9600
parameter bit_samp = 2603;   //设置数据采样率
reg [12:0]cnt; //时钟计数
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt <= 13'd0;
    else if(rx_en == 1)
    begin
        cnt <= cnt + 1'b1;
      if(cnt == buad_rate)
        cnt <= 13'd0;
    end
    else if(rx_en == 0)
        cnt <= 13'd0;
end

reg bit_data; //采样数据
always@(posedge clk)
begin
    if(cnt == bit_samp)
        bit_data <= 1'b1;
    else
       bit_data <= 1'b0;
end

/*检测串口数据下降沿*/
reg rx_bit1,rx_bit2,rx_bit3,rx_bit4;
wire neg_rx;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            rx_bit1 <= 0;
            rx_bit2 <= 0;
            rx_bit3 <= 0;
            rx_bit4 <= 0;
        end
    else if(rx_en != 1)
        begin
            rx_bit1 <= rx_bit;
            rx_bit2 <= rx_bit1;
            rx_bit3 <= rx_bit2;
            rx_bit4 <= rx_bit3;
        end    
end
assign neg_rx =  rx_bit4 & rx_bit3 & ~rx_bit2 & ~rx_bit1 ;

reg rx_en; //接收数据高电平使能
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        rx_en   <= 1'b0;
   else if(neg_rx == 1)    
        rx_en <= 1;    
    else if(rx_stop ==1)
    begin
        rx_en <= 0;
    end    
end

reg rx_stop;  //停止标志位
reg [3:0]bit_num; //串口数据位计数
reg [8:0]rx_data_temp; //存储接收到的数据
reg [7:0]rx_data;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
        rx_data_temp <= 9'b000000000; //初始值设定
        rx_data      <= 8'b00000000;
        bit_num <= 4'b0;
        rx_stop <= 0;
        end
    else if(bit_num == 4'd11)
    begin
         rx_stop <=1;
        bit_num <= 0;
    end
    else if( bit_data == 1)
            begin
                bit_num <= bit_num + 1'b1;
            case(bit_num)
            4'd0:    rx_data_temp[0] <= rx_bit; //起始位        
            4'd1:    rx_data_temp[1] <= rx_bit;
            4'd2:    rx_data_temp[2] <= rx_bit;
            4'd3:    rx_data_temp[3] <= rx_bit;
            4'd4:    rx_data_temp[4] <= rx_bit;
            4'd5:    rx_data_temp[5] <= rx_bit;
            4'd6:    rx_data_temp[6] <= rx_bit;
            4'd7:    rx_data_temp[7] <= rx_bit;
            4'd8:    rx_data_temp[8] <= rx_bit;
            default: ;    
            endcase
            end
        else
            rx_stop <= 0;
    rx_data <= rx_data_temp[8:1];
end

endmodule

3,testbench.v

`timescale 1 ns/ 1 ps
module uart_vlg_tst();
reg clk;
reg rst_n;
reg  rx_bit;
// wires                                               
wire bit_data;
wire [3:0]  bit_num;
wire [7:0]  rx_data;
wire rx_en;
wire rx_stop;
                       
uart i1 (  
    .bit_data(bit_data),
    .bit_num(bit_num),
    .clk(clk),
    .rst_n(rst_n),
    .rx_bit(rx_bit),
    .rx_data(rx_data),
    .rx_stop(rx_stop),
    .rx_en(rx_en)
);
initial                                                
begin                                                  
     #0 clk = 0;
         rst_n = 0;
      #5 rst_n =1;
end                                                    
always                                                                 
begin                                                  
     #10 clk = ~clk;                                       
end

always                                                                 
begin                                                  
     #104167 rx_bit = 1;
      #104167 rx_bit = 1;
      #104167 rx_bit = 0;
      #104167 rx_bit = 1;
      #104167 rx_bit = 0;
      #104167 rx_bit = 1;
      #104167 rx_bit = 0;
      #104167 rx_bit = 1;
      #104167 rx_bit = 1;
      #104167 rx_bit = 0;
      #104167 rx_bit = 0;
      #104167 rx_bit = 1;
      #104167 rx_bit = 1;      
end                                                    
endmodule

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。