赞
踩
UART广泛应用于微控制器和计算机之间的数据通信,如GPS模块、蓝牙模块、GSM模块等。UART是一种通用串行数据总线,用于异步通信,该总线双向通信,可以实现全双工传输和接收。 在嵌入式设计中,UART用于主机与辅助设备通信UART通常被集成于其他通讯接口的连结上。UART 通道有两条数据线:每个设备上都有一个 RX 引脚和一个 TX 引脚(RX 用于接收,TX 用于发送)每个设备的 RX 引脚都连接到另一个设备的 TX 引脚。
UART 是通用异步接收方发送方,没有时钟线。 异步通信以一个字符为传输单位:通信中两个字符之间的时间间隔不固定,但同一字符中两个相邻位之间的时间间隔是固定的。此时,需要在两个UART设备上指定相同的传输速率,以及空闲位、起始位、奇偶校验位和结束位,即遵循相同的协议。
在UART中,传输模式为数据包形式。连接发送器和接收器的机制包括串行数据包的创建和物理硬件线路的控制。数据包由起始位、数据帧、奇偶校验位和停止位组成。
当不传输数据时,UART数据传输线通常保持高电压电平。若要开始数据传输,发送UART会将传输线从高电平拉到低电平并保持1个时钟周期。当接收UART检测到高到低电压跃迁时,便开始以波特率对应的频率读取数据帧中的位。
数据帧包含所传输的实际数据。如果使用奇偶校验位,数据帧长度可以是5位到8位。如果不使用奇偶校验位,数据帧长度可以是9位。在大多数情况下,数据以最低有效位优先方式发送。
奇偶性描述数字是偶数还是奇数。通过奇偶校验位,接收UART判断传输期间是否有数据发生改变。电磁辐射、不一致的波特率或长距离数据传输都可能改变数据位。
接收UART读取数据帧后,将计数值为1的位,检查总数是偶数还是奇数。如果奇偶校验位为0(偶数奇偶校验),则数据帧中的1或逻辑高位总计应为偶数。如果奇偶校验位为1(奇数奇偶校验),则数据帧中的1或逻辑高位总计应为奇数。当奇偶校验位与数据匹配时,UART认为传输未出错。但是,如果奇偶校验位为0,而总和为奇数,或者奇偶校验位为1,而总和为偶数,则UART认为数据帧中的位已改变。
为了表示数据包结束,发送UART将数据传输线从低电压驱动到高电压并保持1到2位时间。
module UART_SRX(Clk,Rst,Rxd,RxRdy,RxErr,Do); input Clk, input Rst; input Rxd; output[7:0]Do; output RxRdy,RxErr; reg [13:0] count; reg [2:0] state; reg [7:0] Do; reg [23:0] data_sam; reg [1:0] RX_BIT_COUNT; reg [2:0] RX_START_COUNT; reg [5:0] RX_REC_COUNT; reg Clk_SAM; reg RxRdy; reg RxErr; reg Rxd_pr; parameter RX_IDLE = 3'b000, //状态机实现 RX_START = 3'b001, RX_REC = 3'b010, RX_STOP = 3'b011, RX_DO = 3'b100; //parameter define parameter CLK_FREQ = 24576000; //系统时钟频率 parameter UART_BPS = 300; //串口波特率 localparam BoundCnt = CLK_FREQ/UART_BPS/6-1; //Fo = Bound*3 = 0.5*Fs/BoundCnt always@(posedge Clk or posedge Rst)begin if(Rst)begin count <= 14'h0; end else begin if(count == BoundCnt)begin //波特率计数时钟 count <= 14'h0; Clk_SAM <= ~Clk_SAM; end else begin count <= count + 14'h1; end end end always @(posedge Clk_SAM or posedge Rst) begin if(Rst) begin Do <= 8'hff; RxRdy <= 1'b0; RxErr <= 1'b0; RX_START_COUNT <= 2'h0; RX_REC_COUNT <= 5'h0; data_sam[23:0]<= 24'b0; state <= RX_IDLE; end else begin case(state) RX_IDLE:begin //接收初始化 RxRdy <= 1'b0; RxErr <= 1'b0; RX_START_COUNT <= 2'h0; RX_REC_COUNT <= 5'h0; if(Rxd == 0)begin state <= RX_START; end end RX_START:begin //接收起始位 Rxd_pr <= Rxd; if(!(Rxd && Rxd_pr))begin RX_START_COUNT <= RX_START_COUNT + 2'h1; if(RX_START_COUNT == 1)begin //校验是否开启 RX_START_COUNT <= 2'h0; state <= RX_REC; end else begin state <= RX_START; end end else begin state <= RX_IDLE; end end RX_REC:begin //校验起始 data_sam[RX_REC_COUNT] <= Rxd; RX_REC_COUNT <= RX_REC_COUNT + 5'h1; if(RX_REC_COUNT == 23) begin state <= RX_STOP; end end RX_STOP:begin Do[0] <= ((data_sam[0]+data_sam[1]+data_sam[2])>1)?1'b1:1'b0; Do[1] <= ((data_sam[3]+data_sam[4]+data_sam[5])>1)?1'b1:1'b0; Do[2] <= ((data_sam[6]+data_sam[7]+data_sam[8])>1)?1'b1:1'b0; Do[3] <= ((data_sam[9]+data_sam[10]+data_sam[11])>1)?1'b1:1'b0; Do[4] <= ((data_sam[12]+data_sam[13]+data_sam[14])>1)?1'b1:1'b0; Do[5] <= ((data_sam[15]+data_sam[16]+data_sam[17])>1)?1'b1:1'b0; Do[6] <= ((data_sam[18]+data_sam[19]+data_sam[20])>1)?1'b1:1'b0; Do[7] <= ((data_sam[21]+data_sam[22]+data_sam[23])>1)?1'b1:1'b0; state <= RX_DO; RxErr <= !Rxd; end RX_DO:begin RxRdy <= 1'b1; state <= RX_IDLE; end endcase end end endmodule
module UART_TX( input CLK , //系统时钟 input RST_n , //系统复位,低有效 input TX_EN , //UART的发送使能 input [7:0] TX_DATA, //UART要发送的数据 output reg TXD , //UART发送端口 output reg TX_BUSY //发送忙状态信号 ); //parameter define parameter CLK_FREQ = 50000000; //系统时钟频率 parameter UART_BPS = 115200 ; //串口波特率 localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数BPS_CNT次 //reg define reg [7:0] tx_data_t; //发送数据寄存器 reg [3:0] tx_cnt ; //发送数据计数器 reg [15:0] baud_cnt ; //波特率计数器 //当TX_EN为高时,寄存输入的并行数据,并拉高BUSY信号 always @(posedge CLK or negedge RST_n) begin if(!RST_n) begin tx_data_t <= 8'b0; TX_BUSY <= 1'b0; end //发送使能时,寄存要发送的数据,并拉高BUSY信号 else if(TX_EN) begin tx_data_t <= TX_DATA; TX_BUSY <= 1'b1; end //当计数到停止位结束时,停止发送过程 else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - BAUD_CNT_MAX/16) begin tx_data_t <= 8'b0; //清空发送数据寄存器 TX_BUSY <= 1'b0; //并拉低BUSY信号 end else begin tx_data_t <= tx_data_t; TX_BUSY <= TX_BUSY; end end //波特率的计数器赋值 always @(posedge CLK or negedge RST_n) begin if(!RST_n) baud_cnt <= 16'd0; //当处于发送过程时,波特率计数器(baud_cnt)进行循环计数 else if(TX_BUSY) begin if(baud_cnt < BAUD_CNT_MAX - 1'b1) baud_cnt <= baud_cnt + 16'b1; else baud_cnt <= 16'd0; //计数达到一个波特率周期后清零 end else baud_cnt <= 16'd0; //发送过程结束时计数器清零 end //tx_cnt进行赋值 always @(posedge CLK or negedge RST_n) begin if(!RST_n) tx_cnt <= 4'd0; else if(TX_BUSY) begin //处于发送过程时tx_cnt才进行计数 if(baud_cnt == BAUD_CNT_MAX - 1'b1) //当波特率计数器计数到一个波特率周期时 tx_cnt <= tx_cnt + 1'b1; //发送数据计数器加1 else tx_cnt <= tx_cnt; end else tx_cnt <= 4'd0; //发送过程结束时计数器清零 end //根据tx_cnt来给uart发送端口赋值 always @(posedge CLK or negedge RST_n) begin if(!RST_n) TXD <= 1'b1; else if(TX_BUSY) begin case(tx_cnt) 4'd0 : TXD <= 1'b0 ; //起始位 4'd1 : TXD <= tx_data_t[0]; //数据位最低位 4'd2 : TXD <= tx_data_t[1]; 4'd3 : TXD <= tx_data_t[2]; 4'd4 : TXD <= tx_data_t[3]; 4'd5 : TXD <= tx_data_t[4]; 4'd6 : TXD <= tx_data_t[5]; 4'd7 : TXD <= tx_data_t[6]; 4'd8 : TXD <= tx_data_t[7]; //数据位最高位 4'd9 : TXD <= 1'b1 ; //停止位 default : TXD <= 1'b1; endcase end else TXD <= 1'b1; //空闲时发送端口为高电平 end endmodule
USART 通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)
STM32内部的USART控制器学习
USART是一种扩展了UART功能的通信接口,它不仅支持异步通信(如UART),还支持同步通信模式。USART可以在同一硬件上实现两种不同的通信方式,提供了更大的灵活性,广泛应用于需要稳定和高速数据传输的场合。
- 异步模式通信过程
起始位:发送端发送一个低电平信号,通知接收端即将传输数据。
数据位:发送端按预定的波特率逐位发送数据,接收端根据相同波特率接收数据。
校验位:可选,用于检测数据传输中的错误。
停止位:发送端发送一个高电平信号,表示数据传输结束。
- 同步模式通信过程
时钟信号:发送端发送时钟信号,接收端根据时钟信号的边缘(上升沿或下降沿)同步接收数据。
数据位:每个数据位在时钟信号的一个边缘发送或接收。
帧格式:可以根据应用需求配置起始位、数据位、校验位和停止位。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。