首页 > 编程知识 正文

单片机和fpga串口通信实验代码,uart串口通信原理

时间:2023-05-05 07:37:54 阅读:51082 作者:2363

提示:写完文章后,目录可以自动生成。 如何生成可以引用右侧的帮助文档

文章目录序言一、UART串口是什么? 二.串行收发1 .串行收发2 .串行发送

前言:学习stm32的时候,大家一定很少使用UART串行端口。 32标准库开发中,只需站在巨人的肩膀上轻松配置串行端口,即可开始使用。 在FPGA上怎么写串行端口?

提示:以下为本文正文内容,以下案例可供参考

一、UART串行端口是什么? 通用同步接收器/传输器(UART )是异步发送和接收发送器。 发送的数据在串行通信和并行通信之间转换,发送时将并行数据转换为串行数据发送,接收时将串行数据转换为并行数据。 UART串行通信是全双工通信。 虽然是异步传输,但为了保证通信的可靠性,规定了传输速度(波特率)、数据位数和停止位。

二、串行收发1 .串行收发代码如下:

moduleuart_rx_path(inputclk_I,input uart_rx_i,output [7:0] uart_rx_data_o,ou output _ art _ t ) //波特率表,9600bps,100 MHz/9600=10416 parameter [ 13:0 ] baud _ div _ cap=14 ' d 5208; //肖像时钟的中间采样点,100 MHz/9600/2=5208 reg [ 13:0 ] baud _ div=0; //波特率设定计数器reg baud_bps=0; //数据采样点信号reg bps_start=0; //波特率启动标志always@(posedgeclk_I ) beginif ) baud_div==baud_div_cap ) /波特率计数器计数到采样点时endelse if (baud _ div baud _ div bps _ start ) /波特率计数器启动后,计数器将返回beginbaud_div=baud_div1'B1; baud_bps=0; endelsebeginbaud_bps=0; baud_div=0; endend reg [ 4:0 ] UART _ rx _ I _ r=5' b 1111; //数据接收缓冲器always @ [ posedge clk _ I ] begin UART _ rx _ I _ r={ UART _ rx _ I _ r [ :0 ],uart_rx_i}; 当连续接收5个低电平时,即uart_rx_int=0时,接收开始信号wire UART _ rx _ int=UART _ rx _ I _ r [4] //接收数据数计数器reg uart_rx_done_r=0; //数据接收完成寄存器reg state=1'b0; reg [ 7:0 ] UART _ rx _ data _ o _ r0=0; //正在接收数据时,数据缓冲器reg [ 7:0 ] UART _ rx _ data _ o _ R1=0; //数据接收完成,数据寄存器always@(posedge clk_i ) beginuart_rx_done_r=1'b0; case(state )1)1'b0 : if (! UART_rx_int(/如果连续接收到5个低电平,即uart_rx_int=0,则启动波特率时钟begin bps _ start=1’B1作为接收开始信号; 状态=1' B1; 每次等待end1'B1:if(baud_bps ) /波特率采样中心时,接收数据并将其放入数据缓冲区的beginbit_num=bit_num 1'b1; if(bit_num4) D9 ) /接收1bit开始信号、8bit有效信号、1bit结束信号UART _ rx _ data _ o _ r0 [ bit _ num-1 ]=UART _ rx _ I; endelseif(bit_num==4'd10 ) /接收完成时,清除接收数据个数计数器,生成接收完成标志位,将数据写入数据寄存器,关闭波特率时uart_rx_done_r=1'b1; URT _ rx _ data _ o _ R1=UART _ rx _ data _ o _ r0; state=1'b0; 进入//状态0,再次循环检测bps_start=0; enddefault: endcaseendassignbaud _ bps _ TB=baud _ bps; //forsimulationassignuart _ rx _ data _ o=UART _ rx _ data _ o _ R1; assign UART _ rx _ done=UART _ rx _ done _ r; 结束模块波特率的部分是固定波特率9600,即

是1秒发送9600个数据,每个数据所用时间是1/9600秒,输入时钟周期是1/100M秒,则计数器要计100M/9600个数。
波特率计数器从起始信号开始计数从0记到BAUD_DIV,然后置0,在中间时刻对数据进行采集。也就是起始信号开始计数从0记到BAUD_DIV,只接受一位数据

always@(posedge clk_i)beginif(baud_div==BAUD_DIV_CAP)//当波特率计数器计数到采样点时,产生采样信号baud_bpsbeginbaud_bps<=1'b1;baud_div<=baud_div+1'b1;endelse if(baud_div<BAUD_DIV && bps_start)//当波特率计数器启动时,计数器累加beginbaud_div<=baud_div+1'b1;baud_bps<=0;endelsebeginbaud_bps<=0;baud_div<=0;endend

串口接受代码
开始接受:当连续接收到五个低电平时即uart_rx_int=0,同时启动波特率计 数器开始计数
每当计数器记计到中值,接收数据,并将其存入数据缓冲寄存器中,当数据接受完,数据缓冲寄存器赋值于数据寄存器,并关闭波特率寄存器,为下次接受数据做准备

reg [4:0] uart_rx_i_r=5'b11111;//数据接收缓存器always@(posedge clk_i)beginuart_rx_i_r<={uart_rx_i_r[3:0],uart_rx_i};end//数据接收缓存器,当连续接收到五个低电平时,即uart_rx_int=0时,作为接收到起始信号:当连续接收到五个低电平时即wire uart_rx_int=uart_rx_i_r[4] | uart_rx_i_r[3] | uart_rx_i_r[2] | uart_rx_i_r[1] | uart_rx_i_r[0];reg [3:0] bit_num=0;//接收数据个数计数器reg uart_rx_done_r=0;//数据接收完成寄存器reg state=1'b0;reg [7:0] uart_rx_data_o_r0=0;//数据接收过程中,数据缓存器reg [7:0] uart_rx_data_o_r1=0;//数据接收完成,数据寄存器always@(posedge clk_i)beginuart_rx_done_r<=1'b0;case(state)1'b0 : if(!uart_rx_int)//当连续接收到五个低电平时,即uart_rx_int=0时,作为接收到起始信号,启动波特率时钟beginbps_start<=1'b1;state<=1'b1;end1'b1 :if(baud_bps)//每次等待波特率采样中心时,接收数据,放入数据缓存器中beginbit_num<=bit_num+1'b1;if(bit_num<4'd9)//接收1bit起始信号,8bit有效信号,1bit结束信号uart_rx_data_o_r0[bit_num-1]<=uart_rx_i;endelse if(bit_num==4'd10) //接收完成时候,接收数据个数计数器清零,产生接收完成标志位,并将数据写入数据寄存器,关闭波特率时候beginbit_num<=0;uart_rx_done_r<=1'b1;uart_rx_data_o_r1<=uart_rx_data_o_r0;state<=1'b0;//进入状态0,再次循环检测bps_start<=0;enddefault:;endcaseendassign baud_bps_tb=baud_bps;//for simulationassign uart_rx_data_o=uart_rx_data_o_r1;assign uart_rx_done=uart_rx_done_r; 2.串口发

代码如下(示例):

module uart_tx_path(input clk_i,input [7:0] uart_tx_data_i,//待发送数据input uart_tx_en_i,//发送发送使能信号output uart_tx_o);parameter BAUD_DIV = 14'd10416;//波特率时钟,9600bps,100Mhz/9600=10416,波特率可调parameter BAUD_DIV_CAP = 14'd5208;//波特率时钟中间采样点,100Mhz/9600/2=5208,波特率可调reg [13:0] baud_div=0;//波特率设置计数器reg baud_bps=0;//数据发送点信号,高有效reg [9:0] send_data=10'b1111111111;//待发送数据寄存器,1bit起始信号+8bit有效信号+1bit结束信号reg [3:0] bit_num=0;//发送数据个数计数器reg uart_send_flag=0;//数据发送标志位reg uart_tx_o_r=1;//发送数据寄存器,初始状态位高always@(posedge clk_i)beginif(baud_div==BAUD_DIV_CAP)//当波特率计数器计数到数据发送中点时,产生采样信号baud_bps,用来发送数据beginbaud_bps<=1'b1;baud_div<=baud_div+1'b1;endelse if(baud_div<BAUD_DIV && uart_send_flag)//数据发送标志位有效期间,波特率计数器累加,以产生波特率时钟beginbaud_div<=baud_div+1'b1;baud_bps<=0;endelsebeginbaud_bps<=0;baud_div<=0;endendalways@(posedge clk_i)beginif(uart_tx_en_i)//接收数据发送使能信号时,产生数据发送标志信号beginuart_send_flag<=1'b1;send_data<={1'b1,uart_tx_data_i,1'b0};//待发送数据寄存器装填,1bit起始信号0+8bit有效信号+1bit结束信号endelse if(bit_num==4'd10)//发送结束时候,清楚发送标志信号,并清楚待发送数据寄存器内部信号beginuart_send_flag<=1'b0;send_data<=10'b1111_1111_11;endendalways@(posedge clk_i)beginif(uart_send_flag)//发送有效时候beginif(baud_bps)//检测发送点信号beginif(bit_num<=4'd9)beginuart_tx_o_r<=send_data[bit_num];//发送待发送寄存器内数据,从低位到高位bit_num<=bit_num+1'b1;endendelse if(bit_num==4'd10)bit_num<=4'd0;endelsebeginuart_tx_o_r<=1'b1;//空闲状态时,保持发送端位高电平,以备发送时候产生低电平信号bit_num<=0;endendassign uart_tx_o=uart_tx_o_r;endmodule

波特率部分与接受相似

串口发送部分
将数据转换成:起始位+数据+停止位
然后再一位一位传输出去

always@(posedge clk_i)beginif(uart_tx_en_i)//接收数据发送使能信号时,产生数据发送标志信号beginuart_send_flag<=1'b1;send_data<={1'b1,uart_tx_data_i,1'b0};//待发送数据寄存器装填,1bit起始信号0+8bit有效信号+1bit结束信号endelse if(bit_num==4'd10)//发送结束时候,清楚发送标志信号,并清楚待发送数据寄存器内部信号beginuart_send_flag<=1'b0;send_data<=10'b1111_1111_11;endendalways@(posedge clk_i)beginif(uart_send_flag)//发送有效时候beginif(baud_bps)//检测发送点信号beginif(bit_num<=4'd9)beginuart_tx_o_r<=send_data[bit_num];//发送待发送寄存器内数据,从低位到高位bit_num<=bit_num+1'b1;endendelse if(bit_num==4'd10)bit_num<=4'd0;endelsebeginuart_tx_o_r<=1'b1;//空闲状态时,保持发送端位高电平,以备发送时候产生低电平信号bit_num<=0;endendassign uart_tx_o=uart_tx_o_r;
## 顶层模块 实现效果:将接受的数据再发发送出去 ```c module uart_top( input clk_i, input rst_n_i, input uart_rx_i,output uart_tx_o);

wire [7:0] uart_rx_data_o;
wire uart_rx_done;

uart_rx_path uart_rx_path_u (
.clk_i(clk_i),
.uart_rx_i(uart_rx_i),

.uart_rx_data_o(uart_rx_data_o), .uart_rx_done(uart_rx_done));

uart_tx_path uart_tx_path_u (
.clk_i(clk_i),
.uart_tx_data_i(uart_rx_data_o),
.uart_tx_en_i(uart_rx_done),
.uart_tx_o(uart_tx_o)
);

endmodule

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