FPGA串口(RS422)调试笔记:理解串口通信与调试记录

这篇具有很好参考价值的文章主要介绍了FPGA串口(RS422)调试笔记:理解串口通信与调试记录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

团队项目需求,由于USB通信存在数据被测试环境干扰的问题,且考虑到所需通信速率不高,所以转为串口通信,下面是自己的调试记录,方便自己理解与日后回顾。

一、串口到底指的什么?

了解之前,我也很疑惑,听到大家都在说串口啦,uart啦,rs232啦,rs422啦,rs485啦,说的我一脸懵逼。后来自己了解后,才发现其实类别都不同,不能放在一起说。

串口包含了uart,还包含usb等等,可以说是uart是串口,但串口不一定是uart,我是这样理解的,不知道对不对。串口是物理层次上说的,一般有两种形式的物理接口,DB9和4针的杜邦线插口。

uart包含了rs232,rs422和rs485这些接口标准。可以说这三种接口的物理层不同,输出的电平不同,但通信协议是一样的,也就是说,编程实现是一样的,只是硬件电路电路上不同,当然其传输速率,抗干扰能力等等也自不相同。

二、调试记录

1.先通过串口助手实现uart的发送与接收

从Xilinx嫖的uart接收与发送的例程,改改引脚定义:团队做的pcb用芯片把rs422电平转化为FPGA芯片识别的ttl电平,所以要做的就是得输进去一个rs422电平。

懵逼的我拿了个一头是usb另一头是DB9的线插上去,咦~怎么不管用啊。后来才发现这根线是usb转rs232的线。。。。。我拿了个rs232转rs422的转换器,接上后,咦~~~管用了。

后来加购了个usb直接转rs422电平的线,就可以了。(嘘,我原本以为,usb连接电脑,那边出来的只能是rs232的电平,之后回来再看的时候,不准笑话自己,哈哈哈)

代码如下(by Xilinx):

`timescale 1ns / 1ps
//
//Module name uart_rx
//Description: 16 个 clock 接收一个 bit,16 个时钟采样,取中间的采样值
//(by_Xilinx)
//
module uart_rx(
    input                    clk, //采样时钟
    input                    rst_n, //复位信号
    input                    rx, //UART 数据输入
    output   reg[7:0]    dataout, //接收数据输出
    output    reg        rdsig, 
    output    reg        dataerror, //数据出错指示
    output    reg        frameerror//帧出错指示
);


reg [7:0] cnt;
reg          rxbuf, rxfall, receive;
parameter paritymode = 1'b0;
reg         presult;
reg          idle;//线路状态指示,高为线路忙,低为线路空闲
always @(posedge clk) //检测线路的下降沿
    begin
        rxbuf <= rx;
        rxfall <= rxbuf & (~rx);
    end

//启动串口接收程序

always @(posedge clk)
    begin
        if (rxfall && (~idle)) begin//检测到线路的下降沿并且原先线路为空闲,启动接收数据进程
            receive <= 1'b1;
        end
        else if(cnt == 8'd168) begin //接收数据完成
            receive <= 1'b0;
        end
    end

//串口接收程序, 16 个时钟接收一个 bit

always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n) begin
            idle<=1'b0;
            cnt<=8'd0;
            rdsig <= 1'b0;
            frameerror <= 1'b0; 
            dataerror <= 1'b0; 
            presult<=1'b0;
        end 
        else if(receive == 1'b1) begin
        case (cnt)
            8'd0:begin
                idle <= 1'b1;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd24:begin //接收第 0 位数据
                idle <= 1'b1;
                dataout[0] <= rx;
                presult <= paritymode^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd40:begin //接收第 1 位数据 
                idle <= 1'b1;
                dataout[1] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd56:begin //接收第 2 位数据 
                idle <= 1'b1;
                dataout[2] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd72:begin //接收第 3 位数据 
                idle <= 1'b1;
                dataout[3] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd88:begin //接收第 4 位数据 
                idle <= 1'b1;
                dataout[4] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd104:begin //接收第 5 位数据 
                idle <= 1'b1;
                dataout[5] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd120:begin //接收第 6 位数据 
                idle <= 1'b1;
                dataout[6] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b0;
            end
            8'd136:begin //接收第 7 位数据 
                idle <= 1'b1;
                dataout[7] <= rx;
                presult <= presult^rx;
                cnt <= cnt + 8'd1;
                rdsig <= 1'b1;
            end
            8'd152:begin //接收奇偶校验位 
                idle <= 1'b1;
            if(presult == rx)
                dataerror <= 1'b0;
            else
                dataerror <= 1'b1; //如果奇偶校验位不对,表示数据出错
                cnt <= cnt + 8'd1;
                rdsig <= 1'b1;
            end
            8'd168:begin
                idle <= 1'b1;
            if(1'b1 == rx)
                frameerror <= 1'b0;
            else
                frameerror <= 1'b1; //如果没有接收到停止位,表示帧出错
                cnt <= cnt + 8'd1;
                rdsig <= 1'b1;
            end
            default: begin
                cnt <= cnt + 8'd1;
            end
        endcase
    end
            else begin
                cnt <= 8'd0;
                idle <= 1'b0;
                rdsig <= 1'b0;
            end
        end
endmodule

`timescale 1ns / 1ps
//
// Module Name: uart_tx 
// 说明:16 个 clock 发送一个 bit, 一个起始位,8 个数据位,一个校验位,一个停止位
//
module uart_tx(
		input		clk, 		//UART 时钟
		input		rst_n, 	//系统复位
		input	   [7:0]  datain, 	//需要发送的数据
		input		wrsig,	//发送命令,上升沿有效
		output reg	idle, 	//线路状态指示,高为线路忙,低为线路空闲
		output reg 	tx			//发送数据信号
	);
		

		reg 	send;
		reg 	wrsigbuf, wrsigrise;
		reg 	presult;
		reg[7:0] cnt; //计数器
		
parameter paritymode = 1'b0;

//检测发送命令 wrsig 的上升沿

always @(posedge clk)
	begin
		wrsigbuf <= wrsig;
		wrsigrise <= (~wrsigbuf) & wrsig; 
	end

//启动串口发送程序

always @(posedge clk)
	begin
	if (wrsigrise && (~idle)) //当发送命令有效且线路为空闲时,启动新的数据发送进程
		begin
			send <= 1'b1;
		end
	else if(cnt == 8'd168) //一帧数据发送结束
		begin
			send <= 1'b0;
		end
	end

//串口发送程序, 16 个时钟发送一个 bit

always @(posedge clk or negedge rst_n)
	begin
		if (!rst_n) begin
			tx <= 1'b0;
			idle <= 1'b0;
			cnt<=8'd0;
			presult<=1'b0;
		end
		else if(send == 1'b1) begin
	case(cnt) //产生起始位
		8'd0: begin
			tx <= 1'b0;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd16: begin
			tx <= datain[0]; //发送数据 0 位
			presult <= datain[0]^paritymode;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd32: begin
			tx <= datain[1]; //发送数据 1 位
			presult <= datain[1]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd48: begin
			tx <= datain[2]; //发送数据 2 位
			presult <= datain[2]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd64: begin
			tx <= datain[3]; //发送数据 3 位
			presult <= datain[3]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd80: begin 
			tx <= datain[4]; //发送数据 4 位
			presult <= datain[4]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd96: begin
			tx <= datain[5]; //发送数据 5 位
			presult <= datain[5]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd112: begin
			tx <= datain[6]; //发送数据 6 位
			presult <= datain[6]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd128: begin 
			tx <= datain[7]; //发送数据 7 位
			presult <= datain[7]^presult;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd144: begin
			tx <= presult; //发送奇偶校验位
			presult <= datain[0]^paritymode;
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd160: begin
			tx <= 1'b1; //发送停止位 
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
		end
		8'd168: begin
			tx <= 1'b1; 
			idle <= 1'b0; //一帧数据发送结束
			cnt <= cnt + 8'd1;
		end
		default: begin
			cnt <= cnt + 8'd1;
		end
	endcase
end
	else begin
		tx <= 1'b1;
		cnt <= 8'd0;
		idle <= 1'b0;
	end
end
endmodule

2.编写top文件,把连续接收的8bit的数据拼接成16bit数据(之后需要的位数)

光这个功能,搞了我两天,我也是崩了,有时候数据不变化,有时候错位(我就是个菜鸡)。

但好在自己看着Modelsim的仿真图,一点点改好了,接收到的十六位数据也正常了。这就是乐趣所在吧,在自己操作下,一点点实现它的价值,感觉就很棒!

3.删去原USB程序,把串口程序拼上去

先用Modelsim仿真,再用signaltap抓实时数据,最后用串口助手发送所需要的数据,成功被后续芯片接收,并测的有效果,表明已通过串口发送到目标芯片,并产生所需数据。

后续和团队软件人员沟通,作出一版通过串口发送的界面,再进行调试。


总结

第一次单独完成一个小功能,还是很开心的,记录下来,数年后再看看这个小菜鸡。

遇到问题,就想着去解决,不知道的东西,就去查资料,现在这个阶段所学的东西,肯定已经有人做过,参考一下,感谢CSDN能提供交流的平台。学无止境,继续前行。文章来源地址https://www.toymoban.com/news/detail-400121.html

到了这里,关于FPGA串口(RS422)调试笔记:理解串口通信与调试记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA学习笔记(三)——串口通信之发送数据(调试过程)

    本学习笔记主要参考小梅哥B站教学视频,网址如下: https://www.bilibili.com/video/BV1va411c7Dz?p=1 使用的编译器为Vivado,HDL语言为verilog 一、串口通信之发送数据 原理 设计代码 测试代码 仿真结果 发现Send_en拉高之前,uart_tx就置为0了,不符合常理。 转到第二个发送信号处,发现Send

    2023年04月09日
    浏览(43)
  • FPGA入门 —— FPGA UART 串口通信

    UART 通用异步收发传输器( Universal Asynchronous Receiver/Transmitter) ,通常称作 UART。 UART 是一种通用的数据通信协议,也是异步串行通信口(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。 它包括了ch340、 RS232、

    2024年02月09日
    浏览(46)
  • 【FPGA】FPGA实现UART串口通信回环

    关于UART协议的基础理论部分已经在上一篇文章中讲述,不再重复介绍。 UART通信协议 本文主要介绍如何使用Verlilog编程,通过FPGA实现UART串口通信回环工程。在本工程中所使用的系统时钟为50MHz,如果选择115200的波特率进行数据传输,那么传输1bit所用的时钟周期数就是50_000_

    2024年02月05日
    浏览(65)
  • FPGA实现串口通信(RS232)含代码

    带有CH340的FPAG开发板 该模块的功能是接收通过 PC 机上的串口调试助手发送的固定波特率的数据,串口接收模块按照串口的协议准确接收串行数据,解析提取有用数据后需将其转化为并行数据;简单的说,接收模块的功能就是 解析+串转并 ; 具体实现步骤如下: 1、算出波特

    2024年02月02日
    浏览(55)
  • 【FPGA】UART串口通信---基于FIFO

    我们在上一章完成了UART串口通信的收发模块,这一章我们将FIFO引入进来,使用FIFO进行缓存数据,来连接串口通信的收发模块 FIFO即First In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而FIFO这种存储器的结构并不需要外

    2023年04月14日
    浏览(84)
  • 【FPGA】UART串口通信——奇偶校验实现

    奇偶校验位是基于uart的数据上进行一个判断 奇校验:数据1个数为奇时,校验为0,反之为1 偶校验:数据0个数为偶时,校验为0,反之为1 Uart回环在之前已经实现,现在需要基于uart增加一个奇偶校验位的需求 uart及代码:https://blog.csdn.net/weixin_59150966/article/details/128005066?spm=10

    2024年02月11日
    浏览(42)
  • 串口RS232/RS485/RS422的DB9引脚定义

    DB9M指的是DB9公头(针型)(M是Male的缩写) DB9F指的是DB9母头(孔型)(F是Female的缩写) DB9M脚定义   DB9F脚定义 RS232接线说明 RS232需要接 3根线 ,收发对接,还要接一根地线。 实物展示   DB9M脚定义  DB9M 1 2 3 4 5 6 7 8 9 RS485 D+ D- GND +5V RS422 T+ T- R+ R- GND +5V (注:该定义来源于

    2024年02月11日
    浏览(50)
  • 通信-RS232、RS485、RS422接口

    本内容包括RS232、RS485与RS422接口、优缺点、针脚定义介绍,所用集成的介绍与其相关电路,验证串口好坏与波特率实测,STM32的URAT与单片机串口调试的几个小招数等。紫色文字是超链接,点击自动跳转至相关博文。持续更新,原创不易! 一、RS232、RS485与RS422介绍 1、关于RS4

    2024年02月04日
    浏览(53)
  • FPGA 串口通信(uart)初探篇(含源代码)

    一、UART 串口通信,说实话是日常生活中很常见的一种9针型的主机和显示屏之间的通信模式。本次博客,只为自己复盘相关知识,初学者,错误较多,请多指教。所以本文参考(一)FPGA之串口通信(UART)_fpga uart-CSDN博客 而编著的。 FPGA是一种可编程的逻辑器件,用于各种数字电

    2024年04月14日
    浏览(34)
  • (五)零基础学懂FPGA中的串口通信(UART)

    此篇为专栏 《FPGA学习笔记》 的第五篇,记录我的学习FPGA的一些开发过程和心得感悟,刚接触FPGA的朋友们可以先去此专栏置顶 《FPGA零基础入门学习路线》来做最基础的扫盲。 本篇内容基于笔者实际开发过程和正点原子资料撰写,将会详细讲解此FPGA实验的全流程, 诚挚 地

    2024年02月04日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包