首页 > 编程语言 >[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-26 RS485串口程序收发环路设计

[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-26 RS485串口程序收发环路设计

时间:2024-07-31 19:29:54浏览次数:24  
标签:26 rs485 tx FPGA uart RS485 发送 安路 串口

软件版本:Anlogic -TD5.9.1-DR1_ES1.1

操作系统:WIN10 64bit

硬件平台:适用安路(Anlogic)FPGA

实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板

板卡获取平台:https://milianke.tmall.com/

登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

 

1概述

在前面的课程中,我们已经学习了UART串口程序的设计,在工业场合为了提高串口的抗干扰能力,以及传输距离,RS485/RS422会更加广泛应用。在本文的实验中我们通过调用前面已经编写好的UART收发IP模块,以及FIFO,实现RS485的单工通信测试。其中重点是关于RS485芯片在单工通信方式下的信号控制逻辑设计。

2 RS485硬件电路设计

2.1 RS485驱动芯片介绍

SP3485 器件是一款3.3V 低功耗半双工收发器,符合RS-485 和RS-422 串行协议的规范。SP3485 可以满足RS-485 和RS-422 串行协议的电气规范,负载下最高10Mbps。

PIN

功能

功能描述

1

RO

数据接收输出

2

RE

接收输出使能,低电平有效

3

DE

输出使能,高电平有效

4

DI

数据发送输入

5

GND

6

A

同相驱动器输出/接收器输入

7

B

反相驱动器输出/接收器输入

8

VCC

供电

2.2 RS485的应用电路设计

 

发送真值表:

INPUTS

OUTPUTS

RE

DE

DI

B

A

X

1

1

0

1

X

1

0

1

0

0

0

X

High-Z

1

0

X

关闭

可以看到,结合原理图设计:

当DE是高电平,RE是任何值,DI决定了A B的输出电平;

当DE和RE都是0,AB 输出为高阻,这个时候,RO可以作为输入

接收真值表:

INPUTS

OUTPUTS

RE

DE

Va~Vb

RO

0

X

-50mv

1

0

X

-200mv

0

X

X

Open/Shorted

1

1

1

X

High-Z

1

0

X

关闭

当DE是0,DE为任意值,RO输入有效:

当Va~Vb的差模电压>-50mv RO输出1;

当Va~Vb的差模电压<-200mv RO输出0

2.3 瞬态抑制器的使用

对于工业场合的工作环境,SMBJ6.0瞬态抑制器,可以抑制RS485总线的浪涌,过压,对RS485芯片起到保护作用。

3 RS485的收发环路

3.1系统框图

RS485采用的通信协议依然是UART串口协议,因此收发模块还是使用前面已经写好的UART收发IP模块。为了实现单工模式的环路测试功能,这里增加了1个FIFO以及1个收发模块控制器。默认情况下,RS485芯片工作于接收数据状态,当FIFO有数据,并且一段时间内没有新数据到达,控制器切换RS485芯片到发送状态,从FIFO中取出缓存的数据发出。

3.2顶层模块源码

以下代码中核心部分为如何实现RS485数据方向的切换,以及数据到FIFO的缓存。

 

  1 /*************RS485 半双工测试*************
  2 --使用到了UART 发送和接收驱动
  3 --通过FIFO缓存数据,并且检测到接收总线一段时间没有时间达到,进入发送模式,发送之前接收到的数据。
  4 *********************************************************************/
  5 
  6 `timescale 1ns / 1ns //仿真时间刻度/精度
  7 
  8 module rs485_top#
  9 (
 10 parameter integer SYSCLKHZ =  25_000_000  //系统输入时钟频率参数
 11 )
 12 (
 13 input       I_sysclk,//系统时钟输入
 14 output      O_rs485_de, // 485 de控制,控制输入 输出方向,0 输入 1输出
 15 input       I_rs485_rx, // 485 RX输入总线
 16 output      O_rs485_tx  // 485 TX输出总线
 17 );
 18 
 19 wire        reset_n;  //内部上电延迟复位
 20 wire        rs485_rx; //内部RX 接收 
 21 wire        rs485_fifo_empty;  //FIFO空
 22 wire        rs485_fifo_rd_en;  //FIFO 读使能
 23 wire        rs485_rvalid;      //读数据有效
 24 wire [7:0]  rs485_rdata;       //串口读数据(接收)
 25 wire [7:0]  rs485_wdata;       //串口写数据(发送)
 26 wire        rs485_wbusy;       //写忙
 27 reg         rs485_de;          //485芯片的DE控制0 输入 1输出
 28 reg         rs485_wreq = 1'b0; //串口写请求
 29 wire        rs485_tx_start;    //发送启动
 30 reg         rs485_tx_start_r = 1'b0; //发送启动寄存
 31 reg [17:0]  T_dcnt; //延迟计数器
 32 reg [11:0]  rstn_cnt = 12'd0; //复位计数器
 33 
 34 //当rs485_de=0,设置rs485内部逻辑准备接收总线数据
 35 assign rs485_rx         = (rs485_de == 1'b0) ? I_rs485_rx : 1'b1;
 36 //当FIFO中有数据,并且串口发送不忙,启动发送
 37 assign rs485_tx_start   = rs485_de&&(rs485_wbusy == 1'b0)&&(!rs485_fifo_empty);
 38 //读FIFO使能,用rs485_tx_start的上升沿触发读FIFO
 39 assign rs485_fifo_rd_en = (rs485_tx_start_r == 1'b0 & rs485_tx_start == 1'b1);//read fifo enable
 40 //当rs485_de=0,设置rs485内部逻辑准备接收总线数据,否则,可以发送数据
 41 assign O_rs485_de       = rs485_de; 
 42 
 43 assign reset_n = rstn_cnt[11];//上电延迟复位
 44 
 45 //复位计数器
 46 always @(posedge I_sysclk)begin
 47     if(rstn_cnt[11] == 1'b0)
 48         rstn_cnt <= rstn_cnt + 1'b1;
 49     else 
 50         rstn_cnt <= rstn_cnt;
 51 end
 52 
 53 //T_dcnt用于一段时间内,判断接收总线是否空闲
 54 always @(posedge I_sysclk or negedge reset_n)begin
 55    if(reset_n == 1'b0)
 56        T_dcnt <= 17'd0; 
 57    else if(rs485_rx && (!rs485_fifo_empty))//如果RX总线是高电平,并且FIFO非空(有数据)
 58        T_dcnt <= (T_dcnt[17] == 1'b1) ? T_dcnt : T_dcnt + 1'b1; //计数器累加
 59    else 
 60        T_dcnt <= 0; //否则重置归零
 61 
 62 end
 63 
 64 //当rs485_de=0,设置rs485内部逻辑准备接收总线数据,否则,可以发送数据
 65 always @(posedge I_sysclk )begin
 66     if(reset_n ==1'b0)//if(rs485_de | reset_n ==1'b0)
 67        rs485_de <= 1'b0;//重置rs485_de,切换到接收
 68     else if((T_dcnt[17]==1'b1)|rs485_wreq|rs485_wbusy)//当T_dcnt延迟计数器到达计数值,或者串口发送控制器正在发送(rs485_wreq,rs485_wbusy有效)
 69        rs485_de <= 1'b1;//设置rs485_de
 70      else
 71      rs485_de <= 1'b0;//设置rs485_de
 72 end
 73 
 74 //打拍寄存一次
 75 always @(posedge I_sysclk) rs485_tx_start_r <= rs485_tx_start;
 76 
 77 //rs485_wreq,延迟于rs485_fifo_rd_en,1个时钟,用于数据同步
 78 always @(posedge I_sysclk) rs485_wreq <= rs485_fifo_rd_en;
 79 
 80 //例化FIFO IP,FIFO设置标准模式,用户缓存接收到的帧
 81 fifo_generator_0 inst_fifo (
 82   .clkw(I_sysclk),          //写时钟输入
 83   .wrst(reset_n == 1'b0),   //写复位
 84   .clkr(I_sysclk_p),          //读时钟输入
 85   .rrst(reset_n == 1'b0),   //读复位
 86   .di(rs485_rdata),          //RX接收到的数据
 87   .we(rs485_rvalid&(rs485_de==1'b0)), // 写FIFO 使能,当rs485_rvalid有效,写入数据
 88   .re(rs485_fifo_rd_en),   //FIFO读使能
 89   .dout(rs485_wdata),         //写数据
 90   .empty_flag(rs485_fifo_empty)    //FIFO 空
 91 
 92 ); 
 93 
 94 //例化串口发送模块
 95 uiuart_tx#
 96 (
 97 .BAUD_DIV(SYSCLKHZ/115200 -1)  //设置波特率  
 98 )
 99 uiuart_tx_u 
100 (
101 .I_clk(I_sysclk),           //系统时钟
102 .I_uart_rstn(reset_n),      //系统复位
103 .I_uart_wreq(rs485_wreq),   //串口发送驱动器发送请求
104 .I_uart_wdata(rs485_wdata), //串口发送,数据
105 .O_uart_wbusy(rs485_wbusy), //串口发送总线忙
106 .O_uart_tx(O_rs485_tx)      //串口发送总线
107 );
108 
109 //例化串口接收模块
110 uiuart_rx#
111 (
112 .BAUD_DIV(SYSCLKHZ/115200 -1) //设置波特率      
113 )
114 uiuart_rx_u 
115 (
116 .I_clk(I_sysclk),           //系统时钟
117 .I_uart_rx_rstn(reset_n),   //系统复位
118 .I_uart_rx(rs485_rx),       //串口接收总线
119 .O_uart_rdata(rs485_rdata), //串口接收数据
120 .O_uart_rvalid(rs485_rvalid)//串口接收数据有效
121 );   
122 
123 endmodule

 

 

4 FPGA工程

关于软件安装、FPGA工程创建、编译、下载等请参考"米联客2023版FPGA课程-安路FPGA TD软件快速入门课程.pdf",该章节路径如下:

打开配套代码的FPGA工程如下:

米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹

01_rtl:放用户编写的rtl代码

02_sim:仿真文件或者工程

03_ip:放使用到的ip文件

04_pin:放fpga的pin脚约束文件或者时序约束文件

05_boot:放编译好的bit或者bin文件(一般为空)

06_doc:放本一些相关文档(一般为空)

5 RTL仿真

5.1仿真测试文件

 

 1 `timescale 1ns/1ns  //定义仿真时间刻度/精度
 2 
 3 module sim_top_tb();
 4  
 5 localparam     BPS       = 'd115200          ;                //波特率
 6 localparam     CLK_FRE    = 'd25_000_000     ;                //系统频率
 7 localparam     CLK_TIME   =  'd250_000_000 /CLK_FRE;          //计算系统时钟周期,以ns为单位
 8 localparam     BIT_TIME   = 'd250_000_000  / BPS ;            //计算出传输每个bit所需要的时间以ns为单位
 9 localparam     NUM_BYTES  = 3;                                //需要发送的BYTES
10 
11 reg              sysclk_p;                                    //系统时钟
12 reg              bsp_clk ;                                    //波特率时钟
13 reg              uart_tx;                                     //uart 数据发送,该信号接入到,FPGA的uart 接收
14 wire             uart_rx;                                      //uart 数据接收,该信号接入到,FPGA的uart 发送
15 wire             rs485_de;                                   
16 reg [8*NUM_BYTES-1:0] uart_send_data;                         //需要发送的数据
17 reg [7:0]            uart_send_data_r;                        //寄存每次需要发送的BYTE
18 
19 integer i,j;
20 
21 //例化顶层模块
22 rs485_top#
23 (
24 .SYSCLKHZ(CLK_FRE)     
25 )
26 rs485_top_inst
27 (
28 .I_sysclk(sysclk_p),
29 .O_rs485_de(rs485_de),
30 .I_rs485_rx(uart_tx),
31 .O_rs485_tx(uart_rx)
32 );
33 
34 //仿真初始化
35 initial begin  
36 
37 //初始化REG寄存器
38 sysclk_p =0;
39 bsp_clk  = 0;  
40 uart_tx  = 1;
41 i=0;
42 j=0;
43 
44 uart_send_data   =0;
45 uart_send_data_r =0;
46 
47 #20000;//延迟20000ns,等待uart测试代码中的复位延迟
48 
49 uart_send_data[(0*8) +: 8] = 8'b1001_0101;//初始化需要发送的第1个BYTE
50 uart_send_data[(1*8) +: 8] = 8'b0000_0101;//初始化需要发送的第2个BYTE
51 uart_send_data[(2*8) +: 8] = 8'b1000_0100;//初始化需要发送的第3个BYTE
52 
53 //uart tx 发送数据
54   for(i=0; i<NUM_BYTES;i=i+1)
55   begin
56 
57       uart_send_data_r = uart_send_data[(i*8) +: 8];//寄存需要发送的数据到寄存器
58       $display("uart_send_data : 0x%h",uart_send_data_r);//打印准备发送的数据
59 
60       @(posedge bsp_clk);  //发送起始位1bit
61       uart_tx = 1'b0;
62 
63       for(j=0;j<8;j=j+1)begin//发送数据8bits
64       @(posedge bsp_clk);  //发送
65       uart_tx = uart_send_data_r[j];
66       end
67 
68        @(posedge bsp_clk);//发送停止位1bit
69        uart_tx = 1'b1;  
70 
71   end
72        @(posedge bsp_clk); 
73        #200 $finish;               
74 end
75  
76 always #(CLK_TIME/2) sysclk_p = ~sysclk_p;     //产生主时钟
77 always #(BIT_TIME/2) bsp_clk  = ~bsp_clk;         //产生波特率时钟
78  
79 
80 endmodule

 

 

5.2仿真结果

6 实验演示

下载程序前,先确保FPGA工程已经编译。

6.1 硬件连接

请确保下载器和开发板已经正确连接,并且开发板已经上电(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)

我们使用的是板卡自带的RS485接口的RS485_0接口,为了方便我们测试,我们使用了RS485转USB的转接线与我们的电脑端相连接,方便我们的通信

6.2 实验结果

标签:26,rs485,tx,FPGA,uart,RS485,发送,安路,串口
From: https://www.cnblogs.com/milianke/p/18335293

相关文章

  • [米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-25 ADC模块FEP-DAQ9248采集显示波形方案
    软件版本:Anlogic-TD5.9.1-DR1_ES1.1操作系统:WIN1064bit硬件平台:适用安路(Anlogic)FPGA实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板板卡获取平台:https://milianke.tmall.com/登录"米联客"FPGA社区http://www.uisrc.com视频课程、答疑解惑! 1概述本方案通过把DAQ9......
  • [米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-23 RGB转HDMI显示方案
    软件版本:Anlogic-TD5.9.1-DR1_ES1.1操作系统:WIN1064bit硬件平台:适用安路(Anlogic)FPGA实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板板卡获取平台:https://milianke.tmall.com/登录"米联客"FPGA社区http://www.uisrc.com视频课程、答疑解惑! 1概述本实验通过FPGA内......
  • [米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-24 基于FPGA简易示波器显示驱动设计
    软件版本:Anlogic-TD5.9.1-DR1_ES1.1操作系统:WIN1064bit硬件平台:适用安路(Anlogic)FPGA实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板板卡获取平台:https://milianke.tmall.com/登录"米联客"FPGA社区http://www.uisrc.com视频课程、答疑解惑! 1概述FPGA在数据采集,数据处理......
  • [米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-22 TPG图像测试数据发生器设计
    软件版本:Anlogic-TD5.9.1-DR1_ES1.1操作系统:WIN1064bit硬件平台:适用安路(Anlogic)FPGA实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板板卡获取平台:https://milianke.tmall.com/登录"米联客"FPGA社区http://www.uisrc.com视频课程、答疑解惑! 1概述TPG(video_test_pa......
  • 0726_驱动2 io多路复用
    一、工作原理1.当一个app应用程序,如果像读取多个硬件中的数据,监听多个文件描述符,这时就要引入io多路服用机制2.使用select/poll/epoll监听多个文件描述符3.如果所有硬件数据(文件描述)没有准备好,进程进入休眠状态4.如果有一个或者多个硬件数据(文件描述符)准备好。唤醒休眠进......
  • [米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-21 VTC视频时序控制器设计
    软件版本:Anlogic-TD5.9.1-DR1_ES1.1操作系统:WIN1064bit硬件平台:适用安路(Anlogic)FPGA实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板板卡获取平台:https://milianke.tmall.com/登录"米联客"FPGA社区http://www.uisrc.com视频课程、答疑解惑! 1概述VideoTimingCont......
  • STM32F103+FreeRTOS的使用ESP8266与手机APP实现TCP连接通信控制
    前言本人初学FreeRTOS,来自不知名普通院校,大二物联网专业,简单看完百问网韦东山老师FreeRTOS就想随便找个小项目试试看,手头里没什么元器件,只有一块ESP8266wifi模块以及温湿度模块显示屏模块,所以用到的模块不多,这俩个模块可能不太适用于FreeRTOS,但主要目的想着以最少的资源练练......
  • 手把手教你玩转ESP8266(原理+驱动)
    在嵌入式开发中,无线通信的方式有很多,其中WIFI是绕不开的话题。说到WIFI通信,就不得不提ESP8266了。ESP8266是一款高性能的WIFI串口模块,实现透明传输。只要有一定的串口知识,不需要知道WIFI原理就可以上手,在业内应用广泛。1.源码下载STM32F103C8T6模板工程链接:https......
  • Leetcode每日一题 202040726 2740.找出分区值
    题目描述给你一个正整数数组nums。将nums分成两个数组:nums1和nums2,并满足下述条件:数组nums中的每个元素都属于数组nums1或数组nums2。两个数组都非空。分区值最小。分区值的计算方法是|max(nums1)-min(nums2)|。其中,max(nums1)表示数组nums1......
  • 视频汇聚EasyCVR平台H.265视频转码技术介绍、特点解析及应用
    随着社会视频资源的不断增加,城市“一网统管”等平台的视频应用也愈加频繁,视频转码并发成倍增加。但是很多城市现有的视频平台无法纳管更多的视频资源以及提供更多的视频转码并发能力。因此,为强化支撑“一网统管”平台开展视频类业务应用,需要对视频应用平台进行扩容及改造,满足海量......